Browse Source

Merge pull request #881 from LedgerHQ/develop

Prepare for rc.1
master
Gaëtan Renaudeau 7 years ago
committed by GitHub
parent
commit
12384c6217
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. BIN
      build/icon.icns
  2. 6
      electron-builder.yml
  3. 3
      scripts/compile.sh
  4. 13
      scripts/dist.sh
  5. 13
      src/api/network.js
  6. 6
      src/commands/libcoreSignAndBroadcast.js
  7. 6
      src/components/SettingsPage/sections/About.js
  8. 127
      src/components/modals/ReleaseNotes.js
  9. 114
      src/components/modals/ReleaseNotes/ReleaseNotesBody.js
  10. 16
      src/components/modals/ReleaseNotes/index.js
  11. 4
      src/components/modals/UpdateFirmware/Disclaimer.js
  12. 4
      src/config/constants.js
  13. 1
      src/config/support.js
  14. 13
      src/helpers/anonymizer.js
  15. 3
      src/helpers/apps/installApp.js
  16. 3
      src/helpers/apps/uninstallApp.js
  17. 23
      src/helpers/deviceAccess.js
  18. 11
      src/helpers/init-libcore.js
  19. 4
      src/main/app.js
  20. 31
      static/i18n/en/app.yml
  21. 9
      static/i18n/en/errors.yml
  22. 2
      static/i18n/fr/app.yml
  23. 6
      static/i18n/fr/errors.yml
  24. BIN
      static/images/browser-window-icon-512x512.png
  25. 39
      yarn.lock

BIN
build/icon.icns

Binary file not shown.

6
electron-builder.yml

@ -12,6 +12,9 @@ mac:
- dmg
- zip
appImage:
systemIntegration: doNotAsk
linux:
asarUnpack:
- node_modules/@ledgerhq/ledger-core
@ -21,9 +24,6 @@ linux:
- target: AppImage
arch:
- x64
- target: tar.gz
arch:
- x64
win:
artifactName: ${name}-${version}-${os}-${arch}.${ext}

3
scripts/compile.sh

@ -4,8 +4,9 @@ set -e
export GIT_REVISION=`git rev-parse HEAD`
export SENTRY_URL=https://db8f5b9b021048d4a401f045371701cb@sentry.io/274561
export JOBS=max
rm -rf ./node_modules/.cache dist
JOBS=max yarn
yarn
NODE_ENV=production yarn run webpack-cli --mode production --config webpack/internals.config.js
NODE_ENV=production yarn run electron-webpack

13
scripts/dist.sh

@ -1,3 +1,16 @@
#!/bin/bash
# hilarious fix: to make linux icon we have to remove icon.png from build folder
# some context:
# - https://github.com/electron-userland/electron-builder/issues/2577
# - https://github.com/electron-userland/electron-builder/issues/2269
if [[ `uname` == 'Linux' ]]; then
mv build/icon.png /tmp
fi
yarn compile && DEBUG=electron-builder electron-builder
# hilarious fix continuation: put back the icon where it was
if [[ `uname` == 'Linux' ]]; then
mv /tmp/icon.png build
fi

13
src/api/network.js

@ -4,6 +4,7 @@ import { GET_CALLS_RETRY, GET_CALLS_TIMEOUT } from 'config/constants'
import { retry } from 'helpers/promise'
import logger from 'logger'
import { createCustomErrorClass } from 'helpers/errors'
import anonymizer from 'helpers/anonymizer'
export const LedgerAPIErrorWithMessage = createCustomErrorClass('LedgerAPIErrorWithMessage')
export const LedgerAPIError = createCustomErrorClass('LedgerAPIError')
@ -34,12 +35,20 @@ const userFriendlyError = <A>(p: Promise<A>, { url, method, startTime }): Promis
logger.warn("can't parse server result", e)
}
if (msg && msg[0] !== '<') {
errorToThrow = new LedgerAPIErrorWithMessage(msg)
errorToThrow = new LedgerAPIErrorWithMessage(msg, {
status,
url: anonymizer.url(url),
method,
})
}
}
}
if (!errorToThrow) {
errorToThrow = new LedgerAPIError(`LedgerAPIError ${status}`, { status })
errorToThrow = new LedgerAPIError(`LedgerAPIError ${status}`, {
status,
url: anonymizer.url(url),
method,
})
}
logger.networkError({
status,

6
src/commands/libcoreSignAndBroadcast.js

@ -208,13 +208,15 @@ export async function doSignAndBroadcast({
.asBitcoinLikeAccount()
.broadcastRawTransaction(Array.from(Buffer.from(signedTransaction, 'hex')))
const fee = builded.getFees().toLong()
// NB we don't check isCancelled() because the broadcast is not cancellable now!
onOperationBroadcasted({
id: `${account.xpub}-${txHash}-OUT`,
hash: txHash,
type: 'OUT',
value: transaction.amount,
fee: 0,
value: transaction.amount + fee,
fee,
blockHash: null,
blockHeight: null,
senders: [account.freshAddress],

6
src/components/SettingsPage/sections/About.js

@ -48,6 +48,12 @@ class SectionHelp extends PureComponent<Props> {
desc={t('app:settings.help.termsDesc')}
url={urls.terms}
/>
<AboutRowItem
title={t('app:settings.help.privacy')}
desc={t('app:settings.help.privacyDesc')}
url={urls.privacyPolicy}
/>
</Body>
</Section>
)

127
src/components/modals/ReleaseNotes.js

@ -1,127 +0,0 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import styled from 'styled-components'
import network from 'api/network'
import { MODAL_RELEASES_NOTES } from 'config/constants'
import Modal, { ModalBody, ModalTitle, ModalContent, ModalFooter } from 'components/base/Modal'
import Button from 'components/base/Button'
import Box from 'components/base/Box'
import GrowScroll from 'components/base/GrowScroll'
import Text from 'components/base/Text'
import Spinner from 'components/base/Spinner'
import GradientBox from 'components/GradientBox'
import TrackPage from 'analytics/TrackPage'
import Markdow, { Notes } from 'components/base/Markdown'
import type { T } from 'types/common'
type Props = {
t: T,
}
type State = {
markdown: ?string,
}
const Title = styled(Text).attrs({
ff: 'Museo Sans',
fontSize: 5,
color: 'dark',
})``
class ReleaseNotes extends PureComponent<Props, State> {
state = {
markdown: null,
}
loading = false
fetchNotes = version => {
if (!this.loading) {
this.loading = true
network({
method: 'GET',
url: `https://api.github.com/repos/LedgerHQ/ledger-live-desktop/releases/tags/v${version}`,
})
.then(response => {
const { body } = response.data
this.setState(
{
markdown: body,
},
() => {
this.loading = false
},
)
})
.catch(() => {
this.setState(
{
markdown: this.props.t('app:common.error.load'),
},
() => {
this.loading = false
},
)
})
}
}
render() {
const { t } = this.props
const renderBody = ({ data, onClose }) => {
const version = data
const { markdown } = this.state
let content
if (markdown === null) {
this.fetchNotes(version)
content = (
<Box horizontal alignItems="center">
<Spinner
size={32}
style={{
margin: 'auto',
}}
/>
</Box>
)
} else {
content = (
<Notes>
<Title>{t('app:releaseNotes.version', { versionNb: version })}</Title>
<Markdow>{markdown}</Markdow>
</Notes>
)
}
return (
<ModalBody onClose={onClose}>
<TrackPage category="Modal" name="ReleaseNotes" />
<ModalTitle>{t('app:releaseNotes.title')}</ModalTitle>
<ModalContent relative style={{ height: 500 }} px={0} pb={0}>
<GrowScroll px={5} pb={8}>
{content}
</GrowScroll>
<GradientBox />
</ModalContent>
<ModalFooter horizontal justifyContent="flex-end">
<Button onClick={onClose} primary>
{t('app:common.continue')}
</Button>
</ModalFooter>
</ModalBody>
)
}
return <Modal name={MODAL_RELEASES_NOTES} render={renderBody} />
}
}
export default translate()(ReleaseNotes)

114
src/components/modals/ReleaseNotes/ReleaseNotesBody.js

@ -0,0 +1,114 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import styled from 'styled-components'
import network from 'api/network'
import Button from 'components/base/Button'
import Box from 'components/base/Box'
import GrowScroll from 'components/base/GrowScroll'
import Text from 'components/base/Text'
import Spinner from 'components/base/Spinner'
import GradientBox from 'components/GradientBox'
import TrackPage from 'analytics/TrackPage'
import Markdow, { Notes } from 'components/base/Markdown'
import { ModalBody, ModalTitle, ModalContent, ModalFooter } from 'components/base/Modal'
import type { T } from 'types/common'
type Props = {
version: string,
onClose: () => void,
t: T,
}
type State = {
markdown: ?string,
}
const Title = styled(Text).attrs({
ff: 'Museo Sans',
fontSize: 5,
color: 'dark',
})``
class ReleaseNotesBody extends PureComponent<Props, State> {
state = {
markdown: null,
}
componentDidMount() {
const { version } = this.props
this.fetchNotes(version)
}
fetchNotes = async (version: string) => {
try {
const {
data: { body },
} = await network({
method: 'GET',
url: `https://api.github.com/repos/LedgerHQ/ledger-live-desktop/releases/tags/v${version}`,
})
if (body) {
this.setState({ markdown: body })
} else {
this.setState({ markdown: this.props.t('app:common.error.load') })
}
} catch (error) {
this.setState({ markdown: this.props.t('app:common.error.load') })
}
}
renderContent = () => {
const { markdown } = this.state
const { t } = this.props
const { version } = this.props
if (markdown) {
return (
<Notes>
<Title>{t('app:releaseNotes.version', { versionNb: version })}</Title>
<Markdow>{markdown}</Markdow>
</Notes>
)
}
return (
<Box horizontal alignItems="center">
<Spinner
size={32}
style={{
margin: 'auto',
}}
/>
</Box>
)
}
render() {
const { onClose, t } = this.props
return (
<ModalBody onClose={onClose}>
<TrackPage category="Modal" name="ReleaseNotes" />
<ModalTitle>{t('app:releaseNotes.title')}</ModalTitle>
<ModalContent relative style={{ height: 500 }} px={0} pb={0}>
<GrowScroll px={5} pb={8}>
{this.renderContent()}
</GrowScroll>
<GradientBox />
</ModalContent>
<ModalFooter horizontal justifyContent="flex-end">
<Button onClick={onClose} primary>
{t('app:common.continue')}
</Button>
</ModalFooter>
</ModalBody>
)
}
}
export default translate()(ReleaseNotesBody)

16
src/components/modals/ReleaseNotes/index.js

@ -0,0 +1,16 @@
// @flow
import React from 'react'
import { MODAL_RELEASES_NOTES } from 'config/constants'
import Modal from 'components/base/Modal'
import ReleaseNotesBody from './ReleaseNotesBody'
const ReleaseNotesModal = () => (
<Modal
name={MODAL_RELEASES_NOTES}
render={({ data, onClose }) => <ReleaseNotesBody version={data} onClose={onClose} />}
/>
)
export default ReleaseNotesModal

4
src/components/modals/UpdateFirmware/Disclaimer.js

@ -48,9 +48,9 @@ class DisclaimerModal extends PureComponent<Props, State> {
<ModalContent>
<Text ff="Open Sans|Regular" fontSize={4} color="graphite" align="center">
<Trans i18nKey="app:manager.firmware.disclaimerTitle">
You are about to install the latest
You are about to install
<Text ff="Open Sans|SemiBold" color="dark">
{`firmware ${firmware ? getCleanVersion(firmware.name) : ''}`}
{`firmware version ${firmware ? getCleanVersion(firmware.name) : ''}`}
</Text>
</Trans>
</Text>

4
src/config/constants.js

@ -31,7 +31,7 @@ export const GENUINE_CACHE_DELAY = intFromEnv('GENUINE_CACHE_DELAY', 1000)
export const GENUINE_TIMEOUT = intFromEnv('GENUINE_TIMEOUT', 120 * 1000)
export const GET_CALLS_RETRY = intFromEnv('GET_CALLS_RETRY', 2)
export const GET_CALLS_TIMEOUT = intFromEnv('GET_CALLS_TIMEOUT', 30 * 1000)
export const LISTEN_DEVICES_POLLING_INTERVAL = intFromEnv('LISTEN_DEVICES_POLLING_INTERVAL', 100)
export const LISTEN_DEVICES_POLLING_INTERVAL = intFromEnv('LISTEN_DEVICES_POLLING_INTERVAL', 1000)
export const OUTDATED_CONSIDERED_DELAY = intFromEnv('OUTDATED_CONSIDERED_DELAY', 5 * 60 * 1000)
export const SYNC_ALL_INTERVAL = 120 * 1000
export const SYNC_BOOT_DELAY = 2 * 1000
@ -47,7 +47,7 @@ export const LEDGER_COUNTERVALUES_API = stringFromEnv(
)
export const LEDGER_REST_API_BASE = stringFromEnv(
'LEDGER_REST_API_BASE',
'https://api.ledgerwallet.com/',
'https://explorers.api.live.ledger.com/',
)
export const MANAGER_API_BASE = stringFromEnv(
'MANAGER_API_BASE',

1
src/config/support.js

@ -17,4 +17,5 @@ export const urls = {
// should join and generalize naming for the same urls once defined
receiveFlowContactSupport:
'https://support.ledgerwallet.com/hc/en-us/requests/new?ticket_form_id=248165',
privacyPolicy: 'https://www.ledgerwallet.com/privacy-policy',
}

13
src/helpers/anonymizer.js

@ -16,25 +16,28 @@ function filepathReplace(path: string) {
return path.replace(cwd, '.').replace(configDir, '$USER_DATA')
}
function filepathRecursiveReplacer(obj: mixed) {
function filepathRecursiveReplacer(obj: mixed, seen: Array<*>) {
if (obj && typeof obj === 'object') {
seen.push(obj)
if (Array.isArray(obj)) {
for (let i = 0; i < obj.length; i++) {
const item = obj[i]
if (seen.indexOf(item) !== -1) return
if (typeof item === 'string') {
obj[i] = filepathReplace(item)
} else {
filepathRecursiveReplacer(item)
filepathRecursiveReplacer(item, seen)
}
}
} else {
for (const k in obj) {
if (obj.hasOwnProperty(k)) {
if (typeof obj.hasOwnProperty === 'function' && obj.hasOwnProperty(k)) {
const value = obj[k]
if (seen.indexOf(value) !== -1) return
if (typeof value === 'string') {
obj[k] = filepathReplace(value)
} else {
filepathRecursiveReplacer(obj[k])
filepathRecursiveReplacer(obj[k], seen)
}
}
}
@ -52,5 +55,5 @@ export default {
filepath: filepathReplace,
filepathRecursiveReplacer,
filepathRecursiveReplacer: (obj: mixed) => filepathRecursiveReplacer(obj, []),
}

3
src/helpers/apps/installApp.js

@ -9,7 +9,6 @@ import type { LedgerScriptParams } from 'helpers/common'
import { createCustomErrorClass } from '../errors'
const ManagerUnexpectedError = createCustomErrorClass('ManagerUnexpected')
const ManagerNotEnoughSpaceError = createCustomErrorClass('ManagerNotEnoughSpace')
const ManagerDeviceLockedError = createCustomErrorClass('ManagerDeviceLocked')
const ManagerAppAlreadyInstalledError = createCustomErrorClass('ManagerAppAlreadyInstalled')
@ -27,7 +26,7 @@ function remapError(promise) {
case e.message.endsWith('6a83'):
throw new ManagerAppRelyOnBTCError()
default:
throw new ManagerUnexpectedError(e.message, { msg: e.message })
throw e
}
})
}

3
src/helpers/apps/uninstallApp.js

@ -8,7 +8,6 @@ import { createDeviceSocket } from 'helpers/socket'
import type { LedgerScriptParams } from 'helpers/common'
import { createCustomErrorClass } from '../errors'
const ManagerUnexpectedError = createCustomErrorClass('ManagerUnexpectedError')
const ManagerDeviceLockedError = createCustomErrorClass('ManagerDeviceLocked')
const ManagerUninstallBTCDep = createCustomErrorClass('ManagerUninstallBTCDep')
@ -20,7 +19,7 @@ function remapError(promise) {
case e.message.endsWith('6a83'):
throw new ManagerUninstallBTCDep()
default:
throw new ManagerUnexpectedError(e.message, { msg: e.message })
throw e
}
})
}

23
src/helpers/deviceAccess.js

@ -22,17 +22,26 @@ const mapError = e => {
let queue = Promise.resolve()
let busy = false
TransportNodeHid.setListenDevicesPollingSkip(() => busy)
export const withDevice: WithDevice = devicePath => job => {
const p = queue.then(async () => {
const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 1 })
if (DEBUG_DEVICE) {
t.setDebugMode(true)
}
busy = true
try {
const res = await job(t).catch(mapError)
return res
const t = await retry(() => TransportNodeHid.open(devicePath), { maxRetry: 1 })
if (DEBUG_DEVICE) {
t.setDebugMode(true)
}
try {
const res = await job(t).catch(mapError)
return res
} finally {
await t.close()
}
} finally {
await t.close()
busy = false
}
})

11
src/helpers/init-libcore.js

@ -13,8 +13,9 @@ const fs = require('fs')
const MAX_RANDOM = 2684869021
// increment this number to "clear" sqlite db (it will use another path :D)
const DB_VERSION = 1
const core = new lib.NJSLedgerCore()
const stringVersion = core.getStringVersion()
const sqlitePrefix = `v${stringVersion.split('.')[0]}`
const bytesArrayToString = (bytesArray = []) => Buffer.from(bytesArray).toString()
@ -151,15 +152,15 @@ const instanciateWalletPool = ({ dbPath }) => {
const NJSPathResolver = new lib.NJSPathResolver({
resolveLogFilePath: pathToResolve => {
const hash = pathToResolve.replace(/\//g, '__')
return path.resolve(dbPath, `./log_file_${DB_VERSION}_${hash}`)
return path.resolve(dbPath, `./log_file_${sqlitePrefix}_${hash}`)
},
resolvePreferencesPath: pathToResolve => {
const hash = pathToResolve.replace(/\//g, '__')
return path.resolve(dbPath, `./preferences_${DB_VERSION}_${hash}`)
return path.resolve(dbPath, `./preferences_${sqlitePrefix}_${hash}`)
},
resolveDatabasePath: pathToResolve => {
const hash = pathToResolve.replace(/\//g, '__')
return path.resolve(dbPath, `./database_${DB_VERSION}_${hash}`)
return path.resolve(dbPath, `./database_${sqlitePrefix}_${hash}`)
},
})

4
src/main/app.js

@ -11,6 +11,7 @@ import {
import menu from 'main/menu'
import db from 'helpers/db'
import { i } from 'helpers/staticPath'
import { terminateAllTheThings } from './terminator'
@ -65,6 +66,9 @@ const saveWindowSettings = window => {
}
const defaultWindowOptions = {
// see https://github.com/electron-userland/electron-builder/issues/2269
icon: i('browser-window-icon-512x512.png'),
backgroundColor: '#fff',
webPreferences: {
devTools,

31
static/i18n/en/app.yml

@ -220,27 +220,27 @@ manager:
installed: 'Firmware version {{version}}'
titleNano: Ledger Nano S
titleBlue: Ledger Blue
update: Update firmware
continue: Continue update
update: Update
continue: Continue
latest: 'Firmware version {{version}} is available'
disclaimerTitle: 'You are about to install the latest <1><0>firmware {{version}}</0></1>'
disclaimerAppDelete: Please note that all the apps installed on your device will be deleted.
disclaimerAppReinstall: You will be able to re-install your apps after the firmware update
disclaimerTitle: 'You are about to install <1><0>firmware version {{version}}</0></1>'
disclaimerAppDelete: Apps installed on your device have to re-installed after the update.
disclaimerAppReinstall: "This does not affect your crypto assets in the blockchain."
modal:
steps:
idCheck: Identifier check
updateMCU: Update MCU
idCheck: Identifier
updateMCU: MCU update
confirm: Confirmation
installing: Firmware updating...
confirmIdentifier: Confirm identifier
confirmIdentifierText: Please confirm identifier on your Device. Be sure the identifier is the same as below
confirmIdentifier: Verify the identifier
confirmIdentifierText: Verify that the identifier on your device is the same as the identifier below. Press the right button to confirm.
identifier: Identifier
mcuTitle: Updating MCU
mcuFirst: Unplug your device from your computer
mcuSecond: Press and hold left button and plug your device until the processing screen appears
mcuFirst: Disconnect the USB cable from your device
mcuSecond: Press the left button and hold it while you reconnect the USB cable until the processing screen appears
mcuPin: If asked on device, please enter your pin code to finish the process
successTitle: Firmware has been updated with success
successText: You can now re-install your applications on your device
successTitle: Firmware updated
successText: You may re-install the apps on your device
title: Manager
subtitle: Install or uninstall apps on your device
device:
@ -369,9 +369,8 @@ settings: # Always ensure descriptions carry full stops (.)
faqDesc: A problem? Get help with Ledger Live, Ledger devices, supported crypto assets and apps.
terms: Terms and conditions
termsDesc: By using Ledger Live you are deemed to have accepted our terms and conditions.
#privacy: Privacy policy
#privacyDesc: Refer to our privacy policy to learn what personal data we collect, and why and how we use it.
#privacyURL: 'https://www.ledgerwallet.com/privacy-policy'
privacy: Privacy policy
privacyDesc: Refer to our privacy policy to learn what personal data we collect, and why and how we use it.
hardResetModal:
title: Reset Ledger Live
desc: Erase all Ledger Live data stored on your computer, including your accounts, transaction history and settings. The private keys to access your crypto assets in the blockchain remain secure on your Ledger device and on your Recovery sheet.

9
static/i18n/en/errors.yml

@ -23,6 +23,12 @@ DisconnectedDevice:
Error:
title: '{{message}}'
description: Something went wrong. Please retry or contact us.
"Invariant Violation":
title: '{{message}}'
description: Something went wrong. Please retry or contact us.
InternalError:
title: '{{message}}'
description: Something went wrong. Please retry or contact us.
TypeError:
title: '{{message}}'
description: Something went wrong. Please retry or contact us.
@ -65,9 +71,6 @@ ManagerDeviceLocked:
ManagerNotEnoughSpace:
title: Sorry, insufficient device storage
description: Uninstall some apps to increase available storage and try again.
ManagerUnexpected:
title: That's unexpected ({{msg}}) #(Manager: {{msg}})
description: Please try again.
ManagerUninstallBTCDep:
title: Sorry, Bitcoin is required # include {{currencyName}}
description: First uninstall apps that depend on Bitcoin.

2
static/i18n/fr/app.yml

@ -366,6 +366,8 @@ settings:
faqDesc: A problem? Get help with Ledger Live, Ledger devices, supported crypto assets and apps.
terms: Terms and conditions
termsDesc: By using Ledger Live you are deemed to have accepted our terms and conditions.
privacy: Privacy policy
privacyDesc: Refer to our privacy policy to learn what personal data we collect, and why and how we use it.
hardResetModal:
title: Reset Ledger Live
desc: Erase all Ledger Live data stored on your computer, including your accounts, transaction history and settings. The private keys to access your crypto assets in the blockchain remain secure on your Ledger device and on your Recovery sheet.

6
static/i18n/fr/errors.yml

@ -5,6 +5,9 @@ BtcUnmatchedApp:
DeviceNotGenuine:
title: Possibly not genuine
description: 'Request Ledger Support assistance.'
DeviceGenuineSocketEarlyClose:
title: Sorry, try again (genuine-close)
description:
DeviceSocketFail:
title: Oops, try again
description: 'Some connection failed, so please try again.'
@ -62,9 +65,6 @@ ManagerDeviceLocked:
ManagerNotEnoughSpace:
title: Sorry, insufficient device storage
description: Uninstall some apps to increase available storage and try again.
ManagerUnexpected:
title: That's unexpected ({{msg}})
description: Please try again.
ManagerUninstallBTCDep:
title: Sorry, Bitcoin is required
description: First uninstall apps that depend on Bitcoin.

BIN
static/images/browser-window-icon-512x512.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

39
yarn.lock

@ -1501,7 +1501,14 @@
"@ledgerhq/hw-transport" "^4.15.0"
bip32-path "0.4.2"
"@ledgerhq/hw-transport-node-hid@^4.13.0", "@ledgerhq/hw-transport-node-hid@^4.7.6":
"@ledgerhq/hw-transport-node-hid@^4.13.0":
version "4.18.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.18.0.tgz#39ab0f9300c755f6b33f28dda22e30677882b6be"
dependencies:
"@ledgerhq/hw-transport" "^4.15.0"
node-hid "^0.7.2"
"@ledgerhq/hw-transport-node-hid@^4.7.6":
version "4.16.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.16.0.tgz#de8d7ffd37e01c77aed566d8c534fe3937c3c35c"
dependencies:
@ -9849,7 +9856,7 @@ mute-stream@0.0.7, mute-stream@~0.0.4:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
nan@^2.2.1, nan@^2.6.2, nan@^2.9.2:
nan@^2.10.0, 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"
@ -9956,12 +9963,12 @@ node-gyp@^3.6.0, node-gyp@^3.6.2:
which "1"
node-hid@^0.7.2:
version "0.7.2"
resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-0.7.2.tgz#15025cdea2e9756aca2de7266529996d40e52c56"
version "0.7.3"
resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-0.7.3.tgz#736e9a4dee5eec96c20fbe301e0311bb185cb2f4"
dependencies:
bindings "^1.3.0"
nan "^2.6.2"
prebuild-install "^2.2.2"
nan "^2.10.0"
prebuild-install "^4.0.0"
node-int64@^0.4.0:
version "0.4.0"
@ -11279,6 +11286,26 @@ prebuild-install@^2.0.0, prebuild-install@^2.2.2:
tunnel-agent "^0.6.0"
which-pm-runs "^1.0.0"
prebuild-install@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-4.0.0.tgz#206ce8106ce5efa4b6cf062fc8a0a7d93c17f3a8"
dependencies:
detect-libc "^1.0.3"
expand-template "^1.0.2"
github-from-package "0.0.0"
minimist "^1.2.0"
mkdirp "^0.5.1"
node-abi "^2.2.0"
noop-logger "^0.1.1"
npmlog "^4.0.1"
os-homedir "^1.0.1"
pump "^2.0.1"
rc "^1.1.6"
simple-get "^2.7.0"
tar-fs "^1.13.0"
tunnel-agent "^0.6.0"
which-pm-runs "^1.0.0"
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"

Loading…
Cancel
Save