diff --git a/package.json b/package.json index 4d1a1526..eca87bbd 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "test-e2e": "jest test-e2e", "test-sync": "bash test-e2e/sync/launch.sh", "prettier": "prettier --write \"{src,webpack,.storybook,test-e2e}/**/*.{js,json}\"", - "ci": "yarn lint && yarn flow && yarn prettier && yarn test", + "ci": "yarn check --integrity && ./scripts/check-no-dups.sh && yarn lint && yarn flow && yarn prettier && yarn test", "storybook": "NODE_ENV=development STORYBOOK_ENV=1 start-storybook -s ./static -p 4444", "publish-storybook": "bash ./scripts/legacy/publish-storybook.sh", "reset-files": "bash ./scripts/legacy/reset-files.sh" @@ -35,11 +35,12 @@ } }, "dependencies": { - "@ledgerhq/hw-app-btc": "^4.34.0", - "@ledgerhq/hw-app-eth": "^4.32.0", - "@ledgerhq/hw-app-xrp": "^4.32.0", - "@ledgerhq/hw-transport": "^4.32.0", - "@ledgerhq/hw-transport-node-hid": "^4.32.0", + "@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/live-common": "4.15.0-beta.0", "animated": "^0.2.2", @@ -183,7 +184,8 @@ "webpack": "^4.6.0", "webpack-bundle-analyzer": "^2.11.1", "webpack-cli": "^2.0.14", - "yaml-loader": "^0.5.0" + "yaml-loader": "^0.5.0", + "yarn-deduplicate": "^1.1.1" }, "engines": { "node": ">=8.9.0 <=8.15.0", diff --git a/scripts/check-no-dups.sh b/scripts/check-no-dups.sh new file mode 100755 index 00000000..3e93cf32 --- /dev/null +++ b/scripts/check-no-dups.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +yarn-deduplicate -l | grep \@ledgerhq + +if [ $? -eq 0 ]; then + echo "Found duplicates in @ledgerhq/* – fix it with yarn-deduplicate" + exit 1 +fi + +yarn-deduplicate -l | grep \"react + +if [ $? -eq 0 ]; then + echo "Found duplicates in some react packages – fix it with yarn-deduplicate" + exit 1 +fi diff --git a/src/bridge/BridgeSyncContext.js b/src/bridge/BridgeSyncContext.js index b3211ffb..0e93cf44 100644 --- a/src/bridge/BridgeSyncContext.js +++ b/src/bridge/BridgeSyncContext.js @@ -100,6 +100,7 @@ class Provider extends Component { next() }, error: error => { + logger.critical(error) this.props.setAccountSyncState(accountId, { pending: false, error }) next() }, diff --git a/src/bridge/EthereumJSBridge.js b/src/bridge/EthereumJSBridge.js index 145d6524..f7948a46 100644 --- a/src/bridge/EthereumJSBridge.js +++ b/src/bridge/EthereumJSBridge.js @@ -129,7 +129,7 @@ function isRecipientValid(currency, recipient) { } // Returns a warning if we detect a non-eip address -function getRecipientWarning(currency, recipient) { +function getRecipientWarning(account, recipient) { if (!recipient.match(/^0x[0-9a-fA-F]{40}$/)) return null const slice = recipient.substr(2) const isFullUpper = slice === slice.toUpperCase() @@ -420,9 +420,9 @@ const EthereumBridge: WalletBridge = { pullMoreOperations: () => Promise.resolve(a => a), // NOT IMPLEMENTED - isRecipientValid: (currency, recipient) => Promise.resolve(isRecipientValid(currency, recipient)), - getRecipientWarning: (currency, recipient) => - Promise.resolve(getRecipientWarning(currency, recipient)), + isRecipientValid: (account, recipient) => Promise.resolve(isRecipientValid(account, recipient)), + getRecipientWarning: (account, recipient) => + Promise.resolve(getRecipientWarning(account, recipient)), createTransaction: () => ({ amount: BigNumber(0), diff --git a/src/bridge/LibcoreBridge.js b/src/bridge/LibcoreBridge.js index e9d2ce8b..e6fb6d40 100644 --- a/src/bridge/LibcoreBridge.js +++ b/src/bridge/LibcoreBridge.js @@ -60,15 +60,15 @@ const EditAdvancedOptions = ({ onChange, value }: EditProps) => ( const recipientValidLRU = LRU({ max: 100 }) -const isRecipientValid = (currency, recipient) => { - const key = `${currency.id}_${recipient}` +const isRecipientValid = (account, recipient) => { + const key = `${account.currency.id}_${recipient}` let promise = recipientValidLRU.get(key) if (promise) return promise if (!recipient) return Promise.resolve(false) promise = libcoreValidAddress .send({ address: recipient, - currencyId: currency.id, + currencyId: account.currency.id, }) .toPromise() recipientValidLRU.set(key, promise) @@ -83,7 +83,7 @@ const getFeesKey = (a, t) => }` const getFees = async (a, transaction) => { - const isValid = await isRecipientValid(a.currency, transaction.recipient) + const isValid = await isRecipientValid(a, transaction.recipient) if (!isValid) return null const key = getFeesKey(a, transaction) let promise = feesLRU.get(key) diff --git a/src/bridge/RippleJSBridge.js b/src/bridge/RippleJSBridge.js index 53b105b5..a6d16ef6 100644 --- a/src/bridge/RippleJSBridge.js +++ b/src/bridge/RippleJSBridge.js @@ -34,6 +34,7 @@ import { NotEnoughBalance, FeeNotLoaded, NotEnoughBalanceBecauseDestinationNotCreated, + InvalidAddressBecauseDestinationIsAlsoSource, } from '@ledgerhq/errors' import type { WalletBridge, EditProps } from './types' @@ -136,15 +137,23 @@ async function signAndBroadcast({ a, t, deviceId, isCancelled, onSigned, onOpera } } -function isRecipientValid(recipient) { +function isRecipientValid(account, recipient) { try { bs58check.decode(recipient) - return true + + return !(account && account.freshAddress === recipient) } catch (e) { return false } } +function getRecipientWarning(account, recipient) { + if (account.freshAddress === recipient) { + return new InvalidAddressBecauseDestinationIsAlsoSource() + } + return null +} + function mergeOps(existing: Operation[], newFetched: Operation[]) { const ids = existing.map(o => o.id) const all = existing.concat(newFetched.filter(o => !ids.includes(o.id))) @@ -270,7 +279,7 @@ const getServerInfo = (map => endpointConfig => { })({}) const recipientIsNew = async (endpointConfig, recipient) => { - if (!isRecipientValid(recipient)) return false + if (!isRecipientValid(null, recipient)) return false const api = apiForEndpointConfig(RippleAPI, endpointConfig) try { await api.connect() @@ -505,8 +514,9 @@ const RippleJSBridge: WalletBridge = { pullMoreOperations: () => Promise.resolve(a => a), // FIXME not implemented - isRecipientValid: (currency, recipient) => Promise.resolve(isRecipientValid(recipient)), - getRecipientWarning: () => Promise.resolve(null), + isRecipientValid: (account, recipient) => Promise.resolve(isRecipientValid(account, recipient)), + getRecipientWarning: (account, recipient) => + Promise.resolve(getRecipientWarning(account, recipient)), createTransaction: () => ({ amount: BigNumber(0), diff --git a/src/bridge/makeMockBridge.js b/src/bridge/makeMockBridge.js index 93080000..169bbd4d 100644 --- a/src/bridge/makeMockBridge.js +++ b/src/bridge/makeMockBridge.js @@ -128,7 +128,7 @@ function makeMockBridge(opts?: Opts): WalletBridge<*> { } }, - isRecipientValid: (currency, recipient) => Promise.resolve(recipient.length > 0), + isRecipientValid: (account, recipient) => Promise.resolve(recipient.length > 0), getRecipientWarning: () => Promise.resolve(null), createTransaction: () => ({ diff --git a/src/bridge/types.js b/src/bridge/types.js index eea8cefa..64835064 100644 --- a/src/bridge/types.js +++ b/src/bridge/types.js @@ -52,8 +52,8 @@ export interface WalletBridge { // count is user's desired number of ops to pull (but implementation can decide to ignore it or not) pullMoreOperations(initialAccount: Account, count: number): Promise<(Account) => Account>; - isRecipientValid(currency: Currency, recipient: string): Promise; - getRecipientWarning(currency: Currency, recipient: string): Promise; + isRecipientValid(account: Account, recipient: string): Promise; + getRecipientWarning(account: Account, recipient: string): Promise; // Related to send funds: diff --git a/src/commands/.DS_Store b/src/commands/.DS_Store deleted file mode 100644 index 5008ddfc..00000000 Binary files a/src/commands/.DS_Store and /dev/null differ diff --git a/src/components/ManagerPage/AppsList.js b/src/components/ManagerPage/AppsList.js index b97fe08f..8d34ab3a 100644 --- a/src/components/ManagerPage/AppsList.js +++ b/src/components/ManagerPage/AppsList.js @@ -40,15 +40,35 @@ const mapStateToProps = state => ({ const List = styled(Box).attrs({ horizontal: true, - m: -3, })` flex-wrap: wrap; + + > * { + width: calc(50% - 10px); + margin-bottom: 20px; + &:nth-child(even) { + margin-left: 20px; + } + + @media (max-width: 1000px) { + width: 100%; + &:nth-child(even) { + margin-left: 0; + } + } + } ` const ICONS_FALLBACK = { bitcoin_testnet: 'bitcoin', } +const CATALOG_INFO_ICON = ( + + + +) + type Status = 'loading' | 'idle' | 'busy' | 'success' | 'error' type Mode = 'home' | 'installing' | 'uninstalling' @@ -80,6 +100,20 @@ const LoadingApp = () => ( const loadingApp = +const FAKE_LIST = ( + + {loadingApp} + {loadingApp} + {loadingApp} + {loadingApp} + {loadingApp} + {loadingApp} + {loadingApp} + {loadingApp} + {loadingApp} + +) + class AppsList extends PureComponent { state = { status: 'loading', @@ -272,22 +306,16 @@ class AppsList extends PureComponent { )} {this.renderModal()} - {!appsLoaded && ( - - - - {loadingApp} - {loadingApp} - {loadingApp} - {loadingApp} - {loadingApp} - {loadingApp} - {loadingApp} - {loadingApp} - {loadingApp} - - - )} + {!appsLoaded && FAKE_LIST} + + ) + } + + renderTooltip = () => { + const { t } = this.props + return ( + + {t('manager.apps.help')} ) } @@ -296,24 +324,12 @@ class AppsList extends PureComponent { const { t } = this.props return ( - - - - {t('manager.apps.all')} - ( - - {t('manager.apps.help')} - - )} - > - - - - - - {this.renderList()} + + + {t('manager.apps.all')} + {CATALOG_INFO_ICON} + {this.renderList()} ) } diff --git a/src/components/ManagerPage/ManagerApp.js b/src/components/ManagerPage/ManagerApp.js index 1f214de8..a5de94d4 100644 --- a/src/components/ManagerPage/ManagerApp.js +++ b/src/components/ManagerPage/ManagerApp.js @@ -14,15 +14,12 @@ import Button from 'components/base/Button' export const Container = styled(Box).attrs({ horizontal: true, - my: 2, - mx: 3, p: 4, bg: 'white', boxShadow: p => (p.noShadow ? -1 : 0), borderRadius: 4, flow: 2, })` - width: calc(50% - 30px); line-height: normal; ` diff --git a/src/components/Onboarding/steps/GenuineCheck/GenuineCheckUnavailable.js b/src/components/Onboarding/steps/GenuineCheck/GenuineCheckUnavailable.js index b5a0023a..727d59f3 100644 --- a/src/components/Onboarding/steps/GenuineCheck/GenuineCheckUnavailable.js +++ b/src/components/Onboarding/steps/GenuineCheck/GenuineCheckUnavailable.js @@ -31,6 +31,8 @@ export function GenuineCheckUnavailableFooter({ - ) diff --git a/src/components/SelectExchange.js b/src/components/SelectExchange.js index e66cfb84..9424d5f7 100644 --- a/src/components/SelectExchange.js +++ b/src/components/SelectExchange.js @@ -87,7 +87,7 @@ class SelectExchange extends Component< this.setState({ exchanges, isLoading: false }) } } catch (error) { - logger.error(error) + logger.critical(error) if (!this._unmounted && this._loadId === _loadId) { this.setState({ error, isLoading: false }) } diff --git a/src/components/SettingsPage/RepairDeviceButton.js b/src/components/SettingsPage/RepairDeviceButton.js index 1a26d384..945a5678 100644 --- a/src/components/SettingsPage/RepairDeviceButton.js +++ b/src/components/SettingsPage/RepairDeviceButton.js @@ -6,6 +6,7 @@ import { connect } from 'react-redux' import { withRouter } from 'react-router' import { translate } from 'react-i18next' import { push } from 'react-router-redux' +import logger from 'logger' import type { T } from 'types/common' import firmwareRepair from 'commands/firmwareRepair' @@ -32,27 +33,38 @@ class RepairDeviceButton extends PureComponent { progress: 0, } + componentWillUnmount() { + if (this.timeout) { + clearTimeout(this.timeout) + } + } + open = () => this.setState({ opened: true, error: null }) sub: * + timeout: * close = () => { if (this.sub) this.sub.unsubscribe() + if (this.timeout) clearTimeout(this.timeout) this.setState({ opened: false, isLoading: false, error: null, progress: 0 }) } repair = (version = null) => { if (this.state.isLoading) return const { push } = this.props - this.setState({ isLoading: true }) + this.timeout = setTimeout(() => this.setState({ isLoading: true }), 500) this.sub = firmwareRepair.send({ version }).subscribe({ next: patch => { this.setState(patch) }, error: error => { + logger.critical(error) + if (this.timeout) clearTimeout(this.timeout) this.setState({ error, isLoading: false, progress: 0 }) }, complete: () => { + if (this.timeout) clearTimeout(this.timeout) this.setState({ opened: false, isLoading: false, progress: 0 }, () => { push('/manager') }) diff --git a/src/components/SettingsPage/sections/Export.js b/src/components/SettingsPage/sections/Export.js index 222f2dde..1680a370 100644 --- a/src/components/SettingsPage/sections/Export.js +++ b/src/components/SettingsPage/sections/Export.js @@ -69,7 +69,10 @@ class SectionExport extends PureComponent { {'+'} - {'button in Accounts'} + {'button in'} + + {'Accounts'} + ), @@ -93,7 +96,13 @@ class SectionExport extends PureComponent { icon: {'3'}, desc: ( - + + {'Scan the'} + + {'LiveQR Code'} + + {'until the loader hits 100%'} + ), }, diff --git a/src/components/modals/AddAccounts/index.js b/src/components/modals/AddAccounts/index.js index 0bd842cf..3c0a7862 100644 --- a/src/components/modals/AddAccounts/index.js +++ b/src/components/modals/AddAccounts/index.js @@ -24,6 +24,7 @@ import { closeModal } from 'reducers/modals' import Modal from 'components/base/Modal' import Stepper from 'components/base/Stepper' import { validateNameEdition } from '@ledgerhq/live-common/lib/account' +import logger from 'logger' import StepChooseCurrency, { StepChooseCurrencyFooter } from './steps/01-step-choose-currency' import StepConnectDevice, { StepConnectDeviceFooter } from './steps/02-step-connect-device' @@ -166,6 +167,9 @@ class AddAccounts extends PureComponent { handleSetCurrency = (currency: ?Currency) => this.setState({ currency }) handleSetScanStatus = (scanStatus: string, err: ?Error = null) => { + if (err) { + logger.critical(err) + } this.setState({ scanStatus, err }) } diff --git a/src/components/modals/Receive/index.js b/src/components/modals/Receive/index.js index 5d73ec95..d937c15b 100644 --- a/src/components/modals/Receive/index.js +++ b/src/components/modals/Receive/index.js @@ -8,6 +8,7 @@ import { createStructuredSelector } from 'reselect' import SyncSkipUnderPriority from 'components/SyncSkipUnderPriority' +import logger from 'logger' import Track from 'analytics/Track' import type { Account } from '@ledgerhq/live-common/lib/types' @@ -141,6 +142,9 @@ class ReceiveModal extends PureComponent { handleChangeAppOpened = (isAppOpened: boolean) => this.setState({ isAppOpened }) handleChangeAddressVerified = (isAddressVerified: boolean, err: ?Error) => { + if (err && err.name !== 'UserRefusedAddress') { + logger.critical(err) + } this.setState({ isAddressVerified, verifyAddressError: err }) } diff --git a/src/components/modals/Send/fields/RecipientField.js b/src/components/modals/Send/fields/RecipientField.js index c2611d68..558061fb 100644 --- a/src/components/modals/Send/fields/RecipientField.js +++ b/src/components/modals/Send/fields/RecipientField.js @@ -53,8 +53,8 @@ class RecipientField extends Component< const { account, bridge, transaction } = this.props const syncId = ++this.syncId const recipient = bridge.getTransactionRecipient(account, transaction) - const isValid = await bridge.isRecipientValid(account.currency, recipient) - const warning = await bridge.getRecipientWarning(account.currency, recipient) + const isValid = await bridge.isRecipientValid(account, recipient) + const warning = await bridge.getRecipientWarning(account, recipient) if (syncId !== this.syncId) return if (this.isUnmounted) return this.setState({ isValid, warning }) @@ -69,9 +69,7 @@ class RecipientField extends Component< if (amount) { t = bridge.editTransactionAmount(account, t, amount) } - const warning = fromQRCode - ? await bridge.getRecipientWarning(account.currency, recipient) - : null + const warning = fromQRCode ? await bridge.getRecipientWarning(account, recipient) : null if (this.isUnmounted) return false if (warning) { // clear the input if field has warning AND has a warning @@ -97,7 +95,7 @@ class RecipientField extends Component< const error = !value || isValid ? QRCodeRefusedReason - : new InvalidAddress(null, { currencyName: account.currency.name }) + : warning || new InvalidAddress(null, { currencyName: account.currency.name }) return ( diff --git a/src/components/modals/Send/index.js b/src/components/modals/Send/index.js index 50c56351..9fc5d3e0 100644 --- a/src/components/modals/Send/index.js +++ b/src/components/modals/Send/index.js @@ -12,6 +12,7 @@ import Track from 'analytics/Track' import { updateAccountWithUpdater } from 'actions/accounts' import { MODAL_SEND } from 'config/constants' import { getBridgeForCurrency } from 'bridge' +import logger from 'logger' import type { WalletBridge } from 'bridge/types' import type { T, Device } from 'types/common' @@ -180,6 +181,9 @@ class SendModal extends PureComponent> { } handleTransactionError = (error: Error) => { + if (!(error instanceof UserRefusedOnDevice)) { + logger.critical(error) + } const stepVerificationIndex = this.STEPS.findIndex(step => step.id === 'verification') if (stepVerificationIndex === -1) return this.setState({ error }) diff --git a/src/components/modals/Send/steps/01-step-amount.js b/src/components/modals/Send/steps/01-step-amount.js index dddbb3e3..fd810e9c 100644 --- a/src/components/modals/Send/steps/01-step-amount.js +++ b/src/components/modals/Send/steps/01-step-amount.js @@ -133,7 +133,7 @@ export class StepAmountFooter extends PureComponent< const totalSpent = await bridge.getTotalSpent(account, transaction) if (syncId !== this.syncId) return const isRecipientValid = await bridge.isRecipientValid( - account.currency, + account, bridge.getTransactionRecipient(account, transaction), ) if (syncId !== this.syncId) return diff --git a/src/components/modals/UpdateFirmware/index.js b/src/components/modals/UpdateFirmware/index.js index 9d2ed400..d48bef1c 100644 --- a/src/components/modals/UpdateFirmware/index.js +++ b/src/components/modals/UpdateFirmware/index.js @@ -11,6 +11,7 @@ import type { FirmwareUpdateContext } from '@ledgerhq/live-common/lib/types/mana import type { StepProps as DefaultStepProps, Step } from 'components/base/Stepper' import type { ModalStatus } from 'components/ManagerPage/FirmwareUpdate' +import logger from 'logger' import { FreezeDeviceChangeEvents } from '../../ManagerPage/HookDeviceChange' import StepFullFirmwareInstall from './steps/01-step-install-full-firmware' @@ -82,7 +83,10 @@ class UpdateModal extends PureComponent { t: this.props.t, }) - setError = (e: Error) => this.setState({ error: e }) + setError = (e: Error) => { + logger.critical(e) + this.setState({ error: e }) + } handleReset = () => this.setState({ stepId: 'idCheck', error: null, nonce: this.state.nonce++ }) diff --git a/static/i18n/en/app.json b/static/i18n/en/app.json index 5a77c007..53f41440 100644 --- a/static/i18n/en/app.json +++ b/static/i18n/en/app.json @@ -366,10 +366,10 @@ "modal": { "button": "Done", "title": "Scan to export to mobile", - "listTitle": "To import accounts on your Ledger Live Mobile app:", - "step1": "Tap the <1><0>+ button in Accounts", + "listTitle": "On the Ledger Live mobile app:", + "step1": "Tap the <1><0>+ button in <3><0>Accounts", "step2": "Tap <1><0>Import desktop accounts", - "step3": "Scan until the loader hits 100%" + "step3": "Scan the <1><0>LiveQR code until the loader hits 100%" } }, "display": { @@ -783,7 +783,7 @@ "description": "Please retry. Interacting with Ledger's API server went wrong." }, "LedgerAPIErrorWithMessage": { - "title": "Oops, {{message}}", + "title": "{{message}}", "description": "Please retry or contact Ledger Support" }, "LedgerAPINotAvailable": { @@ -900,6 +900,9 @@ "InvalidAddress": { "title": "This is not a valid {{currencyName}} address" }, + "InvalidAddressBecauseDestinationIsAlsoSource": { + "title": "Recipient address is the same as the sender address" + }, "CantOpenDevice": { "title": "Oops, couldn’t connect to device", "description": "Device detected but connection failed. Please try again or contact us if the problem persists." @@ -919,4 +922,4 @@ "description": "Please contact Ledger Support" } } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 9a55d7e3..ae73d4c3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1677,56 +1677,48 @@ camelcase "^5.0.0" prettier "^1.13.7" -"@ledgerhq/errors@^4.32.0": - version "4.33.7" - resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-4.33.7.tgz#b78becd20e8a68f7115ad0986fa357a8adddf6b7" - integrity sha512-1vKWcttI5NHpT6rMKKuxWPAjfwDgfgUTf/AyNAT5KXHlhiLvqnA3NDCdNUVadajVNKSa/s1u1ZWKismtbfePzg== +"@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/hw-app-btc@^4.32.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-4.32.0.tgz#e883dcaa3ebb4aca1e2cb27acfc47b8db4e85f3f" - integrity sha512-N/RxtkPVjTDwU+lDPQQE7+4YQMXaXStDrpufQbDn0NXoaJ8KgY+QGkOH6bkuwV+LQvc7rEaM7E3p7/t58KJpMg== +"@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== dependencies: - "@ledgerhq/hw-transport" "^4.32.0" + "@ledgerhq/hw-transport" "^4.35.0" create-hash "^1.1.3" -"@ledgerhq/hw-app-btc@^4.34.0": - version "4.34.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-4.34.0.tgz#0bbc46afd29de04ac6a73582fbf9a09fcf5ed117" - integrity sha512-xR4rH8o8YRvyhnTvb8g89NAJQQqXJkApiFtCvduBamu5V+rDvhHYlFu2B+CU6g8lzLFACMDIqJqXbmwT80AGjw== +"@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== dependencies: - "@ledgerhq/hw-transport" "^4.32.0" - create-hash "^1.1.3" + "@ledgerhq/hw-transport" "^4.35.0" -"@ledgerhq/hw-app-eth@^4.32.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-4.32.0.tgz#7d43ca2c7952f1fb726e02c3b4485be10af481a2" - integrity sha512-d22WinjcsqJNoZSI+6UpTWZ7hl+UhL2dFeVeliCwtBWSj40z6F25MpoviGxPsv0WC7IUjayw+a9jIRcOJ5kkIw== +"@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== dependencies: - "@ledgerhq/hw-transport" "^4.32.0" - -"@ledgerhq/hw-app-xrp@^4.32.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-xrp/-/hw-app-xrp-4.32.0.tgz#260daafa9de1073598ea91ddfeb168dc437edd50" - integrity sha512-MNmLAGUp7Bnj/mjg1Lo5bK1v+q/QPYw7RJAbI4Vl1A4Fsqj6oiZspnSK+BTHGp+CRJavCwumjKuf5y3X5Dp8cA== - dependencies: - "@ledgerhq/hw-transport" "^4.32.0" + "@ledgerhq/hw-transport" "^4.35.0" bip32-path "0.4.2" -"@ledgerhq/hw-transport-node-hid@^4.32.0": - version "4.33.3" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.33.3.tgz#5e96dca2be0a23d80814303f262398087b208a6a" - integrity sha512-hmNAm7k385RJXY38hVUpzYgGgyk9QjScD3erNlFCTO8FnnxmEJCFUmVhWkv4sTwufuUJSpXL3ZXXNZ44qLMJpg== +"@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== dependencies: - "@ledgerhq/hw-transport" "^4.32.0" + "@ledgerhq/hw-transport" "^4.35.0" lodash "^4.17.11" node-hid "^0.7.2" usb "^1.3.3" -"@ledgerhq/hw-transport@^4.21.0", "@ledgerhq/hw-transport@^4.32.0": - version "4.32.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.32.0.tgz#592b9dc51459cb1cd31ce9444cf943f627bc4beb" - integrity sha512-Wgsk9UHC4RShqYoDeIEeKgHZOvNCtB0WWIG0xqlVPzS+IcKDkIxtXQw7hTA7GQSuDuGeauVtlbTQ5yat6+2/BA== +"@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== dependencies: events "^3.0.0" @@ -2258,6 +2250,11 @@ text-table "^0.2.0" webpack-log "^1.1.2" +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + abab@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" @@ -5225,6 +5222,11 @@ commander@2.6.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d" integrity sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0= +commander@^2.10.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== + commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" @@ -13211,12 +13213,7 @@ react-inspector@^2.2.2: babel-runtime "^6.26.0" is-dom "^1.0.9" -react-is@^16.3.1, react-is@^16.4.1: - version "16.4.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.4.1.tgz#d624c4650d2c65dbd52c72622bbf389435d9776e" - integrity sha512-xpb0PpALlFWNw/q13A+1aHeyJyLYCg0/cCHPUA43zYluZuIPHaHL3k8OBsTgQtxqW0FhyDEMvi8fZ/+7+r4OSQ== - -react-is@^16.3.2: +react-is@^16.3.1, react-is@^16.3.2, react-is@^16.4.1: version "16.5.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.5.2.tgz#e2a7b7c3f5d48062eb769fcb123505eb928722e3" integrity sha512-hSl7E6l25GTjNEZATqZIuWOgSnpXb3kD0DVCujmg46K5zLxsbiKaaT6VO9slkSBDPZfYs30lwfJwbOFOnoEnKQ== @@ -17062,6 +17059,15 @@ yargs@~3.10.0: decamelize "^1.0.0" window-size "0.1.0" +yarn-deduplicate@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/yarn-deduplicate/-/yarn-deduplicate-1.1.1.tgz#19b4a87654b66f55bf3a4bd6b153b4e4ab1b6e6d" + integrity sha512-2FDJ1dFmtvqhRmfja89ohYzpaheCYg7BFBSyaUq+kxK0y61C9oHv1XaQovCWGJtP2WU8PksQOgzMVV7oQOobzw== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + commander "^2.10.0" + semver "^5.3.0" + yauzl@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005"