Browse Source

Merge branch 'develop' into new-derivations

gre-patch-1
Gaëtan Renaudeau 6 years ago
parent
commit
384d032080
No known key found for this signature in database GPG Key ID: 7B66B85F042E5451
  1. 2
      .circleci/config.yml
  2. 1
      .gitignore
  3. 4
      package.json
  4. 17
      scripts/download-xliffs.sh
  5. 100
      scripts/release.sh
  6. 1
      src/bridge/LibcoreBridge.js
  7. 35
      src/commands/libcoreSignAndBroadcast.js
  8. 302
      src/components/DevToolsPage/AccountImporter.js
  9. 2
      src/config/urls.js
  10. 21
      src/helpers/libcore.js
  11. 1
      src/internals/index.js
  12. 6
      static/i18n/en/app.json
  13. 16
      yarn.lock

2
.circleci/config.yml

@ -9,7 +9,7 @@ jobs:
build:
<<: *defaults
steps:
- run: sudo apt-get install -y libudev-dev
- run: sudo apt-get install -y libudev-dev libfuse-dev
- run:
name: Install latest yarn
command: |

1
.gitignore

@ -1,3 +1,4 @@
xliffs/
/.env
/dist/
/flow-typed/

4
package.json

@ -3,7 +3,7 @@
"productName": "Ledger Live",
"description": "Ledger Live - Desktop",
"repository": "https://github.com/LedgerHQ/ledger-live-desktop",
"version": "1.2.1",
"version": "1.2.3",
"author": "Ledger",
"license": "MIT",
"scripts": {
@ -35,7 +35,7 @@
}
},
"dependencies": {
"@ledgerhq/hw-app-btc": "4.24.0",
"@ledgerhq/hw-app-btc": "^4.27.0",
"@ledgerhq/hw-app-eth": "^4.24.0",
"@ledgerhq/hw-app-xrp": "^4.25.0",
"@ledgerhq/hw-transport": "^4.24.0",

17
scripts/download-xliffs.sh

@ -0,0 +1,17 @@
#!/bin/sh
if [ -z "$CROWDIN_TOKEN" ]; then
echo "CROWDIN_TOKEN env required" >&2
exit 1
fi
rm -rf xliffs
mkdir xliffs
cd xliffs
for lang in fr es-ES zh-CN ja ko ru; do
curl "https://api.crowdin.com/api/project/ledger-wallet/export-file?file=develop/static/i18n/en/app.json&language=$lang&format=xliff&key=$CROWDIN_TOKEN" > en-$lang.xliff
done
zip -r ledger-live-langs.zip *.xliff

100
scripts/release.sh

@ -69,48 +69,58 @@ fi
runJob "yarn compile" "compiling..." "compiled" "failed to compile" "verbose"
# --------------------------------------------------------------------
# Linux: Internal process error (null)
#
# context: https://github.com/LedgerHQ/ledger-live-desktop/issues/1010
# Linux: Internal process error (null)
#
# The "fix" is not optimal, as it doesn't really solve the problem
# (electron loading system openssl before we can load our embedded one)
# Quick summary:
#
# - build without publishing
# - unpack the .AppImage
# - download reported working libs from ubuntu mirrors, put it inside
# - re-pack the .AppImage
# - checksum stuff
# - upload to gh
runJob \
"DEBUG=electron-builder electron-builder build --publish never" \
"building and packaging app..." \
"app built and packaged successfully" \
"failed to build app" \
"verbose"
runJob \
"scripts/patch-appimage.sh" \
"patching AppImage..." \
"AppImage patched successfully" \
"failed to patch AppImage"
LEDGER_LIVE_VERSION=$(grep version package.json | sed -E 's/.*: "(.*)",/\1/g')
scripts/upload-github-release-asset.sh \
github_api_token="$GH_TOKEN" \
owner=LedgerHQ \
repo=ledger-live-desktop \
tag="$GH_TAG" \
filename="dist/ledger-live-desktop-$LEDGER_LIVE_VERSION-linux-x86_64.AppImage"
scripts/upload-github-release-asset.sh \
github_api_token="$GH_TOKEN" \
owner=LedgerHQ \
repo=ledger-live-desktop \
tag="$GH_TAG" \
filename="dist/latest-linux.yml"
if [[ $(uname) == 'Linux' ]]; then
# --------------------------------------------------------------------
# Linux: Internal process error (null)
#
# context: https://github.com/LedgerHQ/ledger-live-desktop/issues/1010
# Linux: Internal process error (null)
#
# The "fix" is not optimal, as it doesn't really solve the problem
# (electron loading system openssl before we can load our embedded one)
# Quick summary:
#
# - build without publishing
# - unpack the .AppImage
# - download reported working libs from ubuntu mirrors, put it inside
# - re-pack the .AppImage
# - checksum stuff
# - upload to gh
runJob \
"DEBUG=electron-builder electron-builder build --publish never" \
"building and packaging app..." \
"app built and packaged successfully" \
"failed to build app" \
"verbose"
runJob \
"scripts/patch-appimage.sh" \
"patching AppImage..." \
"AppImage patched successfully" \
"failed to patch AppImage"
LEDGER_LIVE_VERSION=$(grep version package.json | sed -E 's/.*: "(.*)",/\1/g')
scripts/upload-github-release-asset.sh \
github_api_token="$GH_TOKEN" \
owner=LedgerHQ \
repo=ledger-live-desktop \
tag="$GH_TAG" \
filename="dist/ledger-live-desktop-$LEDGER_LIVE_VERSION-linux-x86_64.AppImage"
scripts/upload-github-release-asset.sh \
github_api_token="$GH_TOKEN" \
owner=LedgerHQ \
repo=ledger-live-desktop \
tag="$GH_TAG" \
filename="dist/latest-linux.yml"
else
runJob \
"DEBUG=electron-builder electron-builder build --publish always" \
"building and packaging app..." \
"app built and packaged successfully" \
"failed to build app" \
"verbose"
fi

1
src/bridge/LibcoreBridge.js

@ -220,6 +220,7 @@ const LibcoreBridge: WalletBridge<Transaction> = {
.send({
accountId: account.id,
currencyId: account.currency.id,
blockHeight: account.blockHeight,
xpub: account.xpub || '', // FIXME only reason is to build the op id. we need to consider another id for making op id.
derivationMode: account.derivationMode,
seedIdentifier: account.seedIdentifier,

35
src/commands/libcoreSignAndBroadcast.js

@ -2,6 +2,7 @@
import logger from 'logger'
import { BigNumber } from 'bignumber.js'
import { StatusCodes } from '@ledgerhq/hw-transport'
import Btc from '@ledgerhq/hw-app-btc'
import { Observable } from 'rxjs'
import { isSegwitDerivationMode } from '@ledgerhq/live-common/lib/derivation'
@ -13,6 +14,7 @@ import {
bigNumberToLibcoreAmount,
getOrCreateWallet,
} from 'helpers/libcore'
import { UpdateYourApp } from 'config/errors'
import withLibcore from 'helpers/withLibcore'
import { createCommand, Command } from 'helpers/ipc'
@ -26,6 +28,7 @@ type BitcoinLikeTransaction = {
type Input = {
accountId: string,
blockHeight: number,
currencyId: string,
derivationMode: DerivationMode,
seedIdentifier: string,
@ -41,7 +44,17 @@ type Result = { type: 'signed' } | { type: 'broadcasted', operation: OperationRa
const cmd: Command<Input, Result> = createCommand(
'libcoreSignAndBroadcast',
({ accountId, currencyId, derivationMode, seedIdentifier, xpub, index, transaction, deviceId }) =>
({
accountId,
blockHeight,
currencyId,
derivationMode,
seedIdentifier,
xpub,
index,
transaction,
deviceId,
}) =>
Observable.create(o => {
let unsubscribed = false
const currency = getCryptoCurrencyById(currencyId)
@ -50,6 +63,7 @@ const cmd: Command<Input, Result> = createCommand(
doSignAndBroadcast({
accountId,
currency,
blockHeight,
derivationMode,
seedIdentifier,
xpub,
@ -79,6 +93,7 @@ const cmd: Command<Input, Result> = createCommand(
async function signTransaction({
hwApp,
currency,
blockHeight,
transaction,
derivationMode,
sigHashType,
@ -86,6 +101,7 @@ async function signTransaction({
}: {
hwApp: Btc,
currency: CryptoCurrency,
blockHeight: number,
transaction: *,
derivationMode: DerivationMode,
sigHashType: number,
@ -94,7 +110,12 @@ async function signTransaction({
const additionals = []
let expiryHeight
if (currency.id === 'bitcoin_cash' || currency.id === 'bitcoin_gold') additionals.push('bip143')
if (currency.id === 'zcash') expiryHeight = Buffer.from([0x00, 0x00, 0x00, 0x00])
if (currency.id === 'zcash') {
expiryHeight = Buffer.from([0x00, 0x00, 0x00, 0x00])
if (blockHeight >= 419200) {
additionals.push('sapling')
}
}
const rawInputs = transaction.getInputs()
const hasExtraData = currency.id === 'zcash'
@ -166,6 +187,7 @@ async function signTransaction({
export async function doSignAndBroadcast({
accountId,
derivationMode,
blockHeight,
seedIdentifier,
currency,
xpub,
@ -180,6 +202,7 @@ export async function doSignAndBroadcast({
accountId: string,
derivationMode: DerivationMode,
seedIdentifier: string,
blockHeight: number,
currency: CryptoCurrency,
xpub: string,
index: number,
@ -222,12 +245,18 @@ export async function doSignAndBroadcast({
signTransaction({
hwApp: new Btc(transport),
currency,
blockHeight,
transaction: builded,
sigHashType: parseInt(sigHashType, 16),
hasTimestamp,
derivationMode,
}),
)
).catch(e => {
if (e && e.statusCode === StatusCodes.INCORRECT_P1_P2) {
throw new UpdateYourApp(`UpdateYourApp ${currency.id}`, currency)
}
throw e
})
if (!signedTransaction || isCancelled() || !njsAccount) return
onSigned()

302
src/components/DevToolsPage/AccountImporter.js

@ -1,5 +1,7 @@
// @flow
/* eslint-disable react/no-multi-comp */
import React, { PureComponent, Fragment } from 'react'
import invariant from 'invariant'
import { connect } from 'react-redux'
@ -9,7 +11,8 @@ import type { Currency, Account } from '@ledgerhq/live-common/lib/types'
import { decodeAccount } from 'reducers/accounts'
import { addAccount } from 'actions/accounts'
import FormattedVal from 'components/base/FormattedVal'
import FakeLink from 'components/base/FakeLink'
import Ellipsis from 'components/base/Ellipsis'
import Switch from 'components/base/Switch'
import Spinner from 'components/base/Spinner'
import Box, { Card } from 'components/base/Box'
@ -32,26 +35,40 @@ type Props = {
addAccount: Account => void,
}
const INITIAL_STATE = {
status: 'idle',
currency: null,
xpub: '',
account: null,
isSegwit: true,
isUnsplit: false,
error: null,
type ImportableAccountType = {
name: string,
currency: Currency,
derivationMode: string,
xpub: string,
}
type State = {
status: string,
importableAccounts: ImportableAccountType[],
currency: ?Currency,
xpub: string,
account: ?Account,
name: string,
isSegwit: boolean,
isUnsplit: boolean,
error: ?Error,
}
const INITIAL_STATE = {
status: 'idle',
currency: null,
xpub: '',
name: 'dev',
isSegwit: true,
isUnsplit: false,
error: null,
importableAccounts: [],
}
class AccountImporter extends PureComponent<Props, State> {
state = INITIAL_STATE
@ -67,142 +84,199 @@ class AccountImporter extends PureComponent<Props, State> {
onChangeXPUB = xpub => this.setState({ xpub })
onChangeSegwit = isSegwit => this.setState({ isSegwit })
onChangeUnsplit = isUnsplit => this.setState({ isUnsplit })
onChangeName = name => this.setState({ name })
isValid = () => {
const { currency, xpub } = this.state
return !!currency && !!xpub
const { currency, xpub, status } = this.state
return !!currency && !!xpub && status !== 'scanning'
}
scan = async () => {
if (!this.isValid()) return
this.setState({ status: 'scanning' })
const { importableAccounts } = this.state
try {
const { currency, xpub, isSegwit, isUnsplit } = this.state
invariant(currency, 'no currency')
const derivationMode = isSegwit
? isUnsplit
? 'segwit_unsplit'
: 'segwit'
: isUnsplit
? 'unsplit'
: ''
const rawAccount = await scanFromXPUB
.send({
seedIdentifier: 'dev_tool',
currencyId: currency.id,
xpub,
derivationMode,
for (let i = 0; i < importableAccounts.length; i++) {
const a = importableAccounts[i]
const scanPayload = {
seedIdentifier: `dev_${a.xpub}`,
currencyId: a.currency.id,
xpub: a.xpub,
derivationMode: a.derivationMode,
}
const rawAccount = await scanFromXPUB.send(scanPayload).toPromise()
const account = decodeAccount(rawAccount)
await this.import({
...account,
name: a.name,
})
.toPromise()
const account = decodeAccount(rawAccount)
this.setState({ status: 'finish', account })
this.removeImportableAccount(a)
}
this.reset()
} catch (error) {
this.setState({ status: 'error', error })
}
}
import = async () => {
const { account } = this.state
addToScan = () => {
const { xpub, currency, isSegwit, isUnsplit, name } = this.state
const derivationMode = isSegwit
? isUnsplit
? 'segwit_unsplit'
: 'segwit'
: isUnsplit
? 'unsplit'
: ''
const importableAccount = { xpub, currency, derivationMode, name }
this.setState(({ importableAccounts }) => ({
importableAccounts: [...importableAccounts, importableAccount],
currency: null,
xpub: '',
name: 'dev',
isSegwit: true,
isUnsplit: false,
}))
}
removeImportableAccount = importableAccount => {
this.setState(({ importableAccounts }) => ({
importableAccounts: importableAccounts.filter(i => i.xpub !== importableAccount.xpub),
}))
}
import = async account => {
invariant(account, 'no account')
await idleCallback()
this.props.addAccount(account)
this.reset()
}
reset = () => this.setState(INITIAL_STATE)
render() {
const { currency, xpub, isSegwit, isUnsplit, status, account, error } = this.state
const {
currency,
xpub,
name,
isSegwit,
isUnsplit,
status,
error,
importableAccounts,
} = this.state
const supportsSplit = !!currency && !!currency.forkedFrom
return (
<Card title="Import from xpub" flow={3}>
{status === 'idle' ? (
<Fragment>
<Box flow={1}>
<Label>{'currency'}</Label>
<SelectCurrency autoFocus value={currency} onChange={this.onChangeCurrency} />
</Box>
{currency && (currency.supportsSegwit || supportsSplit) ? (
<Box horizontal justify="flex-end" align="center" flow={3}>
{supportsSplit && (
<Box horizontal align="center" flow={1}>
<Box ff="Museo Sans|Bold" fontSize={4}>
{'unsplit'}
<Fragment>
<Card title="Import from xpub" flow={3}>
{status === 'idle' || status === 'scanning' ? (
<Fragment>
<Box flow={1}>
<Label>{'currency'}</Label>
<SelectCurrency autoFocus value={currency} onChange={this.onChangeCurrency} />
</Box>
{currency && (currency.supportsSegwit || supportsSplit) ? (
<Box horizontal justify="flex-end" align="center" flow={3}>
{supportsSplit && (
<Box horizontal align="center" flow={1}>
<Box ff="Museo Sans|Bold" fontSize={4}>
{'unsplit'}
</Box>
<Switch isChecked={isUnsplit} onChange={this.onChangeUnsplit} />
</Box>
<Switch isChecked={isUnsplit} onChange={this.onChangeUnsplit} />
</Box>
)}
{currency.supportsSegwit && (
<Box horizontal align="center" flow={1}>
<Box ff="Museo Sans|Bold" fontSize={4}>
{'segwit'}
)}
{currency.supportsSegwit && (
<Box horizontal align="center" flow={1}>
<Box ff="Museo Sans|Bold" fontSize={4}>
{'segwit'}
</Box>
<Switch isChecked={isSegwit} onChange={this.onChangeSegwit} />
</Box>
<Switch isChecked={isSegwit} onChange={this.onChangeSegwit} />
</Box>
)}
</Box>
) : null}
<Box flow={1}>
<Label>{'xpub'}</Label>
<Input
placeholder="xpub"
value={xpub}
onChange={this.onChangeXPUB}
onEnter={this.scan}
/>
</Box>
<Box align="flex-end">
<Button primary small disabled={!this.isValid()} onClick={this.scan}>
{'scan'}
</Button>
</Box>
</Fragment>
) : status === 'scanning' ? (
<Box align="center" justify="center" p={5}>
<Spinner size={16} />
</Box>
) : status === 'finish' ? (
account ? (
<Box p={8} align="center" justify="center" flow={5} horizontal>
<Box horizontal flow={4} color="graphite" align="center">
{currency && <CurrencyCircleIcon size={64} currency={currency} />}
<Box>
<Box ff="Museo Sans|Bold">{account.name}</Box>
<FormattedVal
fontSize={2}
alwaysShowSign={false}
color="graphite"
unit={account.unit}
showCode
val={account.balance || 0}
/>
<Box fontSize={2}>{`${account.operations.length} operation(s)`}</Box>
)}
</Box>
) : null}
<Box flow={1}>
<Label>{'xpub'}</Label>
<Input
placeholder="xpub"
value={xpub}
onChange={this.onChangeXPUB}
onEnter={this.addToScan}
/>
</Box>
<Button outline small disabled={!account} onClick={this.import}>
{'import'}
</Button>
</Box>
) : (
<Box flow={1}>
<Label>{'name'}</Label>
<Input
placeholder="name"
value={name}
onChange={this.onChangeName}
onEnter={this.addToScan}
/>
</Box>
<Box align="flex-end">
<Button primary small disabled={!this.isValid()} onClick={this.addToScan}>
{'add to scan'}
</Button>
</Box>
</Fragment>
) : status === 'error' ? (
<Box align="center" justify="center" p={5} flow={4}>
<Box>{'No accounts found or wrong xpub'}</Box>
<Box>
<TranslatedError error={error} />
</Box>
<Button primary onClick={this.reset} small autoFocus>
{'Reset'}
</Button>
</Box>
)
) : status === 'error' ? (
<Box align="center" justify="center" p={5} flow={4}>
<Box>
<TranslatedError error={error} />
</Box>
<Button primary onClick={this.reset} small autoFocus>
{'Reset'}
</Button>
</Box>
) : null}
</Card>
) : null}
</Card>
{!!importableAccounts.length && (
<Card flow={2}>
{importableAccounts.map((acc, i) => (
<ImportableAccount
key={acc.xpub}
importableAccount={acc}
onRemove={this.removeImportableAccount}
isLoading={status === 'scanning' && i === 0}
>
{acc.xpub}
</ImportableAccount>
))}
{status !== 'scanning' && (
<Box mt={4} align="flex-start">
<Button primary onClick={this.scan}>
{'Launch scan'}
</Button>
</Box>
)}
</Card>
)}
</Fragment>
)
}
}
class ImportableAccount extends PureComponent<{
importableAccount: ImportableAccountType,
onRemove: ImportableAccountType => void,
isLoading: boolean,
}> {
remove = () => {
this.props.onRemove(this.props.importableAccount)
}
render() {
const { importableAccount, isLoading } = this.props
return (
<Box horizontal flow={2} align="center">
{isLoading && <Spinner size={16} color="rgba(0, 0, 0, 0.3)" />}
<CurrencyCircleIcon currency={importableAccount.currency} size={24} />
<Box grow ff="Rubik" fontSize={3}>
<Ellipsis>{`[${importableAccount.name}] ${importableAccount.derivationMode ||
'default'} ${importableAccount.xpub}`}</Ellipsis>
</Box>
{!isLoading && (
<FakeLink onClick={this.remove} fontSize={3}>
{'Remove'}
</FakeLink>
)}
</Box>
)
}
}

2
src/config/urls.js

@ -8,7 +8,7 @@ export const urls = {
// Ledger support
faq: 'https://support.ledgerwallet.com/hc/en-us',
terms: 'https://www.ledgerwallet.com/terms',
terms: 'https://www.ledger.com/pages/terms-of-use-and-disclaimer',
noDeviceBuyNew: 'https://www.ledgerwallet.com/',
noDeviceTrackOrder: 'http://order.ledgerwallet.com/',
noDeviceLearnMore: 'https://www.ledgerwallet.com/',

21
src/helpers/libcore.js

@ -113,7 +113,6 @@ async function scanAccountsOnDeviceBySegwit({
// retrieve or create the wallet
const wallet = await getOrCreateWallet(core, walletName, { currency, derivationMode })
const accountsCount = await wallet.getAccountCount()
// recursively scan all accounts on device on the given app
// new accounts will be created in sqlite, existing ones will be updated
@ -123,7 +122,6 @@ async function scanAccountsOnDeviceBySegwit({
walletName,
devicePath,
currency,
accountsCount,
accountIndex: 0,
accounts: [],
onAccountScanned,
@ -204,7 +202,6 @@ async function scanNextAccount(props: {
currency: CryptoCurrency,
seedIdentifier: string,
derivationMode: DerivationMode,
accountsCount: number,
accountIndex: number,
accounts: AccountRaw[],
onAccountScanned: AccountRaw => void,
@ -217,7 +214,6 @@ async function scanNextAccount(props: {
walletName,
devicePath,
currency,
accountsCount,
accountIndex,
accounts,
onAccountScanned,
@ -227,13 +223,12 @@ async function scanNextAccount(props: {
isUnsubscribed,
} = props
// create account only if account has not been scanned yet
// if it has already been created, we just need to get it, and sync it
const hasBeenScanned = accountIndex < accountsCount
const njsAccount = hasBeenScanned
? await wallet.getAccount(accountIndex)
: await createAccount(wallet, devicePath)
let njsAccount
try {
njsAccount = await wallet.getAccount(accountIndex)
} catch (err) {
njsAccount = await createAccount(wallet, devicePath)
}
if (isUnsubscribed()) return []
@ -559,14 +554,12 @@ export async function scanAccountsFromXPUB({
const currency = getCryptoCurrencyById(currencyId)
const walletName = getWalletName({
currency,
seedIdentifier: 'debug',
seedIdentifier,
derivationMode,
})
const wallet = await getOrCreateWallet(core, walletName, { currency, derivationMode })
await wallet.eraseDataSince(new Date(0))
const index = 0
const isSegwit = isSegwitDerivationMode(derivationMode)

1
src/internals/index.js

@ -1,4 +1,5 @@
// @flow
import '@babel/polyfill'
import commands from 'commands'
import logger from 'logger'
import uuid from 'uuid/v4'

6
static/i18n/en/app.json

@ -170,7 +170,7 @@
"luno": "Luno makes it safe and easy to buy, store and learn about cryptocurrencies like Bitcoin and Ethereum",
"shapeshift": "ShapeShift is an online marketplace where users can buy and sell digital assets. It is a fast and secure way for the world to buy and sell digital assets, with no lengthy signup process, no counterparty risk, and no friction.",
"genesis": "Genesis is an institutional trading firm offering liquidity and borrow for digital currencies, including bitcoin, bitcoin cash, ethereum, ethereum classic, litecoin, and XRP.",
"kyber": "KYBER, his a trading platform for exchange and conversion of ERC-20 tokens"
"kyber": "Kyber is a trading platform for exchange and conversion of ERC-20 tokens"
},
"genuinecheck": {
"modal": {
@ -826,8 +826,8 @@
"description": "Please try again or contact Ledger Support"
},
"UpdateYourApp": {
"title": "App update required. Uninstall and reinstall the {{managerAppName}} app in the Manager",
"description": null
"title": "App update required",
"description": "Uninstall and reinstall the {{managerAppName}} app in the Manager"
},
"WebsocketConnectionError": {
"title": "Sorry, try again (websocket error).",

16
yarn.lock

@ -1670,10 +1670,10 @@
camelcase "^5.0.0"
prettier "^1.13.7"
"@ledgerhq/hw-app-btc@4.24.0", "@ledgerhq/hw-app-btc@^4.24.0":
version "4.24.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-4.24.0.tgz#8889b2bc9b9583209ed24f832c96ea8d23e1dc74"
integrity sha512-OEc8UCcdAWp10PPM9Keoh8imuusmNVe2o/89ujMT5UIWOGCu7duezpsnCY11jGNxf2hyos6lezUMlUAOHBuISQ==
"@ledgerhq/hw-app-btc@^4.27.0":
version "4.27.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-4.27.0.tgz#11fc822bd34a47a39b1a7ae03ced69cf1d432796"
integrity sha512-7Ck48wCBb6nd9UXarNeGOsOqbOTi2cs4AxFhbDNrVLvPiBSH0yEiNQEF95J6u5BxKkAdM1GV9LoRumR4KhZGqQ==
dependencies:
"@ledgerhq/hw-transport" "^4.24.0"
create-hash "^1.1.3"
@ -1741,10 +1741,10 @@
dependencies:
events "^3.0.0"
"@ledgerhq/ledger-core@2.0.0-rc.8":
version "2.0.0-rc.8"
resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-2.0.0-rc.8.tgz#618ff2ca091464c71890678d3912921ee46f98af"
integrity sha512-UYEwlw7+JfRCPw1z2kw9EGs88wsk5XBGxMPpNPF1cdpE7extEL63Gr+4h4ibU6kXEeEIpfI0lZ2l/6HwzMw6EQ==
"@ledgerhq/ledger-core@2.0.0-rc.10":
version "2.0.0-rc.10"
resolved "https://registry.yarnpkg.com/@ledgerhq/ledger-core/-/ledger-core-2.0.0-rc.10.tgz#55b7261924df8ed5a33fcc51fdfafc8d6a323fc4"
integrity sha512-PbT6y8lwpVfbD5DZIH8CsOZoipNSGHY7BVHNTS+55QsQ6wAPf7sztZjZ8fk6TM0SfdbdIr7Cc5bFQ6cgljTNIA==
dependencies:
"@ledgerhq/hw-app-btc" "^4.7.3"
"@ledgerhq/hw-transport-node-hid" "^4.7.6"

Loading…
Cancel
Save