Browse Source

Merge branch 'develop' into LL-1006-script

develop
Juan Cortés Ross 6 years ago
committed by GitHub
parent
commit
173b9931de
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .circleci/config.yml
  2. 15
      package.json
  3. 3
      src/analytics/segment.js
  4. 24
      src/bridge/LibcoreBridge.js
  5. 2
      src/commands/index.js
  6. 7
      src/commands/killInternalProcess.js
  7. 14
      src/commands/libcoreReset.js
  8. 2
      src/components/DashboardPage/index.js
  9. 5
      src/components/EnsureDeviceApp.js
  10. 10
      src/components/FeesField/BitcoinKind.js
  11. 12
      src/components/GenuineCheck.js
  12. 7
      src/components/ManagerPage/DeviceInfos.js
  13. 25
      src/components/ManagerPage/FirmwareUpdate.js
  14. 2
      src/components/ManagerPage/ManagerGenuineCheck.js
  15. 6
      src/components/Onboarding/index.js
  16. 6
      src/components/Onboarding/steps/Analytics.js
  17. 7
      src/components/Onboarding/steps/Finish.js
  18. 23
      src/components/Onboarding/steps/GenuineCheck/GenuineCheckErrorPage.js
  19. 7
      src/components/Onboarding/steps/GenuineCheck/GenuineCheckUnavailable.js
  20. 7
      src/components/Onboarding/steps/GenuineCheck/index.js
  21. 41
      src/components/Onboarding/steps/SelectDevice.js
  22. 82
      src/components/Onboarding/steps/SelectPIN/SelectPINRestoreNanoX.js
  23. 81
      src/components/Onboarding/steps/SelectPIN/SelectPINnanoX.js
  24. 24
      src/components/Onboarding/steps/SelectPIN/index.js
  25. 4
      src/components/Onboarding/steps/SetPassword.js
  26. 2
      src/components/Onboarding/steps/WriteSeed/WriteSeedRestore.js
  27. 8
      src/components/Onboarding/steps/WriteSeed/index.js
  28. 5
      src/components/SettingsPage/CleanButton.js
  29. 5
      src/components/SettingsPage/ResetButton.js
  30. 3
      src/components/Updater/UpdaterContext.js
  31. 3
      src/components/base/Modal/ConfirmModal.js
  32. 2
      src/config/urls.js
  33. 24
      src/helpers/reset.js
  34. 34
      src/icons/device/NanoX.js
  35. 30
      src/icons/device/NanoXBanner.js
  36. 1
      src/icons/device/index.js
  37. 12
      src/reducers/onboarding.js
  38. 4
      src/reducers/settings.js
  39. 11
      src/renderer/events.js
  40. 5
      src/types/common.js
  41. 32
      static/i18n/en/app.json
  42. 0
      static/images/ledger-nano-s-onb.svg
  43. 8
      static/images/ledger-nano-x-onb.svg
  44. BIN
      static/images/logos/connectDevice.png
  45. 33
      static/images/nano-x-error-onb.svg
  46. 24
      static/images/select-pin-nano-x-onb.svg
  47. 157
      yarn.lock

2
.circleci/config.yml

@ -10,7 +10,7 @@ jobs:
<<: *defaults
steps:
- run: sudo apt-get update
- run: sudo apt-get install -y libudev-dev
- run: sudo apt-get install -y libudev-dev libusb-1.0-0-dev
- run:
name: Install latest yarn
command: |

15
package.json

@ -35,13 +35,14 @@
}
},
"dependencies": {
"@ledgerhq/errors": "^4.35.1",
"@ledgerhq/hw-app-btc": "^4.35.0",
"@ledgerhq/hw-app-eth": "^4.35.0",
"@ledgerhq/hw-app-xrp": "^4.35.0",
"@ledgerhq/hw-transport": "^4.35.0",
"@ledgerhq/hw-transport-node-hid": "^4.35.0",
"@ledgerhq/ledger-core": "2.0.0-rc.16",
"@ledgerhq/devices": "^4.39.0",
"@ledgerhq/errors": "^4.39.0",
"@ledgerhq/hw-app-btc": "^4.39.0",
"@ledgerhq/hw-app-eth": "^4.39.0",
"@ledgerhq/hw-app-xrp": "^4.39.0",
"@ledgerhq/hw-transport": "^4.39.0",
"@ledgerhq/hw-transport-node-hid": "^4.40.0",
"@ledgerhq/ledger-core": "2.0.0-rc.21",
"@ledgerhq/live-common": "4.18.0",
"animated": "^0.2.2",
"async": "^2.6.1",

3
src/analytics/segment.js

@ -3,6 +3,7 @@
import uuid from 'uuid/v4'
import logger from 'logger'
import invariant from 'invariant'
import { getDeviceModel } from '@ledgerhq/devices'
import { getSystemLocale } from 'helpers/systemLocale'
import { langAndRegionSelector, shareAnalyticsSelector } from 'reducers/settings'
import { getCurrentDevice } from 'reducers/devices'
@ -34,7 +35,7 @@ const extraProperties = store => {
const systemLocale = getSystemLocale()
const device = getCurrentDevice(state)
const deviceInfo = device && {
productId: device.productId,
productId: getDeviceModel(device.modelId).usbProductId,
}
return {
appVersion: __APP_VERSION__,

24
src/bridge/LibcoreBridge.js

@ -103,17 +103,19 @@ const getFees = async (a, transaction) => {
const checkValidTransaction = (a, t) =>
!t.feePerByte
? Promise.reject(new FeeNotLoaded())
: !t.amount
? Promise.resolve(true)
: getFees(a, t)
.then(() => true)
.catch(e => {
if (e.code === NOT_ENOUGH_FUNDS) {
throw new NotEnoughBalance()
}
feesLRU.del(getFeesKey(a, t))
throw e
})
: t.feePerByte.eq(0)
? Promise.resolve(false)
: !t.amount
? Promise.resolve(true)
: getFees(a, t)
.then(() => true)
.catch(e => {
if (e.code === NOT_ENOUGH_FUNDS) {
throw new NotEnoughBalance()
}
feesLRU.del(getFeesKey(a, t))
throw e
})
const LibcoreBridge: WalletBridge<Transaction> = {
scanAccountsOnDevice(currency, devicePath) {

2
src/commands/index.js

@ -16,6 +16,7 @@ import installApp from 'commands/installApp'
import killInternalProcess from 'commands/killInternalProcess'
import libcoreGetFees from 'commands/libcoreGetFees'
import libcoreGetVersion from 'commands/libcoreGetVersion'
import libcoreReset from 'commands/libcoreReset'
import libcoreScanAccounts from 'commands/libcoreScanAccounts'
import libcoreScanFromXPUB from 'commands/libcoreScanFromXPUB'
import libcoreSignAndBroadcast from 'commands/libcoreSignAndBroadcast'
@ -44,6 +45,7 @@ const all: Array<Command<any, any>> = [
killInternalProcess,
libcoreGetFees,
libcoreGetVersion,
libcoreReset,
libcoreScanAccounts,
libcoreScanFromXPUB,
libcoreSignAndBroadcast,

7
src/commands/killInternalProcess.js

@ -1,10 +1,10 @@
// @flow
import { createCommand, Command } from 'helpers/ipc'
import { of } from 'rxjs'
import { never } from 'rxjs'
type Input = void
type Result = boolean
type Result = void
const cmd: Command<Input, Result> = createCommand('killInternalProcess', () => {
setTimeout(() => {
@ -12,7 +12,8 @@ const cmd: Command<Input, Result> = createCommand('killInternalProcess', () => {
// special exit code for better identification
process.exit(42)
})
return of(true)
// The command shouldn't finish now because process.exit will make it end!
return never()
})
export default cmd

14
src/commands/libcoreReset.js

@ -0,0 +1,14 @@
// @flow
import { createCommand, Command } from 'helpers/ipc'
import { from } from 'rxjs'
import withLibcore from 'helpers/withLibcore'
type Input = void
type Result = boolean
const cmd: Command<Input, Result> = createCommand('libcoreReset', () =>
from(withLibcore(core => core.getPoolInstance().freshResetAll())),
)
export default cmd

2
src/components/DashboardPage/index.js

@ -3,7 +3,7 @@
import React, { PureComponent, Fragment } from 'react'
import uniq from 'lodash/uniq'
import { compose } from 'redux'
import IconNanoX from 'icons/device/NanoX'
import IconNanoX from 'icons/device/NanoXBanner'
import { translate } from 'react-i18next'
import { connect } from 'react-redux'
import { push } from 'react-router-redux'

5
src/components/EnsureDeviceApp.js

@ -98,8 +98,11 @@ class EnsureDeviceApp extends Component<{
id: 'device',
title: (
<Trans i18nKey="deviceConnect.step1" parent="div">
{'Connect and unlock your '}
{'Connect your'}
<Bold>{'Ledger device'}</Bold>
{'to your computer and enter your'}
<Bold>{'PIN code'}</Bold>
{' on your device'}
</Trans>
),
icon: usbIcon,

10
src/components/FeesField/BitcoinKind.js

@ -8,7 +8,7 @@ import { translate } from 'react-i18next'
import type { T } from 'types/common'
import { FeeNotLoaded } from '@ledgerhq/errors'
import { FeeNotLoaded, FeeRequired } from '@ledgerhq/errors'
import InputCurrency from 'components/base/InputCurrency'
import Select from 'components/base/Select'
import type { Fees } from '@ledgerhq/live-common/lib/api/Fees'
@ -147,7 +147,13 @@ class FeesField extends Component<OwnProps, State> {
onChange={onChange}
onChangeFocus={this.onChangeFocus}
loading={!feePerByte && !error}
error={!feePerByte && error ? new FeeNotLoaded() : null}
error={
!feePerByte && error
? new FeeNotLoaded()
: feePerByte && feePerByte.isZero()
? new FeeRequired()
: null
}
renderRight={
<InputRight>{t('send.steps.amount.unitPerByte', { unit: satoshi.code })}</InputRight>
}

12
src/components/GenuineCheck.js

@ -146,7 +146,7 @@ class GenuineCheck extends PureComponent<Props> {
id: 'device',
title: (
<Trans i18nKey="deviceConnect.step1" parent="div">
{'Connect and unlock your '}
{'Connect and unlock your'}
<Bold>{'Ledger device'}</Bold>
</Trans>
),
@ -157,9 +157,9 @@ class GenuineCheck extends PureComponent<Props> {
id: 'deviceInfo',
title: (
<Trans i18nKey="deviceConnect.dashboard" parent="div">
{'Navigate to the '}
<Bold>{'dashboard'}</Bold>
{' on your device'}
{'Navigate to the'}
<Bold>{'Dashboard'}</Bold>
{'on your device'}
</Trans>
),
icon: homeIcon,
@ -169,9 +169,9 @@ class GenuineCheck extends PureComponent<Props> {
id: 'isGenuine',
title: (
<Trans i18nKey="deviceConnect.step3" parent="div">
{'Allow '}
{'Allow'}
<Bold>{'Ledger Manager'}</Bold>
{' on your device'}
{'on your device'}
</Trans>
),
icon: genuineCheckIcon,

7
src/components/ManagerPage/DeviceInfos.js

@ -5,7 +5,7 @@ import React, { PureComponent } from 'react'
import Text from 'components/base/Text'
import Box, { Card } from 'components/base/Box'
import Button from 'components/base/Button'
import { getDeviceModel } from '@ledgerhq/devices'
import type { Device, MemoryInfos } from 'types/common'
import MemInfos from './MemInfos'
@ -43,10 +43,11 @@ class DeviceInfos extends PureComponent<Props, State> {
return <Box py={5}>{'You dont have any device connected'}</Box>
}
const deviceInfos = getDeviceModel(device.modelId)
const title = (
<Text>
{device.manufacturer}
<Text ff="Museo Sans|Bold">{` ${device.product}`}</Text>
<Text ff="Museo Sans|Bold">{`${deviceInfos.productName}`}</Text>
</Text>
)
return (

25
src/components/ManagerPage/FirmwareUpdate.js

@ -3,10 +3,10 @@
import React, { PureComponent, Fragment } from 'react'
import { translate } from 'react-i18next'
import { getDeviceModel } from '@ledgerhq/devices'
import type { DeviceInfo, FirmwareUpdateContext } from '@ledgerhq/live-common/lib/types/manager'
import type { Device, T } from 'types/common'
import type { DeviceInfo, FirmwareUpdateContext } from '@ledgerhq/live-common/lib/types/manager'
import type { StepId } from 'components/modals/UpdateFirmware'
import getLatestFirmwareForDevice from 'commands/getLatestFirmwareForDevice'
@ -18,6 +18,7 @@ import Box, { Card } from 'components/base/Box'
import Text from 'components/base/Text'
import NanoS from 'icons/device/NanoS'
import NanoX from 'icons/device/NanoX'
import Blue from 'icons/device/Blue'
import CheckFull from 'icons/CheckFull'
@ -26,6 +27,17 @@ import UpdateFirmwareButton from './UpdateFirmwareButton'
export const getCleanVersion = (input: string): string =>
input.endsWith('-osu') ? input.replace('-osu', '') : input
const Icon = ({ type }: { type: string }) => {
switch (type) {
case 'blue':
return <Blue size={30} />
case 'nanoX':
return <NanoX size={30} />
default:
return <NanoS size={30} />
}
}
export type ModalStatus = 'closed' | 'disclaimer' | 'install' | 'error' | 'success'
type Props = {
@ -81,18 +93,19 @@ class FirmwareUpdate extends PureComponent<Props, State> {
render() {
const { deviceInfo, t, device } = this.props
const { firmware, modal, stepId, ready } = this.state
const deviceSpecs = getDeviceModel(device.modelId)
return (
<Card p={4}>
<Box horizontal align="center" flow={2}>
<Box color="dark">
{device.product === 'Blue' ? <Blue size={30} /> : <NanoS size={30} />}
<Icon type={deviceSpecs.id} />
</Box>
<Box>
<Box horizontal align="center">
<Text ff="Open Sans|SemiBold" fontSize={4} color="dark">
{device.product === 'Blue'
? t('manager.firmware.titleBlue')
: t('manager.firmware.titleNano')}
{deviceSpecs.productName}
</Text>
<Box color="wallet" ml={2}>
<Tooltip render={() => t('manager.yourDeviceIsGenuine')}>

2
src/components/ManagerPage/ManagerGenuineCheck.js

@ -28,7 +28,7 @@ class ManagerGenuineCheck extends PureComponent<Props> {
<img
src={i('logos/connectDevice.png')}
alt="connect your device"
style={{ marginBottom: 30, maxWidth: 362, width: '100%' }}
style={{ marginBottom: 30, maxWidth: 25, width: '100%' }}
/>
<Text ff="Museo Sans|Regular" fontSize={7} color="dark" style={{ marginBottom: 10 }}>
{t('manager.device.title')}

6
src/components/Onboarding/index.js

@ -19,7 +19,7 @@ import {
prevStep,
jumpStep,
updateGenuineCheck,
isLedgerNano,
deviceModelId,
flowType,
relaunchOnboarding,
onboardingRelaunchedSelector,
@ -102,7 +102,7 @@ export type StepProps = {
getDeviceInfo: Function,
updateGenuineCheck: Function,
openModal: Function,
isLedgerNano: Function,
deviceModelId: Function,
flowType: Function,
}
@ -171,7 +171,7 @@ class Onboarding extends PureComponent<Props> {
settings,
updateGenuineCheck,
openModal,
isLedgerNano,
deviceModelId,
flowType,
prevStep,
nextStep,

6
src/components/Onboarding/steps/Analytics.js

@ -3,6 +3,8 @@
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import { connect } from 'react-redux'
import { getDeviceModel } from '@ledgerhq/devices'
import { saveSettings } from 'actions/settings'
import Box from 'components/base/Box'
import Switch from 'components/base/Switch'
@ -67,13 +69,15 @@ class Analytics extends PureComponent<StepProps, State> {
const { nextStep, t, onboarding } = this.props
const { analyticsToggle, sentryLogsToggle } = this.state
const model = getDeviceModel(onboarding.deviceModelId)
return (
<FixedTopContainer>
<TrackPage
category="Onboarding"
name="Analytics"
flowType={onboarding.flowType}
deviceType={onboarding.isLedgerNano ? 'Nano S' : 'Blue'}
deviceType={model.productName}
/>
<StepContainerInner>
<Title data-e2e="onboarding_title">{t('onboarding.analytics.title')}</Title>

7
src/components/Onboarding/steps/Finish.js

@ -3,6 +3,8 @@
import React, { Component } from 'react'
import { openURL } from 'helpers/linking'
import styled from 'styled-components'
import { getDeviceModel } from '@ledgerhq/devices'
import { i } from 'helpers/staticPath'
import { urls } from 'config/urls'
@ -66,13 +68,16 @@ export default class Finish extends Component<StepProps, *> {
render() {
const { finish, t, onboarding } = this.props
const { emit } = this.state
const model = getDeviceModel(onboarding.deviceModelId)
return (
<Box sticky justifyContent="center">
<TrackPage
category="Onboarding"
name="Finish"
flowType={onboarding.flowType}
deviceType={onboarding.isLedgerNano ? 'Nano S' : 'Blue'}
deviceType={model.productName}
/>
<ConfettiLayer>
<ConfettiParty emit={emit} />

23
src/components/Onboarding/steps/GenuineCheck/GenuineCheckErrorPage.js

@ -11,9 +11,21 @@ import Box from 'components/base/Box'
import Button from 'components/base/Button'
import ExternalLinkButton from 'components/base/ExternalLinkButton'
import TrackPage from 'analytics/TrackPage'
import { getDeviceModel } from '@ledgerhq/devices'
import { Title, Description, OnboardingFooterWrapper } from '../../helperComponents'
const Img = ({ type }: { type: string }) => {
switch (type) {
case 'blue':
return <img alt="" src={i('blue-error-onb.svg')} />
case 'nanoX':
return <img alt="" src={i('nano-x-error-onb.svg')} />
default:
return <img alt="" src={i('nano-error-onb.svg')} />
}
}
type Props = {
t: T,
redoGenuineCheck: () => void,
@ -23,12 +35,15 @@ type Props = {
class GenuineCheckErrorPage extends PureComponent<Props, *> {
trackErrorPage = (page: string) => {
const { onboarding } = this.props
const model = getDeviceModel(onboarding.deviceModelId)
return (
<TrackPage
category="Onboarding"
name={`Genuine Check Error Page - ${page}`}
flowType={onboarding.flowType}
deviceType={onboarding.isLedgerNano ? 'Nano S' : 'Blue'}
deviceType={model.productName}
/>
)
}
@ -59,11 +74,7 @@ class GenuineCheckErrorPage extends PureComponent<Props, *> {
</Fragment>
)}
<Box mt={5} mr={7}>
{onboarding.isLedgerNano ? (
<img alt="" src={i('nano-error-onb.svg')} />
) : (
<img alt="" src={i('blue-error-onb.svg')} />
)}
<Img type={onboarding.deviceModelId} />
</Box>
</Fragment>
)

7
src/components/Onboarding/steps/GenuineCheck/GenuineCheckUnavailable.js

@ -1,8 +1,9 @@
// @flow
import React from 'react'
import { colors } from 'styles/theme'
import { getDeviceModel } from '@ledgerhq/devices'
import { colors } from 'styles/theme'
import type { T } from 'types/common'
import type { OnboardingState } from 'reducers/onboarding'
@ -54,6 +55,8 @@ export function GenuineCheckUnavailableMessage({
t: T,
onboarding: OnboardingState,
}) {
const model = getDeviceModel(onboarding.deviceModelId)
return (
<Box
horizontal
@ -76,7 +79,7 @@ export function GenuineCheckUnavailableMessage({
handleOpenGenuineCheckModal()
track('Genuine Check Retry', {
flowType: onboarding.flowType,
deviceType: onboarding.isLedgerNano ? 'Nano S' : 'Blue',
deviceType: model.productName,
})
}}
>

7
src/components/Onboarding/steps/GenuineCheck/index.js

@ -3,8 +3,9 @@
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import styled from 'styled-components'
import { colors } from 'styles/theme'
import { getDeviceModel } from '@ledgerhq/devices'
import { colors } from 'styles/theme'
import { updateGenuineCheck } from 'reducers/onboarding'
import Box from 'components/base/Box'
@ -165,13 +166,15 @@ class GenuineCheck extends PureComponent<StepProps, State> {
return this.renderGenuineFail()
}
const model = getDeviceModel(onboarding.deviceModelId)
return (
<FixedTopContainer>
<TrackPage
category="Onboarding"
name="Genuine Check"
flowType={onboarding.flowType}
deviceType={onboarding.isLedgerNano ? 'Nano S' : 'Blue'}
deviceType={model.productName}
/>
<StepContainerInner>
<Title>{t('onboarding.genuineCheck.title')}</Title>

41
src/components/Onboarding/steps/SelectDevice.js

@ -3,11 +3,14 @@
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import { connect } from 'react-redux'
import { getDeviceModel } from '@ledgerhq/devices'
import { i } from 'helpers/staticPath'
import { rgba } from 'styles/helpers'
import { isLedgerNano } from 'reducers/onboarding'
import { deviceModelId } from 'reducers/onboarding'
import type { DeviceModelId } from 'reducers/onboarding'
import Box from 'components/base/Box'
import TrackPage from 'analytics/TrackPage'
@ -19,11 +22,11 @@ import OnboardingFooter from '../OnboardingFooter'
import type { StepProps } from '..'
const mapDispatchToProps = { isLedgerNano }
const mapDispatchToProps = { deviceModelId }
class SelectDevice extends PureComponent<StepProps, {}> {
handleIsLedgerNano = (isLedgerNano: boolean) => {
this.props.isLedgerNano(isLedgerNano)
handleDeviceModelId = (deviceModelId: DeviceModelId) => {
this.props.deviceModelId(deviceModelId)
}
handleContinue = () => {
@ -46,24 +49,34 @@ class SelectDevice extends PureComponent<StepProps, {}> {
<Box pt={4}>
<Inner>
<DeviceContainer
isActive={onboarding.isLedgerNano}
onClick={() => this.handleIsLedgerNano(true)}
isActive={onboarding.deviceModelId === 'nanoX'}
onClick={() => this.handleDeviceModelId('nanoX')}
>
{onboarding.deviceModelId === 'nanoX' && <DeviceSelected />}
<DeviceIcon>
<img alt="" src={i('ledger-nano-x-onb.svg')} />
</DeviceIcon>
<BlockTitle>{getDeviceModel('nanoX').productName}</BlockTitle>
</DeviceContainer>
<DeviceContainer
isActive={onboarding.deviceModelId === 'nanoS'}
onClick={() => this.handleDeviceModelId('nanoS')}
>
{onboarding.isLedgerNano && <DeviceSelected />}
{onboarding.deviceModelId === 'nanoS' && <DeviceSelected />}
<DeviceIcon>
<img alt="" src={i('ledger-nano-onb.svg')} />
<img alt="" src={i('ledger-nano-s-onb.svg')} />
</DeviceIcon>
<BlockTitle>{t('onboarding.selectDevice.ledgerNanoCard.title')}</BlockTitle>
<BlockTitle>{getDeviceModel('nanoS').productName}</BlockTitle>
</DeviceContainer>
<DeviceContainer
isActive={!onboarding.isLedgerNano && onboarding.isLedgerNano !== null}
onClick={() => this.handleIsLedgerNano(false)}
isActive={onboarding.deviceModelId === 'blue'}
onClick={() => this.handleDeviceModelId('blue')}
>
{!onboarding.isLedgerNano && onboarding.isLedgerNano !== null && <DeviceSelected />}
{onboarding.deviceModelId === 'blue' && <DeviceSelected />}
<DeviceIcon>
<img alt="" src={i('ledger-blue-onb.svg')} />
</DeviceIcon>
<BlockTitle>{t('onboarding.selectDevice.ledgerBlueCard.title')}</BlockTitle>
<BlockTitle>{getDeviceModel('blue').productName}</BlockTitle>
</DeviceContainer>
</Inner>
</Box>
@ -73,7 +86,7 @@ class SelectDevice extends PureComponent<StepProps, {}> {
t={t}
nextStep={this.handleContinue}
prevStep={() => jumpStep('init')}
isContinueDisabled={onboarding.isLedgerNano === null}
isContinueDisabled={onboarding.deviceModelId === ''}
/>
</FixedTopContainer>
)

82
src/components/Onboarding/steps/SelectPIN/SelectPINRestoreNanoX.js

@ -0,0 +1,82 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import { colors } from 'styles/theme'
import { i } from 'helpers/staticPath'
import Box from 'components/base/Box'
import type { T } from 'types/common'
import IconChevronRight from 'icons/ChevronRight'
import { IconOptionRow, DisclaimerBox, OptionRow, Inner } from '../../helperComponents'
type Props = {
t: T,
}
class SelectPINrestoreNanoX extends PureComponent<Props, *> {
render() {
const { t } = this.props
const stepsLedgerNano = [
{
key: 'step1',
icon: <IconOptionRow>{'1.'}</IconOptionRow>,
desc: t('onboarding.selectPIN.restore.instructions.nanoX.step1'),
},
{
key: 'step2',
icon: <IconOptionRow>{'2.'}</IconOptionRow>,
desc: t('onboarding.selectPIN.restore.instructions.nanoX.step2'),
},
{
key: 'step3',
icon: <IconOptionRow>{'3.'}</IconOptionRow>,
desc: t('onboarding.selectPIN.restore.instructions.nanoX.step3'),
},
{
key: 'step4',
icon: <IconOptionRow>{'4.'}</IconOptionRow>,
desc: t('onboarding.selectPIN.restore.instructions.nanoX.step4'),
},
{
key: 'step5',
icon: <IconOptionRow>{'5.'}</IconOptionRow>,
desc: t('onboarding.selectPIN.restore.instructions.nanoX.step5'),
},
]
const disclaimerNotes = [
{
key: 'note1',
icon: <IconChevronRight size={12} style={{ color: colors.smoke }} />,
desc: t('onboarding.selectPIN.disclaimer.note1'),
},
{
key: 'note2',
icon: <IconChevronRight size={12} style={{ color: colors.smoke }} />,
desc: t('onboarding.selectPIN.disclaimer.note2'),
},
{
key: 'note3',
icon: <IconChevronRight size={12} style={{ color: colors.smoke }} />,
desc: t('onboarding.selectPIN.disclaimer.note3'),
},
]
return (
<Box align="center" mt={3}>
<Inner style={{ width: 700 }}>
<img alt="" src={i('select-pin-nano-x-onb.svg')} />
<Box shrink grow flow={4} style={{ marginLeft: 40 }}>
{stepsLedgerNano.map(step => <OptionRow key={step.key} step={step} />)}
</Box>
</Inner>
<DisclaimerBox mt={6} disclaimerNotes={disclaimerNotes} />
</Box>
)
}
}
export default translate()(SelectPINrestoreNanoX)

81
src/components/Onboarding/steps/SelectPIN/SelectPINnanoX.js

@ -0,0 +1,81 @@
// @flow
import React, { PureComponent } from 'react'
import { translate, Trans } from 'react-i18next'
import { colors } from 'styles/theme'
import { i } from 'helpers/staticPath'
import Box from 'components/base/Box'
import type { T } from 'types/common'
import IconChevronRight from 'icons/ChevronRight'
import { IconOptionRow, DisclaimerBox, OptionRow, Inner } from '../../helperComponents'
type Props = {
t: T,
}
class SelectPINnanoX extends PureComponent<Props, *> {
render() {
const { t } = this.props
const stepsLedgerNano = [
{
key: 'step1',
icon: <IconOptionRow>{'1.'}</IconOptionRow>,
desc: t('onboarding.selectPIN.initialize.instructions.nanoX.step1'),
},
{
key: 'step2',
icon: <IconOptionRow>{'2.'}</IconOptionRow>,
desc: (
<Box style={{ display: 'block' }}>
<Trans i18nKey="onboarding.selectPIN.initialize.instructions.nanoX.step2" />
</Box>
),
},
{
key: 'step3',
icon: <IconOptionRow>{'3.'}</IconOptionRow>,
desc: t('onboarding.selectPIN.initialize.instructions.nanoX.step3'),
},
{
key: 'step4',
icon: <IconOptionRow>{'4.'}</IconOptionRow>,
desc: t('onboarding.selectPIN.initialize.instructions.nanoX.step4'),
},
]
const disclaimerNotes = [
{
key: 'note1',
icon: <IconChevronRight size={12} style={{ color: colors.smoke }} />,
desc: t('onboarding.selectPIN.disclaimer.note1'),
},
{
key: 'note2',
icon: <IconChevronRight size={12} style={{ color: colors.smoke }} />,
desc: t('onboarding.selectPIN.disclaimer.note2'),
},
{
key: 'note3',
icon: <IconChevronRight size={12} style={{ color: colors.smoke }} />,
desc: t('onboarding.selectPIN.disclaimer.note3'),
},
]
return (
<Box align="center" mt={3}>
<Inner style={{ width: 700 }}>
<img alt="" src={i('select-pin-nano-x-onb.svg')} />
<Box shrink grow flow={4} style={{ marginLeft: 40 }}>
{stepsLedgerNano.map(step => <OptionRow key={step.key} step={step} />)}
</Box>
</Inner>
<DisclaimerBox mt={6} disclaimerNotes={disclaimerNotes} />
</Box>
)
}
}
export default translate()(SelectPINnanoX)

24
src/components/Onboarding/steps/SelectPIN/index.js

@ -1,23 +1,39 @@
// @flow
import React from 'react'
import { getDeviceModel } from '@ledgerhq/devices'
import Box from 'components/base/Box'
import TrackPage from 'analytics/TrackPage'
import type { DeviceModelId } from 'reducers/onboarding'
import GrowScroll from 'components/base/GrowScroll'
import { Title, FixedTopContainer } from '../../helperComponents'
import OnboardingFooter from '../../OnboardingFooter'
import SelectPINnano from './SelectPINnano'
import SelectPINblue from './SelectPINblue'
import SelectPINnanoX from './SelectPINnanoX'
import SelectPINrestoreNano from './SelectPINrestoreNano'
import SelectPINRestoreNanoX from './SelectPINRestoreNanoX'
import SelectPINrestoreBlue from './SelectPINrestoreBlue'
import type { StepProps } from '../..'
const SelectPin = ({ modelId, restore = false }: { modelId: DeviceModelId, restore?: boolean }) => {
switch (modelId) {
case 'nanoX':
return restore ? <SelectPINRestoreNanoX /> : <SelectPINnanoX />
case 'blue':
return restore ? <SelectPINrestoreBlue /> : <SelectPINblue />
default:
return restore ? <SelectPINrestoreNano /> : <SelectPINnano />
}
}
export default (props: StepProps) => {
const { nextStep, prevStep, t, onboarding } = props
const model = getDeviceModel(onboarding.deviceModelId)
return (
<FixedTopContainer>
<GrowScroll pb={7}>
@ -25,20 +41,20 @@ export default (props: StepProps) => {
category="Onboarding"
name="Choose PIN"
flowType={onboarding.flowType}
deviceType={onboarding.isLedgerNano ? 'Nano S' : 'Blue'}
deviceType={model.productName}
/>
{onboarding.flowType === 'restoreDevice' ? (
<Box grow alignItems="center">
<Title>{t('onboarding.selectPIN.restore.title')}</Title>
<Box align="center" mt={7}>
{onboarding.isLedgerNano ? <SelectPINrestoreNano /> : <SelectPINrestoreBlue />}
<SelectPin modelId={onboarding.deviceModelId} restore />
</Box>
</Box>
) : (
<Box grow alignItems="center">
<Title>{t('onboarding.selectPIN.initialize.title')}</Title>
<Box align="center" mt={7}>
{onboarding.isLedgerNano ? <SelectPINnano /> : <SelectPINblue />}
<SelectPin modelId={onboarding.deviceModelId} />
</Box>
</Box>
)}

4
src/components/Onboarding/steps/SetPassword.js

@ -2,6 +2,8 @@
import React, { PureComponent, Fragment } from 'react'
import { connect } from 'react-redux'
import { getDeviceModel } from '@ledgerhq/devices'
import { colors } from 'styles/theme'
import db from 'helpers/db'
@ -105,7 +107,7 @@ class SetPassword extends PureComponent<Props, State> {
category="Onboarding"
name="Set Password"
flowType={onboarding.flowType}
deviceType={onboarding.isLedgerNano ? 'Nano S' : 'Blue'}
deviceType={getDeviceModel(onboarding.deviceModelId).productName}
/>
<StepContainerInner>
<Fragment>

2
src/components/Onboarding/steps/WriteSeed/WriteSeedRestore.js

@ -123,7 +123,7 @@ class WriteSeedRestore extends PureComponent<Props, *> {
<Box style={{ width: 260, justifyContent: 'center', alignItems: 'center' }}>
<img alt="" src={i('write-seed-onb.svg')} />
</Box>
{onboarding.isLedgerNano ? (
{onboarding.deviceModelId === 'nanoS' ? (
<Box shrink flow={2} m={0}>
{stepsNano.map(step => <OptionRow key={step.key} step={step} />)}
</Box>

8
src/components/Onboarding/steps/WriteSeed/index.js

@ -1,7 +1,7 @@
// @flow
import React from 'react'
import { getDeviceModel } from '@ledgerhq/devices'
import Box from 'components/base/Box'
import TrackPage from 'analytics/TrackPage'
@ -17,6 +17,8 @@ import type { StepProps } from '../..'
export default (props: StepProps) => {
const { nextStep, prevStep, t, onboarding } = props
const model = getDeviceModel(onboarding.deviceModelId)
return (
<FixedTopContainer>
<GrowScroll pb={7}>
@ -24,12 +26,12 @@ export default (props: StepProps) => {
category="Onboarding"
name="Recovery Phase"
flowType={onboarding.flowType}
deviceType={onboarding.isLedgerNano ? 'Nano S' : 'Blue'}
deviceType={model.productName}
/>
<Box grow alignItems="center">
{onboarding.flowType === 'restoreDevice' ? (
<WriteSeedRestore onboarding={onboarding} />
) : onboarding.isLedgerNano ? (
) : onboarding.deviceModelId === 'nanoS' ? (
<WriteSeedNano />
) : (
<WriteSeedBlue />

5
src/components/SettingsPage/CleanButton.js

@ -6,6 +6,7 @@ import { translate } from 'react-i18next'
import logger from 'logger'
import type { T } from 'types/common'
import { cleanAccountsCache } from 'actions/accounts'
import SyncSkipUnderPriority from 'components/SyncSkipUnderPriority'
import Button from 'components/base/Button'
import ConfirmModal from 'components/base/Modal/ConfirmModal'
import { softReset } from 'helpers/reset'
@ -69,7 +70,9 @@ class CleanButton extends PureComponent<Props, State> {
title={t('settings.softResetModal.title')}
subTitle={t('common.areYouSure')}
desc={t('settings.softResetModal.desc')}
/>
>
<SyncSkipUnderPriority priority={999} />
</ConfirmModal>
<ResetFallbackModal isOpened={fallbackOpened} onClose={this.closeFallback} />
</Fragment>

5
src/components/SettingsPage/ResetButton.js

@ -7,6 +7,7 @@ import { translate } from 'react-i18next'
import logger from 'logger'
import type { T } from 'types/common'
import { hardReset } from 'helpers/reset'
import SyncSkipUnderPriority from 'components/SyncSkipUnderPriority'
import Box from 'components/base/Box'
import Button from 'components/base/Button'
import ConfirmModal from 'components/base/Modal/ConfirmModal'
@ -73,7 +74,9 @@ class ResetButton extends PureComponent<Props, State> {
<IconTriangleWarning width={23} height={21} />
</IconWrapperCircle>
)}
/>
>
<SyncSkipUnderPriority priority={999} />
</ConfirmModal>
<ResetFallbackModal isOpened={fallbackOpened} onClose={this.closeFallback} />
</Fragment>

3
src/components/Updater/UpdaterContext.js

@ -44,7 +44,8 @@ class Provider extends Component<UpdaterProviderProps, UpdaterProviderState> {
this.sub = autoUpdate.send({}).subscribe({
next: e => {
if (e.status === 'download-progress') {
const downloadProgress = e.payload && e.payload.percent ? e.payload.percent : 0
const downloadProgress =
e.payload && e.payload.percent ? e.payload.percent.toFixed(0) : 0
this.setState({ status: e.status, downloadProgress })
} else {
this.setStatus(e.status)

3
src/components/base/Modal/ConfirmModal.js

@ -29,6 +29,7 @@ type Props = {
analyticsName: string,
cancellable?: boolean,
centered?: boolean,
children?: *,
}
class ConfirmModal extends PureComponent<Props> {
@ -50,6 +51,7 @@ class ConfirmModal extends PureComponent<Props> {
t,
analyticsName,
centered,
children,
...props
} = this.props
@ -91,6 +93,7 @@ class ConfirmModal extends PureComponent<Props> {
<Box ff="Open Sans" color="smoke" fontSize={4} textAlign="center">
{desc}
</Box>
{children}
</Box>
)}
/>

2
src/config/urls.js

@ -4,7 +4,7 @@ export const urls = {
liveHome: 'https://www.ledger.com/pages/ledger-live',
// Social
twitter: 'https://twitter.com/LedgerHQ',
twitter: 'https://twitter.com/Ledger',
github: 'https://github.com/LedgerHQ/ledger-live-desktop',
reddit: 'https://www.reddit.com/r/ledgerwallet/',

24
src/helpers/reset.js

@ -1,23 +1,21 @@
// @flow
import fs from 'fs'
import { shell, remote } from 'electron'
import path from 'path'
import rimraf from 'rimraf'
import resolveUserDataDirectory from 'helpers/resolveUserDataDirectory'
import { disable as disableDBMiddleware } from 'middlewares/db'
import db from 'helpers/db'
import { delay } from 'helpers/promise'
import killInternalProcess from 'commands/killInternalProcess'
import { DBNotReset } from '@ledgerhq/errors'
import libcoreReset from 'commands/libcoreReset'
async function resetLibcoreDatabase() {
await killInternalProcess.send().toPromise()
const dbpath = path.resolve(resolveUserDataDirectory(), 'sqlite/')
rimraf.sync(dbpath, { glob: false })
if (fs.existsSync(dbpath)) {
throw new DBNotReset()
}
async function resetLibcore() {
// we need to stop everything that is happening right now, like syncs
await killInternalProcess
.send()
.toPromise()
.catch(() => {}) // this is a normal error due to the crash of the process, we ignore it
// we can now ask libcore to reset itself
await libcoreReset.send().toPromise()
}
function reload() {
@ -30,7 +28,7 @@ export async function hardReset() {
disableDBMiddleware()
db.resetAll()
await delay(500)
await resetLibcoreDatabase()
await resetLibcore()
reload()
}
@ -38,7 +36,7 @@ export async function softReset({ cleanAccountsCache }: *) {
cleanAccountsCache()
await delay(500)
await db.cleanCache()
await resetLibcoreDatabase()
await resetLibcore()
reload()
}

34
src/icons/device/NanoX.js

@ -2,29 +2,15 @@
import React from 'react'
export default ({ size = 30, ...p }: { size: number }) => (
<svg viewBox="0 0 6 16" height={size} width={size} {...p}>
<defs>
<path
id="a"
d="M5.75 6.835a3.509 3.509 0 0 0-1.5-1.105V1.75h-2.5v3.98a3.509 3.509 0 0 0-1.5 1.105V1.666C.25.884.884.25 1.666.25h2.668c.782 0 1.416.634 1.416 1.416v5.169zm-1.5 7.415V9.5a1.25 1.25 0 1 0-2.5 0v4.75h2.5zM3 6.75A2.75 2.75 0 0 1 5.75 9.5v4.834c0 .782-.634 1.416-1.416 1.416H1.666A1.416 1.416 0 0 1 .25 14.334V9.5A2.75 2.75 0 0 1 3 6.75z"
/>
</defs>
<g fill="none" fillRule="evenodd">
<path
fill="#000"
fillRule="nonzero"
d="M5.75 6.835a3.509 3.509 0 0 0-1.5-1.105V1.75h-2.5v3.98a3.509 3.509 0 0 0-1.5 1.105V1.666C.25.884.884.25 1.666.25h2.668c.782 0 1.416.634 1.416 1.416v5.169zm-1.5 7.415V9.5a1.25 1.25 0 1 0-2.5 0v4.75h2.5zM3 6.75A2.75 2.75 0 0 1 5.75 9.5v4.834c0 .782-.634 1.416-1.416 1.416H1.666A1.416 1.416 0 0 1 .25 14.334V9.5A2.75 2.75 0 0 1 3 6.75z"
/>
<g>
<mask id="b" fill="#fff">
<use xlinkHref="#a" />
</mask>
<use fill="#FFF" xlinkHref="#a" />
<g fill="#FFF" mask="url(#b)">
<path d="M-5 0h16v16H-5z" />
</g>
</g>
</g>
const path = (
<path
fill="currentColor"
d="M6.667 14.543A4.181 4.181 0 0 0 5 13.223V1.667H1.667v11.556A4.181 4.181 0 0 0 0 14.543V1.2A1.2 1.2 0 0 1 1.2 0h4.267a1.2 1.2 0 0 1 1.2 1.2v13.343zm-3.334 4.403a.833.833 0 1 1 0-1.666.833.833 0 0 1 0 1.666zm0-14a.833.833 0 1 1 0-1.666.833.833 0 0 1 0 1.666zm-1.666 21.72H5v-9.623a1.667 1.667 0 1 0-3.333 0v9.624zM3.333 13.71a3.333 3.333 0 0 1 3.334 3.333v10.302a.988.988 0 0 1-.989.988H.988A.988.988 0 0 1 0 27.345V17.043a3.333 3.333 0 0 1 3.333-3.333z"
/>
)
export default ({ size, ...p }: { size: number }) => (
<svg viewBox="0 0 8 30" height={size} width={size} {...p}>
{path}
</svg>
)

30
src/icons/device/NanoXBanner.js

@ -0,0 +1,30 @@
// @flow
import React from 'react'
export default ({ size = 30, ...p }: { size: number }) => (
<svg viewBox="0 0 6 16" height={size} width={size} {...p}>
<defs>
<path
id="a"
d="M5.75 6.835a3.509 3.509 0 0 0-1.5-1.105V1.75h-2.5v3.98a3.509 3.509 0 0 0-1.5 1.105V1.666C.25.884.884.25 1.666.25h2.668c.782 0 1.416.634 1.416 1.416v5.169zm-1.5 7.415V9.5a1.25 1.25 0 1 0-2.5 0v4.75h2.5zM3 6.75A2.75 2.75 0 0 1 5.75 9.5v4.834c0 .782-.634 1.416-1.416 1.416H1.666A1.416 1.416 0 0 1 .25 14.334V9.5A2.75 2.75 0 0 1 3 6.75z"
/>
</defs>
<g fill="none" fillRule="evenodd">
<path
fill="#000"
fillRule="nonzero"
d="M5.75 6.835a3.509 3.509 0 0 0-1.5-1.105V1.75h-2.5v3.98a3.509 3.509 0 0 0-1.5 1.105V1.666C.25.884.884.25 1.666.25h2.668c.782 0 1.416.634 1.416 1.416v5.169zm-1.5 7.415V9.5a1.25 1.25 0 1 0-2.5 0v4.75h2.5zM3 6.75A2.75 2.75 0 0 1 5.75 9.5v4.834c0 .782-.634 1.416-1.416 1.416H1.666A1.416 1.416 0 0 1 .25 14.334V9.5A2.75 2.75 0 0 1 3 6.75z"
/>
<g>
<mask id="b" fill="#fff">
<use xlinkHref="#a" />
</mask>
<use fill="#FFF" xlinkHref="#a" />
<g fill="#FFF" mask="url(#b)">
<path d="M-5 0h16v16H-5z" />
</g>
</g>
</g>
</svg>
)

1
src/icons/device/index.js

@ -1,3 +1,4 @@
export Blue from './Blue'
export NanoS from './NanoS'
export NanoX from './NanoX'
export NanoXBanner from './NanoXBanner'

12
src/reducers/onboarding.js

@ -15,6 +15,8 @@ type Step = {
},
}
export type DeviceModelId = 'nanoX' | 'nanoS' | 'blue' | ''
export type OnboardingState = {
stepIndex: number,
stepName: string, // TODO: specify that the string comes from Steps type
@ -27,7 +29,7 @@ export type OnboardingState = {
genuineCheckUnavailable: ?Error,
displayErrorScreen: boolean,
},
isLedgerNano: boolean | null,
deviceModelId: DeviceModelId,
flowType: string,
onboardingRelaunched?: boolean,
}
@ -43,7 +45,7 @@ const initialState: OnboardingState = {
genuineCheckUnavailable: null,
displayErrorScreen: false,
},
isLedgerNano: null,
deviceModelId: '',
flowType: '',
onboardingRelaunched: false,
steps: [
@ -167,9 +169,9 @@ const handlers = {
...state,
flowType,
}),
ONBOARDING_SET_DEVICE_TYPE: (state: OnboardingState, { payload: isLedgerNano }) => ({
ONBOARDING_SET_DEVICE_TYPE: (state: OnboardingState, { payload: deviceModelId }) => ({
...state,
isLedgerNano,
deviceModelId,
}),
ONBOARDING_RELAUNCH: (state: OnboardingState, { payload: onboardingRelaunched }) => ({
...initialState,
@ -187,5 +189,5 @@ export const nextStep = createAction('ONBOARDING_NEXT_STEP')
export const prevStep = createAction('ONBOARDING_PREV_STEP')
export const jumpStep = createAction('ONBOARDING_JUMP_STEP')
export const updateGenuineCheck = createAction('UPDATE_GENUINE_CHECK')
export const isLedgerNano = createAction('ONBOARDING_SET_DEVICE_TYPE')
export const deviceModelId = createAction('ONBOARDING_SET_DEVICE_TYPE')
export const flowType = createAction('ONBOARDING_SET_FLOW_TYPE')

4
src/reducers/settings.js

@ -244,10 +244,12 @@ export const exportSettingsSelector = createSelector(
counterValueCurrencySelector,
counterValueExchangeSelector,
state => state.settings.currenciesSettings,
(counterValueCurrency, counterValueExchange, currenciesSettings) => ({
developerModeSelector,
(counterValueCurrency, counterValueExchange, currenciesSettings, developerModeEnabled) => ({
counterValue: counterValueCurrency.ticker,
counterValueExchange,
currenciesSettings,
developerModeEnabled,
}),
)

11
src/renderer/events.js

@ -51,14 +51,19 @@ export default ({ store }: { store: Object }) => {
function syncDevices() {
syncDeviceSub = listenDevices.send().subscribe(
({ device, type }) => {
({ device, deviceModel, type }) => {
if (device) {
const stateDevice = {
path: device.path,
modelId: deviceModel ? deviceModel.id : 'nanoS',
type: 'hid',
}
if (type === 'add') {
d.device('Device - add')
store.dispatch(addDevice(device))
store.dispatch(addDevice(stateDevice))
} else if (type === 'remove') {
d.device('Device - remove')
store.dispatch(removeDevice(device))
store.dispatch(removeDevice(stateDevice))
}
}
},

5
src/types/common.js

@ -1,11 +1,8 @@
// @flow
export type Device = {
manufacturer: string,
path: string,
product: string,
productId: string,
vendorId: string,
modelId: string,
}
// -------------------- Settings

32
static/i18n/en/app.json

@ -145,10 +145,10 @@
"messageIfSkipped": "Your {{currencyName}} address has not been confirmed on your Ledger device. Please verify it for optimal security."
},
"deviceConnect": {
"dashboard": "Navigate to the <1><0>{{managerAppName}}</0></1> on your device",
"dashboard": "Navigate to the <1>Dashboard</1> on your device",
"step1": "Connect and unlock your <1>Ledger device</1>",
"step2": "Navigate to the <1><0>{{managerAppName}}</0></1> app on your device",
"step3": "Allow <1><0>Ledger Manager</0></1> on your device"
"step3": "Allow <1>Ledger Manager</1> on your device"
},
"emptyState": {
"sidebar": {
@ -258,8 +258,6 @@
},
"firmware": {
"installed": "Firmware version {{version}}",
"titleNano": "Ledger Nano S",
"titleBlue": "Ledger Blue",
"update": "Update",
"latest": "Firmware version {{version}} is available",
"disclaimerTitle": "You are about to install <1><0>firmware version {{version}}</0></1>.",
@ -569,13 +567,7 @@
}
},
"selectDevice": {
"title": "Select your device",
"ledgerNanoCard": {
"title": "Ledger Nano S"
},
"ledgerBlueCard": {
"title": "Ledger Blue"
}
"title": "Select your device"
},
"selectPIN": {
"disclaimer": {
@ -592,6 +584,12 @@
"step3": "Press the left or right button to select a digit. Press both buttons to validate.",
"step4": "Select ✓ to confirm your PIN code. Select ⬅ to erase a digit."
},
"nanoX": {
"step1": "Connect the Ledger Nano X to your computer.",
"step2": "Press both buttons to choose Set up as new device.",
"step3": "Press the left or right button to select a digit.",
"step4": "Select ✓ to confirm your PIN code. Select ⬅ to erase a digit."
},
"blue": {
"step1": "Connect the Ledger Blue to your computer.",
"step2": "Tap on <1><0>Configure as new device</0></1>.",
@ -608,6 +606,13 @@
"step3": "Press the left or right button to select a digit. Press both buttons to validate.",
"step4": "Select ✓ to confirm your PIN code. Select ⬅ to erase a digit."
},
"nanoX": {
"step1": "Connect your Ledger Nano X to your computer.",
"step2": "Press both buttons as instructed on your Ledger Nano X screen.",
"step3": "Press the left button to cancel Configure as new device.",
"step4": "Press the right button to select Restore configuration.",
"step5": "Choose a PIN code between 4 and 8 digits long."
},
"blue": {
"step1": "Connect the Ledger Blue to your computer.",
"step2": "Tap on <1><0>Restore configuration</0></1>.",
@ -929,9 +934,12 @@
"FeeNotLoaded": {
"title": "Couldn’t load fee rates, please set manual fees"
},
"FeeRequired": {
"title": "Fees are required"
},
"UnknownMCU": {
"title": "Unknown MCU version",
"description": "Please contact Ledger Support"
}
}
}
}

0
static/images/ledger-nano-onb.svg → static/images/ledger-nano-s-onb.svg

Before

Width:  |  Height:  |  Size: 931 B

After

Width:  |  Height:  |  Size: 931 B

8
static/images/ledger-nano-x-onb.svg

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="76" viewBox="0 0 14 76">
<g fill="none" fill-rule="evenodd">
<path fill="#6490F1" fill-opacity=".1" stroke="#1D2028" stroke-width="1.5" d="M1.6.75a.85.85 0 0 0-.85.85v72.8c0 .47.38.85.85.85h10.8c.47 0 .85-.38.85-.85V1.6a.85.85 0 0 0-.85-.85H1.6z"/>
<path fill="#FFF" stroke="#1D2028" stroke-width="1.5" d="M7 33.321a6.25 6.25 0 0 0-6.25 6.25V74.4c0 .47.38.85.85.85h10.8c.47 0 .85-.38.85-.85V39.571A6.25 6.25 0 0 0 7 33.321z"/>
<ellipse cx="6.995" cy="39.835" fill="#FFF" stroke="#6490F1" stroke-width=".5" rx="3.295" ry="3.256"/>
<ellipse cx="6.993" cy="7.004" stroke="#6490F1" stroke-width=".5" rx="3.293" ry="3.254"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 731 B

BIN
static/images/logos/connectDevice.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

33
static/images/nano-x-error-onb.svg

@ -0,0 +1,33 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="379" height="42" viewBox="0 0 379 42">
<defs>
<linearGradient id="a" x1="50%" x2="50%" y1="0%" y2="100%">
<stop offset="0%"/>
<stop offset="100%" stop-color="#FFF"/>
</linearGradient>
<rect id="b" width="41.711" height="238.384" rx="4"/>
<path id="c" d="M5.773 5l2.541-2.541a.235.235 0 0 0 0-.332l-.441-.441a.235.235 0 0 0-.332 0L5 4.226l-2.541-2.54a.235.235 0 0 0-.332 0l-.441.441a.235.235 0 0 0 0 .332L4.226 5l-2.54 2.541a.235.235 0 0 0 0 .332l.441.441c.092.092.24.092.332 0L5 5.774l2.541 2.54c.092.092.24.092.332 0l.441-.441a.235.235 0 0 0 0-.332L5.774 5z"/>
</defs>
<g fill="none" fill-rule="evenodd">
<path stroke="#1D2027" stroke-width="2" d="M127.356 29a1 1 0 0 1-1 1H100.13a5 5 0 0 1-5-5v-8.486a5 5 0 0 1 5-5h26.225a1 1 0 0 1 1 1V29z"/>
<path stroke="#142533" stroke-width="2" d="M94.747 23.792H83.818v-6.436h10.93v6.436z"/>
<path stroke="#1D2027" stroke-width="2" d="M127.423 26.287V15.032l6.977.082a1 1 0 0 1 .988 1V25.381a1 1 0 0 1-1.012.988l-6.953-.082z"/>
<path fill="url(#a)" d="M6.836 53.925h1.616v82.65H6.836v-82.65zm5.657 0h1.616v82.65h-1.616v-82.65z" transform="matrix(0 -1 -1 0 137 31)"/>
<g transform="rotate(-90 84.5 -42.5)">
<use fill="#FFF" xlink:href="#b"/>
<rect width="39.711" height="236.384" x="1" y="1" fill="#FCE0E4" stroke="#142533" stroke-linejoin="square" stroke-width="2" rx="4"/>
<path fill="#FFF" stroke="#EA2E49" d="M10.6 44.5a1.1 1.1 0 0 0-1.1 1.1v50.8a1.1 1.1 0 0 0 1.1 1.1h20.8a1.1 1.1 0 0 0 1.1-1.1V45.6a1.1 1.1 0 0 0-1.1-1.1H10.6z"/>
<path fill="#FFF" stroke="#142533" stroke-width="2" d="M20.856 108.966C9.89 108.966 1 117.856 1 128.822v118.562a3 3 0 0 0 3 3h33.711a3 3 0 0 0 3-3V128.822c0-10.966-8.89-19.856-19.855-19.856z"/>
<ellipse cx="21.016" cy="129.123" stroke="#EA2E49" rx="10.57" ry="10.644"/>
<ellipse cx="21.016" cy="21.123" stroke="#EA2E49" rx="10.57" ry="10.644"/>
<g transform="translate(16 66)">
<mask id="d" fill="#fff">
<use xlink:href="#c"/>
</mask>
<use fill="#000" fill-rule="nonzero" xlink:href="#c"/>
<g fill="#EA2E49" mask="url(#d)">
<path d="M0 0h10v10H0z"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

24
static/images/select-pin-nano-x-onb.svg

@ -0,0 +1,24 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="264" height="128" viewBox="0 0 264 128">
<defs>
<linearGradient id="a" x1="50%" x2="50%" y1="0%" y2="100%">
<stop offset="0%"/>
<stop offset="100%" stop-color="#FFF"/>
</linearGradient>
<path id="b" d="M91 0h34a4 4 0 0 1 4 4v118.144c0 11.519-9.337 20.856-20.856 20.856h-.288C96.337 143 87 133.663 87 122.144V4a4 4 0 0 1 4-4z"/>
</defs>
<g fill="none" fill-rule="evenodd">
<path stroke="#1D2027" stroke-width="2" d="M127.856 30.44a1 1 0 0 1-1 1H100.63a5 5 0 0 1-5-5v-8.486a5 5 0 0 1 5-5h26.225a1 1 0 0 1 1 1v16.485z"/>
<path stroke="#142533" stroke-width="2" d="M95.247 25.231H84.318v-6.435h10.93v6.435z"/>
<path stroke="#1D2027" stroke-width="2" d="M127.923 27.726V16.471l6.977.083a1 1 0 0 1 .988 1V26.82a1 1 0 0 1-1.012.988l-6.953-.083z"/>
<path fill="url(#a)" d="M6.836 53.925h1.616v82.65H6.836v-82.65zm5.657 0h1.616v82.65h-1.616v-82.65z" transform="matrix(0 -1 -1 0 137.5 32.44)"/>
<g transform="rotate(-90 125.09 4.475)">
<use fill="#FFF" xlink:href="#b"/>
<path fill="#6490F1" fill-opacity=".15" stroke="#142533" stroke-linejoin="square" stroke-width="2" d="M91 1a3 3 0 0 0-3 3v118.144C88 133.11 96.89 142 107.856 142h.288C119.11 142 128 133.11 128 122.144V4a3 3 0 0 0-3-3H91z"/>
<path fill="#FFF" stroke="#6490F1" d="M97.6 41.5a1.1 1.1 0 0 0-1.1 1.1v52.8a1.1 1.1 0 0 0 1.1 1.1h20.8a1.1 1.1 0 0 0 1.1-1.1V42.6a1.1 1.1 0 0 0-1.1-1.1H97.6z"/>
<path fill="#6490F1" d="M105.5 51h5a.5.5 0 0 1 .5.5v34a.5.5 0 0 1-.5.5h-5a.5.5 0 0 1-.5-.5v-34a.5.5 0 0 1 .5-.5zm1.238 3.042l.774.512v.013l-.774.505.341.466.722-.577h.013l.243.899.551-.177-.328-.88.932.053v-.597l-.932.046.328-.873-.551-.17-.243.892h-.013l-.722-.584-.34.472zm0 3.908l.774.512v.013l-.774.505.341.466.722-.578h.013l.243.9.551-.178-.328-.88.932.053v-.597l-.932.046.328-.872-.551-.17-.243.891h-.013l-.722-.584-.34.473zm0 3.907l.774.512v.013l-.774.505.341.466.722-.577h.013l.243.899.551-.178-.328-.879.932.053v-.597l-.932.046.328-.873-.551-.17-.243.892h-.013l-.722-.584-.34.472zm0 3.908l.774.511v.014l-.774.505.341.466.722-.578h.013l.243.899.551-.177-.328-.88.932.053v-.597l-.932.046.328-.872-.551-.171-.243.892h-.013l-.722-.584-.34.473zm0 3.907l.774.512v.013l-.774.505.341.466.722-.577h.013l.243.898.551-.177-.328-.879.932.053v-.597l-.932.046.328-.873-.551-.17-.243.892h-.013l-.722-.584-.34.472zm0 3.908l.774.511v.013l-.774.506.341.465.722-.577h.013l.243.899.551-.177-.328-.88.932.053v-.597l-.932.046.328-.873-.551-.17-.243.892h-.013l-.722-.584-.34.473zm0 3.907l.774.512v.013l-.774.505.341.466.722-.578h.013l.243.9.551-.178-.328-.879.932.052v-.597l-.932.046.328-.872-.551-.17-.243.891h-.013l-.722-.583-.34.472zm0 3.907l.774.512v.013l-.774.505.341.466.722-.577h.013l.243.899.551-.177-.328-.88.932.053v-.597l-.932.046.328-.873-.551-.17-.243.892h-.013l-.722-.584-.34.472z"/>
<path fill="#FFF" stroke="#142533" stroke-width="2" d="M123.166 135.105c7.049-8.4 5.953-20.925-2.447-27.974l-90.824-76.21a3 3 0 0 0-4.227.37L4 57.115a3 3 0 0 0 .37 4.227l90.824 76.21c8.4 7.049 20.924 5.953 27.973-2.447z"/>
<ellipse cx="108.016" cy="122.123" stroke="#6490F1" rx="10.57" ry="10.644"/>
<ellipse cx="108.016" cy="22.123" stroke="#6490F1" rx="10.57" ry="10.644"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

157
yarn.lock

@ -1677,55 +1677,66 @@
camelcase "^5.0.0"
prettier "^1.13.7"
"@ledgerhq/errors@^4.32.0", "@ledgerhq/errors@^4.35.1":
version "4.35.1"
resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-4.35.1.tgz#3f162dc05480e444083b6381bd098df187751633"
integrity sha512-2Bo3/NRKyz3ddR07TvZ87VpDJc8fz4+ONLJnhzC0mwIwu+Pxal6SgCBiGtv503oGxkgDuG5PtODZBaehWkGRnQ==
"@ledgerhq/devices@^4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-4.39.0.tgz#47d23a1a58004da162e007e0c456ab2119038c7d"
integrity sha512-2Jd7CVvMJDZxxaSpQpfOMeGWf7M0f6nZqZQWfjsUDQHw45Kunck101pXr6U/5UejJiLl/fhyLqvaXz0X0cs+1A==
dependencies:
"@ledgerhq/errors" "^4.39.0"
"@ledgerhq/errors@^4.32.0", "@ledgerhq/errors@^4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-4.39.0.tgz#10b9889f78df94ce36a4b34d9a3a45aac77be0e9"
integrity sha512-kBr2rnoYDACRCxTLtEufE4oCvYj6vx2oFWVVjwskBxYsF5LC9R8Mbg5C4GgvDweiWW4Io8HA9p9jCsOfdCDygg==
"@ledgerhq/hw-app-btc@^4.32.0", "@ledgerhq/hw-app-btc@^4.35.0":
version "4.35.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-4.35.0.tgz#aafd655c988da39f774b0a4706e7f8897222f414"
integrity sha512-oX9YcQAuU+rOJm/lE7YF5+JXNppHcUv23ZltGz5CbWHnhm7Tqo4MOR8N5oSnHKlHW+IawfWCPN5PqdF7RGyQ5w==
"@ledgerhq/hw-app-btc@^4.32.0", "@ledgerhq/hw-app-btc@^4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-4.39.0.tgz#5b564e683a43a50002579834ec54aa790fde35f1"
integrity sha512-xPOtoIgsErycMFTKHb0yHLqlKn0C+9msLBsA1zRPNsWMdxEEBO5pzFVmn5ha1j3q/73yeICHlcB4KZcTb7CShA==
dependencies:
"@ledgerhq/hw-transport" "^4.35.0"
"@ledgerhq/hw-transport" "^4.39.0"
create-hash "^1.1.3"
"@ledgerhq/hw-app-eth@^4.32.0", "@ledgerhq/hw-app-eth@^4.35.0":
version "4.35.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-4.35.0.tgz#3a8c1b0db87224a24ff5441a0e819122e5585f2d"
integrity sha512-MSDr8+CaoXhtm64ELuI/8wpcfmrMUjzGJgASY6bnjc82vAW+6sHNZlTU0zWRTZxqQUuZ8WpuJP159cf92MWq3g==
"@ledgerhq/hw-app-eth@^4.32.0", "@ledgerhq/hw-app-eth@^4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-4.39.0.tgz#3cbba1f1650665c4c29c7b9fa246cb2360495867"
integrity sha512-IKPcLTcGohh/S6Z1LaAfn2pGyxfT6xu958/xV+5H4a3Ej0CWKaxcno4FkhaxH4OiViF0F5SEFzxtH+UntH2jdg==
dependencies:
"@ledgerhq/hw-transport" "^4.35.0"
"@ledgerhq/hw-transport" "^4.39.0"
"@ledgerhq/hw-app-xrp@^4.32.0", "@ledgerhq/hw-app-xrp@^4.35.0":
version "4.35.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-xrp/-/hw-app-xrp-4.35.0.tgz#f6aec06ae53f8732d90f745963a2de96c2ffa432"
integrity sha512-kQLdr9xrYvkFR9+QVyTNtmSGFDfrQ63ac0QhWKEoILiiQ0dxfZ7qCCp/qPJk/sx9H8dMX37X6y+xAnSU1frbfg==
"@ledgerhq/hw-app-xrp@^4.32.0", "@ledgerhq/hw-app-xrp@^4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-xrp/-/hw-app-xrp-4.39.0.tgz#cc399649f17873778e34bcde16f488faef3117e5"
integrity sha512-lbrG7AhQdJzt/zhu0G5yfC2t4zlytWuzbNLrPp/VQKJJPUKsC98H81pmfMzn1lFBdm8frmBVUW6reN5p7wDS2Q==
dependencies:
"@ledgerhq/hw-transport" "^4.35.0"
"@ledgerhq/hw-transport" "^4.39.0"
bip32-path "0.4.2"
"@ledgerhq/hw-transport-node-hid@^4.35.0":
version "4.35.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.35.0.tgz#0eba08e5edd14a8c779ebaf73ec21976ee5f112e"
integrity sha512-Otnymk9B7qCEfjych/SvTvJsMM+DqyoB0saEwL80ukjuGFqMunecrG5w8nC4aCc169IVz70Spkg2uU90TBUCuw==
"@ledgerhq/hw-transport-node-hid@^4.40.0":
version "4.40.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.40.0.tgz#7f35194f94e20374e1bd6a04e5299032c5e81b6c"
integrity sha512-Nxp2Ys5lxgWTUG/A+W7O3nemkIBigW0LSJI6QrCDdLDg7deU+Zp6QA/CDS95BLijqi5m0AqKE2U4IyQh4OFnhQ==
dependencies:
"@ledgerhq/hw-transport" "^4.35.0"
"@ledgerhq/devices" "^4.39.0"
"@ledgerhq/errors" "^4.39.0"
"@ledgerhq/hw-transport" "^4.39.0"
lodash "^4.17.11"
node-hid "^0.7.2"
usb "^1.3.3"
node-hid "^0.7.6"
usb "^1.5.0"
"@ledgerhq/hw-transport@^4.21.0", "@ledgerhq/hw-transport@^4.32.0", "@ledgerhq/hw-transport@^4.35.0":
version "4.35.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.35.0.tgz#aa7b851111ed759cd7489fa07a7b34c1773e8314"
integrity sha512-o8ekdoCkHMvOByIKDmAMNDjm8Q5cu+sbqmebPtGrHAPbgIZBUbNA5UupY/Om+xypdxXYnuBw+MF8FyIVOjnIsg==
"@ledgerhq/hw-transport@^4.21.0", "@ledgerhq/hw-transport@^4.32.0", "@ledgerhq/hw-transport@^4.39.0":
version "4.39.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.39.0.tgz#602c6ea3fef56d1df205274ea742b4cf85613f6c"
integrity sha512-XkVAy2SFRDdE3qQGGVxB7RQdsdIx1fcoRNReU7NQXK59fYqxue+ZoiGtynEoHq9RKMg8EBG2kBXSVEh1iPdOlA==
dependencies:
"@ledgerhq/devices" "^4.39.0"
"@ledgerhq/errors" "^4.39.0"
events "^3.0.0"
"@ledgerhq/ledger-core@2.0.0-rc.16":
version "2.0.0-rc.16"
resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-2.0.0-rc.16.tgz#51f141c0143edb020e38855bf2e2619e3446e74f"
integrity sha512-gmbeXRBg4NSqzH6+EajYTzaQlwN5ugaN1nH0SI6BvRqMfcorxNRE8byfh3F2u+7TNchBW72vOZnKPDShaR9/pQ==
"@ledgerhq/ledger-core@2.0.0-rc.21":
version "2.0.0-rc.21"
resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-2.0.0-rc.21.tgz#f9e48cf162150ef3d5089ac19e9effcef4626697"
integrity sha512-DqBY1D95wz3a56k8bx7e8YhTsVake/4ZBxH5RgUnXl4OQYRQNKyrtqt94yKvYi+JkRqtU2z60XgB5mo58jaq+w==
dependencies:
bindings "^1.3.0"
nan "^2.6.2"
@ -4172,6 +4183,13 @@ bindings@^1.3.0:
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.1.tgz#21fc7c6d67c18516ec5aaa2815b145ff77b26ea5"
integrity sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew==
bindings@^1.3.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.4.0.tgz#909efa49f2ebe07ecd3cb136778f665052040127"
integrity sha512-7znEVX22Djn+nYjxCWKDne0RRloa9XfYa84yk3s+HkE3LpDYZmhArYr9O9huBoHY3/oXispx5LorIX7Sl2CgSQ==
dependencies:
file-uri-to-path "1.0.0"
bip32-path@0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/bip32-path/-/bip32-path-0.4.2.tgz#5db0416ad6822712f077836e2557b8697c0c7c99"
@ -7844,6 +7862,11 @@ file-loader@^1.1.11:
loader-utils "^1.0.2"
schema-utils "^0.4.5"
file-uri-to-path@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
filename-regex@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
@ -11330,16 +11353,21 @@ mute-stream@0.0.7:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
nan@^2.10.0, nan@^2.8.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.0.tgz#9d443fdb5e13a20770cc5e602eee59760a685885"
integrity sha512-zT5nC0JhbljmyEf+Z456nvm7iO7XgRV2hYxoBtPpnyp+0Q4aCoP6uWNn76v/I6k2kCYNLWqWbwBWQcjsNI/bjw==
nan@^2.12.1:
version "2.12.1"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552"
integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==
nan@^2.2.1, nan@^2.6.2, nan@^2.9.2:
version "2.10.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==
nan@^2.8.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.0.tgz#9d443fdb5e13a20770cc5e602eee59760a685885"
integrity sha512-zT5nC0JhbljmyEf+Z456nvm7iO7XgRV2hYxoBtPpnyp+0Q4aCoP6uWNn76v/I6k2kCYNLWqWbwBWQcjsNI/bjw==
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@ -11417,6 +11445,13 @@ node-abi@^2.2.0:
dependencies:
semver "^5.4.1"
node-abi@^2.7.0:
version "2.7.1"
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.7.1.tgz#a8997ae91176a5fbaa455b194976e32683cda643"
integrity sha512-OV8Bq1OrPh6z+Y4dqwo05HqrRL9YNF7QVMRfq1/pguwKLG+q9UB/Lk0x5qXjO23JjJg+/jqCHSTaG1P3tfKfuw==
dependencies:
semver "^5.4.1"
node-dir@0.1.8:
version "0.1.8"
resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.8.tgz#55fb8deb699070707fb67f91a460f0448294c77d"
@ -11465,14 +11500,14 @@ node-gyp@^3.6.0:
tar "^2.0.0"
which "1"
node-hid@^0.7.2:
version "0.7.4"
resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-0.7.4.tgz#2db109acee654b56bf518ffb3fd92cf9cd0647c1"
integrity sha512-gvgNDPoszObn7avIDYMUvVv1T0xQB4/CZFJWckra/LXAc0qHYho4M1LCnCKlLIocL2R5/3qGv0J4AjRMdwgjxg==
node-hid@^0.7.6:
version "0.7.6"
resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-0.7.6.tgz#61523694f1111d209fca55bb704732dad029f3bc"
integrity sha512-cjbjL1CmOpImKQrqkvQKZUWuzvofwECZQ50zoih5vtPRowIZ4TFJDTN3tJYfVhbQYM9PGqDFXLcTILjx9EPvzw==
dependencies:
bindings "^1.3.0"
nan "^2.10.0"
prebuild-install "^5.2.1"
bindings "^1.3.1"
nan "^2.12.1"
prebuild-install "^5.2.2"
node-int64@^0.4.0:
version "0.4.0"
@ -12769,10 +12804,10 @@ prebuild-install@^2.0.0:
tunnel-agent "^0.6.0"
which-pm-runs "^1.0.0"
prebuild-install@^5.2.1:
version "5.2.2"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.2.2.tgz#237888f21bfda441d0ee5f5612484390bccd4046"
integrity sha512-4e8VJnP3zJdZv/uP0eNWmr2r9urp4NECw7Mt1OSAi3rcLrbBRxGiAkfUFtre2MhQ5wfREAjRV+K1gubvs/GPsA==
prebuild-install@^5.2.2:
version "5.2.4"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.2.4.tgz#8cc41a217ef778a31d3a876fe6668d05406db750"
integrity sha512-CG3JnpTZXdmr92GW4zbcba4jkDha6uHraJ7hW4Fn8j0mExxwOKK20hqho8ZuBDCKYCHYIkFM1P2jhtG+KpP4fg==
dependencies:
detect-libc "^1.0.3"
expand-template "^2.0.3"
@ -12780,7 +12815,7 @@ prebuild-install@^5.2.1:
minimist "^1.2.0"
mkdirp "^0.5.1"
napi-build-utils "^1.0.1"
node-abi "^2.2.0"
node-abi "^2.7.0"
noop-logger "^0.1.1"
npmlog "^4.0.1"
os-homedir "^1.0.1"
@ -13495,17 +13530,7 @@ react-treebeard@^2.1.0:
shallowequal "^0.2.2"
velocity-react "^1.3.1"
react@*, react@^16.2.0:
version "16.6.1"
resolved "https://registry.yarnpkg.com/react/-/react-16.6.1.tgz#ee2aef4f0a09e494594882029821049772f915fe"
integrity sha512-OtawJThYlvRgm9BXK+xTL7BIlDx8vv21j+fbQDjRRUyok6y7NyjlweGorielTahLZHYIdKUoK2Dp9ByVWuMqxw==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
prop-types "^15.6.2"
scheduler "^0.11.0"
react@^16.6.3:
react@*, react@^16.2.0, react@^16.6.3:
version "16.6.3"
resolved "https://registry.yarnpkg.com/react/-/react-16.6.3.tgz#25d77c91911d6bbdd23db41e70fb094cc1e0871c"
integrity sha512-zCvmH2vbEolgKxtqXL2wmGCUxUyNheYn/C+PD1YAjfxHC54+MhdruyhO7QieQrYsYeTxrn93PM2y0jRH1zEExw==
@ -14424,14 +14449,6 @@ sax@^1.2.4, sax@~1.2.1, sax@~1.2.4:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
scheduler@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.11.0.tgz#def1f1bfa6550cc57981a87106e65e8aea41a6b5"
integrity sha512-MAYbBfmiEHxF0W+c4CxMpEqMYK+rYF584VP/qMKSiHM6lTkBKKYOJaDiSILpJHla6hBOsVd6GucPL46o2Uq3sg==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"
scheduler@^0.11.2:
version "0.11.3"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.11.3.tgz#b5769b90cf8b1464f3f3cfcafe8e3cd7555a2d6b"
@ -16183,7 +16200,7 @@ url@^0.11.0, url@~0.11.0:
punycode "1.3.2"
querystring "0.2.0"
usb@^1.3.3:
usb@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/usb/-/usb-1.5.0.tgz#3e07b23c6dacf06a7c8801ae913926702a818218"
integrity sha512-/0stiQEmweuO2BKv2avzQQ8ypDUjo4Osz5sSEi+d0F4Rc+ddX1xED3uf4Tkelc1eADlfn0JQZYHP0bI7CNDA0Q==

Loading…
Cancel
Save