From ce7c84332399272af4e2d98c0fc002217fd9a591 Mon Sep 17 00:00:00 2001 From: meriadec Date: Tue, 22 May 2018 10:03:46 +0200 Subject: [PATCH 1/8] Connect BTC like transaction to LibcoreBridge --- src/bridge/LibcoreBridge.js | 14 +++- src/bridge/makeMockBridge.js | 2 +- src/bridge/types.js | 6 +- src/components/DeviceSignTransaction.js | 2 +- src/internals/accounts/index.js | 3 +- .../accounts/scanAccountsOnDevice.js | 24 +++++-- .../signAndBroadcastTransaction/btc.js | 71 +++++++++++++++++++ src/reducers/accounts.js | 4 ++ src/renderer/runJob.js | 2 +- 9 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 src/internals/accounts/signAndBroadcastTransaction/btc.js diff --git a/src/bridge/LibcoreBridge.js b/src/bridge/LibcoreBridge.js index eb4864fe..9b9776cd 100644 --- a/src/bridge/LibcoreBridge.js +++ b/src/bridge/LibcoreBridge.js @@ -1,7 +1,8 @@ // @flow import React from 'react' import { ipcRenderer } from 'electron' -import { decodeAccount } from 'reducers/accounts' + +import { decodeAccount, encodeAccount } from 'reducers/accounts' import runJob from 'renderer/runJob' import FeesBitcoinKind from 'components/FeesField/BitcoinKind' import AdvancedOptionsBitcoinKind from 'components/AdvancedOptions/BitcoinKind' @@ -153,7 +154,16 @@ const LibcoreBridge: WalletBridge = { getMaxAmount: (a, t) => Promise.resolve(a.balance - t.feePerByte), - signAndBroadcast: () => Promise.reject(notImplemented), + signAndBroadcast: ({ account, transaction, deviceId }) => { + const rawAccount = encodeAccount(account) + return runJob({ + channel: 'accounts', + job: 'signAndBroadcastTransactionBTCLike', + successResponse: 'accounts.signAndBroadcastTransactionBTCLike.success', + errorResponse: 'accounts.signAndBroadcastTransactionBTCLike.fail', + data: { account: rawAccount, transaction, deviceId }, + }) + }, } export default LibcoreBridge diff --git a/src/bridge/makeMockBridge.js b/src/bridge/makeMockBridge.js index 1bc2eef9..21032f3d 100644 --- a/src/bridge/makeMockBridge.js +++ b/src/bridge/makeMockBridge.js @@ -146,7 +146,7 @@ function makeMockBridge(opts?: Opts): WalletBridge<*> { getMaxAmount, - signAndBroadcast: async (account, t) => { + signAndBroadcast: async ({ account, transaction: t }) => { const rng = new Prando() const op = genOperation(account, account.operations, account.currency, rng) op.amount = -t.amount diff --git a/src/bridge/types.js b/src/bridge/types.js index 716ba35d..d85d3fe0 100644 --- a/src/bridge/types.js +++ b/src/bridge/types.js @@ -98,5 +98,9 @@ export interface WalletBridge { * NOTE: in future, when transaction balance is close to account.balance, we could wipe it all at this level... * to implement that, we might want to have special logic `account.balance-transaction.amount < dust` but not sure where this should leave (i would say on UI side because we need to inform user visually). */ - signAndBroadcast(account: Account, transaction: Transaction, deviceId: DeviceId): Promise; + signAndBroadcast({ + account: Account, + transaction: Transaction, + deviceId: DeviceId, + }): Promise; } diff --git a/src/components/DeviceSignTransaction.js b/src/components/DeviceSignTransaction.js index 471c3ab4..ff9c3865 100644 --- a/src/components/DeviceSignTransaction.js +++ b/src/components/DeviceSignTransaction.js @@ -34,7 +34,7 @@ class DeviceSignTransaction extends PureComponent { sign = async () => { const { device, account, transaction, bridge, onSuccess } = this.props try { - const txid = await bridge.signAndBroadcast(account, transaction, device.path) + const txid = await bridge.signAndBroadcast({ account, transaction, deviceId: device.path }) onSuccess(txid) } catch (error) { this.setState({ error }) diff --git a/src/internals/accounts/index.js b/src/internals/accounts/index.js index 18c02cfe..6a18e8e8 100644 --- a/src/internals/accounts/index.js +++ b/src/internals/accounts/index.js @@ -3,11 +3,13 @@ import type { IPCSend } from 'types/electron' import scanAccountsOnDevice from './scanAccountsOnDevice' +import signAndBroadcastTransactionBTCLike from './signAndBroadcastTransaction/btc' import sync from './sync' export default { sync, + signAndBroadcastTransactionBTCLike, scan: async ( send: IPCSend, { @@ -29,7 +31,6 @@ export default { }) send('accounts.scanAccountsOnDevice.success', accounts) } catch (err) { - console.log(err) send('accounts.scanAccountsOnDevice.fail', formatErr(err)) } }, diff --git a/src/internals/accounts/scanAccountsOnDevice.js b/src/internals/accounts/scanAccountsOnDevice.js index f8ba2daf..4cb1688c 100644 --- a/src/internals/accounts/scanAccountsOnDevice.js +++ b/src/internals/accounts/scanAccountsOnDevice.js @@ -46,19 +46,33 @@ export default async function scanAccountsOnDevice(props: Props): Promise = await CommNodeHid.open(deviceId) + const hwApp = new Btc(transport) + + const WALLET_IDENTIFIER = await getWalletIdentifier({ + hwApp, + isSegwit: account.isSegwit, + currencyId: account.currencyId, + devicePath: deviceId, + }) + + const njsWallet = await core.getWallet(WALLET_IDENTIFIER) + const njsAccount = await njsWallet.getAccount(account.index) + const bitcoinLikeAccount = njsAccount.asBitcoinLikeAccount() + const njsWalletCurrency = njsWallet.getCurrency() + const amount = core.createAmount(njsWalletCurrency, transaction.amount) + const fees = core.createAmount(njsWalletCurrency, transaction.feePerByte) + const transactionBuilder = bitcoinLikeAccount.buildTransaction() + + // TODO: check if is valid address. if not, it will fail silently on invalid + + transactionBuilder.sendToAddress(amount, transaction.recipient) + // TODO: don't use hardcoded value for sequence (and first also maybe) + transactionBuilder.pickInputs(0, 0xffffff) + transactionBuilder.setFeesPerByte(fees) + + const builded = await transactionBuilder.build() + const signedTransaction = await core.signTransaction(hwApp, builded) + + const txHash = await njsAccount + .asBitcoinLikeAccount() + .broadcastRawTransaction(signedTransaction) + + send('accounts.signAndBroadcastTransactionBTCLike.success', txHash) + } catch (err) { + send('accounts.signAndBroadcastTransactionBTCLike.fail', err) + } +} diff --git a/src/reducers/accounts.js b/src/reducers/accounts.js index 6ecb4009..40847073 100644 --- a/src/reducers/accounts.js +++ b/src/reducers/accounts.js @@ -119,6 +119,10 @@ export function decodeAccount(account: AccountRaw): Account { }) } +export function encodeAccount(account: Account): AccountRaw { + return accountModel.encode(account).data +} + // Yeah. `any` should be `AccountRaw[]` but it can also be a map // of wrapped accounts. And as flow is apparently incapable of doing // such a simple thing, let's put any, right? I don't care. diff --git a/src/renderer/runJob.js b/src/renderer/runJob.js index fa136b48..b2fc8e64 100644 --- a/src/renderer/runJob.js +++ b/src/renderer/runJob.js @@ -14,7 +14,7 @@ export default function runJob({ successResponse: string, errorResponse: string, data?: any, -}): Promise { +}): Promise { return new Promise((resolve, reject) => { ipcRenderer.send(channel, { type: job, data }) ipcRenderer.on('msg', handler) From d96c0bcdc9b34e6c5abb0ee903ee89f80829c2c9 Mon Sep 17 00:00:00 2001 From: meriadec Date: Tue, 22 May 2018 12:25:36 +0200 Subject: [PATCH 2/8] Fix getFreshAddresses --- src/internals/accounts/scanAccountsOnDevice.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/internals/accounts/scanAccountsOnDevice.js b/src/internals/accounts/scanAccountsOnDevice.js index 4cb1688c..d0e7245c 100644 --- a/src/internals/accounts/scanAccountsOnDevice.js +++ b/src/internals/accounts/scanAccountsOnDevice.js @@ -218,10 +218,10 @@ async function buildAccountRaw({ // get a bunch of fresh addresses const rawAddresses = await njsAccount.getFreshPublicAddresses() - // TODO: waiting for libcore - const addresses = rawAddresses.map((strAddr, i) => ({ - str: strAddr, - path: `${accountPath}/${i}'`, + + const addresses = rawAddresses.map(njsAddress => ({ + str: njsAddress.toString(), + path: `${accountPath}/${njsAddress.getDerivationPath()}`, })) const operations = ops.map(op => buildOperationRaw({ core, op, xpub })) From 82906be335df45c053a0cb7de42f2920f5412f1b Mon Sep 17 00:00:00 2001 From: meriadec Date: Tue, 22 May 2018 15:22:03 +0200 Subject: [PATCH 3/8] Enforce flow in scanAccountsOnDevice --- .../accounts/scanAccountsOnDevice.js | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/internals/accounts/scanAccountsOnDevice.js b/src/internals/accounts/scanAccountsOnDevice.js index d0e7245c..3dbbed7b 100644 --- a/src/internals/accounts/scanAccountsOnDevice.js +++ b/src/internals/accounts/scanAccountsOnDevice.js @@ -56,7 +56,7 @@ export async function getWalletIdentifier({ isSegwit: boolean, currencyId: string, devicePath: string, -}) { +}): Promise { const isVerify = false const deviceIdentifiers = await hwApp.getWalletPublicKey(devicePath, isVerify, isSegwit) const { publicKey } = deviceIdentifiers @@ -70,7 +70,13 @@ async function scanAccountsOnDeviceBySegwit({ onAccountScanned, devicePath, isSegwit, -}) { +}: { + hwApp: Object, + currencyId: string, + onAccountScanned: AccountRaw => void, + devicePath: string, + isSegwit: boolean, +}): Promise { // compute wallet identifier const WALLET_IDENTIFIER = await getWalletIdentifier({ hwApp, isSegwit, currencyId, devicePath }) @@ -94,7 +100,17 @@ async function scanAccountsOnDeviceBySegwit({ return accounts } -async function scanNextAccount(props) { +async function scanNextAccount(props: { + // $FlowFixMe + wallet: NJSWallet, + hwApp: Object, + currencyId: string, + accountsCount: number, + accountIndex: number, + accounts: AccountRaw[], + onAccountScanned: AccountRaw => void, + isSegwit: boolean, +}): Promise { const { wallet, hwApp, @@ -150,7 +166,11 @@ async function scanNextAccount(props) { return scanNextAccount({ ...props, accountIndex: accountIndex + 1 }) } -async function getOrCreateWallet(WALLET_IDENTIFIER, currencyId, isSegwit) { +async function getOrCreateWallet( + WALLET_IDENTIFIER: string, + currencyId: string, + isSegwit: boolean, +): NJSWallet { // TODO: investigate why importing it on file scope causes trouble const core = require('init-ledger-core')() try { @@ -190,7 +210,7 @@ async function buildAccountRaw({ hwApp: Object, // $FlowFixMe ops: NJSOperation[], -}) { +}): Promise { const balanceByDay = ops.length ? await getBalanceByDaySinceOperation({ njsAccount, @@ -309,7 +329,7 @@ async function getBalanceByDaySinceOperation({ return res } -function areSameDay(date1, date2) { +function areSameDay(date1: Date, date2: Date): boolean { return ( date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && From 6cc893eec6120189be9ba6a2341177972400053e Mon Sep 17 00:00:00 2001 From: meriadec Date: Tue, 22 May 2018 15:28:27 +0200 Subject: [PATCH 4/8] Bye bye to the beloved alix.js --- alix.js | 141 -------------------------------------------------------- 1 file changed, 141 deletions(-) delete mode 100644 alix.js diff --git a/alix.js b/alix.js deleted file mode 100644 index eab6144c..00000000 --- a/alix.js +++ /dev/null @@ -1,141 +0,0 @@ -/* eslint-disable no-console */ - -const CommNodeHid = require('@ledgerhq/hw-transport-node-hid').default -const Btc = require('@ledgerhq/hw-app-btc').default - -const { CREATE } = process.env - -const { - createWallet, - createAccount, - createAmount, - getCurrency, - getWallet, - syncAccount, - signTransaction, -} = require('@ledgerhq/ledger-core') - -async function getOrCreateWallet(currencyId) { - try { - const wallet = await getWallet(currencyId) - return wallet - } catch (err) { - const currency = await getCurrency(currencyId) - const wallet = await createWallet(currencyId, currency) - return wallet - } -} - -async function scanNextAccount(wallet, hwApp, accountIndex = 0) { - console.log(`creating an account with index ${accountIndex}`) - const account = await createAccount(wallet, hwApp) - console.log(`synchronizing account ${accountIndex}`) - await syncAccount(account) - console.log(`finished sync`) - const utxoCount = await account.asBitcoinLikeAccount().getUTXOCount() - console.log(`utxoCount = ${utxoCount}`) -} - -async function scanAccountsOnDevice(props) { - try { - const { devicePath, currencyId } = props - console.log(`get or create wallet`) - const wallet = await getOrCreateWallet(currencyId) - console.log(`open device`) - const transport = await CommNodeHid.open(devicePath) - console.log(`create app`) - const hwApp = new Btc(transport) - console.log(`scan account`) - const accounts = await scanNextAccount(wallet, hwApp) - console.log(accounts) - return [] - } catch (err) { - console.log(err) - } -} - -waitForDevices(async device => { - // const accounts = await scanAccountsOnDevice({ - // devicePath: device.path, - // currencyId: 'bitcoin_testnet', - // }) - // console.log(accounts) - try { - console.log(`> Creating transport`) - const transport = await CommNodeHid.open(device.path) - - // transport.setDebugMode(true) - - console.log(`> Instanciate BTC app`) - const hwApp = new Btc(transport) - - console.log(`> Get currency`) - const currency = await getCurrency('bitcoin_testnet') - - console.log(`> Create wallet`) - const wallet = CREATE ? await createWallet('khalil', currency) : await getWallet('khalil') - - console.log(`> Create account`) - const account = CREATE ? await createAccount(wallet, hwApp) : await wallet.getAccount(0) - - console.log(`> Sync account`) - if (CREATE) { - await syncAccount(account) - } - - console.log(`> Create transaction`) - const transaction = await createTransaction(wallet, account) - const signedTransaction = await signTransaction(hwApp, transaction) - - await account.asBitcoinLikeAccount().broadcastRawTransaction(signedTransaction) - // console.log(signedTransaction); - - process.exit(0) - // console.log(account.getIndex()); - // console.log(account.isSynchronizing()); - } catch (err) { - console.log(err.message) - process.exit(1) - } -}) - -function waitForDevices(onDevice) { - console.log(`> Waiting for device...`) - CommNodeHid.listen({ - error: () => {}, - complete: () => {}, - next: async e => { - if (!e.device) { - return - } - if (e.type === 'add') { - console.log(`> Detected ${e.device.manufacturer} ${e.device.product}`) - onDevice(e.device) - } - if (e.type === 'remove') { - console.log(`removed ${JSON.stringify(e)}`) - } - }, - }) -} - -async function createTransaction(wallet, account) { - const ADDRESS_TO_SEND = 'n2jdejywRogCunR2ozZAfXp1jMnfGpGXGR' - - const bitcoinLikeAccount = account.asBitcoinLikeAccount() - const walletCurrency = wallet.getCurrency() - const amount = createAmount(walletCurrency, 10000) - - console.log(`--------------------------------`) - console.log(amount.toLong()) - console.log(`-----------------after `) - const fees = createAmount(walletCurrency, 1000) - - const transactionBuilder = bitcoinLikeAccount.buildTransaction() - transactionBuilder.sendToAddress(amount, ADDRESS_TO_SEND) - // TODO: don't use hardcoded value for sequence (and first also maybe) - transactionBuilder.pickInputs(0, 0xffffff) - transactionBuilder.setFeesPerByte(fees) - - return transactionBuilder.build() -} From 8b122ca3181e8e8314ce2440b99d218d4d623799 Mon Sep 17 00:00:00 2001 From: meriadec Date: Tue, 22 May 2018 17:11:53 +0200 Subject: [PATCH 5/8] Update EthereumJSBridge signAndBroadcast signature --- src/bridge/EthereumJSBridge.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bridge/EthereumJSBridge.js b/src/bridge/EthereumJSBridge.js index 0415b2c8..794d617b 100644 --- a/src/bridge/EthereumJSBridge.js +++ b/src/bridge/EthereumJSBridge.js @@ -263,7 +263,7 @@ const EthereumBridge: WalletBridge = { getMaxAmount: (a, t) => Promise.resolve(a.balance - t.gasPrice), - signAndBroadcast: async (a, t, deviceId) => { + signAndBroadcast: async ({ account: a, transaction: t, deviceId }) => { const api = apiForCurrency(a.currency) const nonce = await api.getAccountNonce(a.address) From 6a01fd61c29ac91a9056411414faace19c3eaad0 Mon Sep 17 00:00:00 2001 From: meriadec Date: Tue, 22 May 2018 18:12:55 +0200 Subject: [PATCH 6/8] Fix confirm address on device (for BTC-like cryptos) relatable: https://ledgerhq.atlassian.net/secure/RapidBoard.jspa?rapidView=17&modal=detail&selectedIssue=LIVE-113 --- src/components/CurrentAddressForAccount.js | 22 ++++++++ src/components/DeviceCheckAddress.js | 53 +++++++++---------- .../modals/Receive/03-step-confirm-address.js | 4 +- .../modals/Receive/04-step-receive-funds.js | 25 ++++----- 4 files changed, 63 insertions(+), 41 deletions(-) create mode 100644 src/components/CurrentAddressForAccount.js diff --git a/src/components/CurrentAddressForAccount.js b/src/components/CurrentAddressForAccount.js new file mode 100644 index 00000000..6bbd6547 --- /dev/null +++ b/src/components/CurrentAddressForAccount.js @@ -0,0 +1,22 @@ +// @flow + +import React from 'react' +import type { Account } from '@ledgerhq/live-common/lib/types' + +import CurrentAddress from 'components/CurrentAddress' + +type Props = { + account: Account, +} + +export default function CurrentAddressForAccount(props: Props) { + const { account, ...p } = props + + // TODO: handle other cryptos than BTC-like + let freshAddress = account.addresses[0] + if (!freshAddress) { + freshAddress = { str: '', path: '' } + } + + return +} diff --git a/src/components/DeviceCheckAddress.js b/src/components/DeviceCheckAddress.js index b94dadf2..84a6ec78 100644 --- a/src/components/DeviceCheckAddress.js +++ b/src/components/DeviceCheckAddress.js @@ -27,35 +27,34 @@ class CheckAddress extends PureComponent { this.verifyAddress({ device, account }) } - componentDidUnmount() { - if (this.sub) this.sub.unsubscribe() - } + verifyAddress = async ({ device, account }: { device: Device, account: Account }) => { + try { + // TODO: this will work only for BTC-like accounts + const freshAddress = account.addresses[0] + if (!freshAddress) { + throw new Error('Account doesnt have fresh addresses') + } + + const { address } = await getAddress + .send({ + currencyId: account.currency.id, + devicePath: device.path, + path: freshAddress.path, + segwit: account.isSegwit, + verify: true, + }) + .toPromise() - sub: * + if (address !== freshAddress.str) { + throw new Error('Confirmed address is different') + } - verifyAddress = ({ device, account }: { device: Device, account: Account }) => { - this.sub = getAddress - .send({ - currencyId: account.currency.id, - devicePath: device.path, - path: account.path, - segwit: account.isSegwit, - verify: true, - }) - .subscribe({ - next: () => { - this.setState({ - isVerified: true, - }) - this.props.onCheck(true) - }, - error: () => { - this.setState({ - isVerified: false, - }) - this.props.onCheck(false) - }, - }) + this.setState({ isVerified: true }) + this.props.onCheck(true) + } catch (err) { + this.setState({ isVerified: false }) + this.props.onCheck(false) + } } render() { diff --git a/src/components/modals/Receive/03-step-confirm-address.js b/src/components/modals/Receive/03-step-confirm-address.js index 2f205e1b..46cf076f 100644 --- a/src/components/modals/Receive/03-step-confirm-address.js +++ b/src/components/modals/Receive/03-step-confirm-address.js @@ -7,7 +7,7 @@ import type { Account } from '@ledgerhq/live-common/lib/types' import type { Device, T } from 'types/common' import Box from 'components/base/Box' -import CurrentAddress from 'components/CurrentAddress' +import CurrentAddressForAccount from 'components/CurrentAddressForAccount' import DeviceConfirm from 'components/DeviceConfirm' import DeviceCheckAddress from 'components/DeviceCheckAddress' @@ -50,7 +50,7 @@ export default (props: Props) => ( {props.t('receive:steps.confirmAddress.action')} {props.t('receive:steps.confirmAddress.text')} - {props.account && } + {props.account && } {props.device && props.account && ( diff --git a/src/components/modals/Receive/04-step-receive-funds.js b/src/components/modals/Receive/04-step-receive-funds.js index a913b8a7..98096f7f 100644 --- a/src/components/modals/Receive/04-step-receive-funds.js +++ b/src/components/modals/Receive/04-step-receive-funds.js @@ -6,7 +6,7 @@ import type { Account } from '@ledgerhq/live-common/lib/types' import type { T } from 'types/common' import Box from 'components/base/Box' -import CurrentAddress from 'components/CurrentAddress' +import CurrentAddressForAccount from 'components/CurrentAddressForAccount' import Label from 'components/base/Label' import RequestAmount from 'components/RequestAmount' @@ -30,16 +30,17 @@ export default (props: Props) => ( withMax={false} /> - + {props.account && ( + + )} ) From 861178d52abcc617af47b21fc4ff54380505cb45 Mon Sep 17 00:00:00 2001 From: meriadec Date: Tue, 22 May 2018 18:13:44 +0200 Subject: [PATCH 7/8] Prettier and clean --- src/helpers/getAddressForCurrency/index.js | 3 ++- src/internals/index.js | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helpers/getAddressForCurrency/index.js b/src/helpers/getAddressForCurrency/index.js index 329657b5..b96813e3 100644 --- a/src/helpers/getAddressForCurrency/index.js +++ b/src/helpers/getAddressForCurrency/index.js @@ -26,6 +26,7 @@ const all = { ethereum_classic_testnet: ethereum, } -const getAddressForCurrency: Module = (currencyId: string) => all[currencyId] || fallback(currencyId) +const getAddressForCurrency: Module = (currencyId: string) => + all[currencyId] || fallback(currencyId) export default getAddressForCurrency diff --git a/src/internals/index.js b/src/internals/index.js index 88a8ca08..4cc59b34 100644 --- a/src/internals/index.js +++ b/src/internals/index.js @@ -24,7 +24,6 @@ if (handlers.default) { } process.on('message', payload => { - console.log(payload) if (payload.data && payload.data.requestId) { const { data, requestId, id } = payload.data // this is the new type of "command" payload! From d575ae9eea9694da5c84ccfed220d59eddeef273 Mon Sep 17 00:00:00 2001 From: meriadec Date: Wed, 23 May 2018 11:11:09 +0200 Subject: [PATCH 8/8] Flow and feedback fixes --- package.json | 4 ++-- src/bridge/EthereumJSBridge.js | 8 ++++---- src/components/DeviceCheckAddress.js | 17 +++++++++++++++-- yarn.lock | 12 ++++++------ 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index b6ec1bed..29965f00 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@ledgerhq/hw-transport": "^4.12.0", "@ledgerhq/hw-transport-node-hid": "^4.12.0", "@ledgerhq/ledger-core": "^1.0.1", - "@ledgerhq/live-common": "^2.7.2", + "@ledgerhq/live-common": "^2.7.5", "axios": "^0.18.0", "babel-runtime": "^6.26.0", "bcryptjs": "^2.4.3", @@ -83,7 +83,7 @@ "redux-thunk": "^2.2.0", "reselect": "^3.0.1", "rxjs": "^6.2.0", - "rxjs-compat": "^6.2.0", + "rxjs-compat": "^6.1.0", "smooth-scrollbar": "^8.2.7", "source-map": "0.7.2", "source-map-support": "^0.5.4", diff --git a/src/bridge/EthereumJSBridge.js b/src/bridge/EthereumJSBridge.js index 794d617b..4f820111 100644 --- a/src/bridge/EthereumJSBridge.js +++ b/src/bridge/EthereumJSBridge.js @@ -97,12 +97,12 @@ const EthereumBridge: WalletBridge = { const account: Account = { id: accountId, xpub: '', - path, + path, // FIXME we probably not want the address path in the account.path walletPath: String(index), name: 'New Account', isSegwit: false, address, - addresses: [address], + addresses: [{ str: address, path, }], balance, blockHeight: currentBlock.height, archived: true, @@ -128,12 +128,12 @@ const EthereumBridge: WalletBridge = { const account: Account = { id: accountId, xpub: '', - path, + path, // FIXME we probably not want the address path in the account.path walletPath: String(index), name: address.slice(32), isSegwit: false, address, - addresses: [address], + addresses: [{ str: address, path, }], balance, blockHeight: currentBlock.height, archived: true, diff --git a/src/components/DeviceCheckAddress.js b/src/components/DeviceCheckAddress.js index 84a6ec78..0ee2a324 100644 --- a/src/components/DeviceCheckAddress.js +++ b/src/components/DeviceCheckAddress.js @@ -27,6 +27,19 @@ class CheckAddress extends PureComponent { this.verifyAddress({ device, account }) } + componentWillUnmount() { + this._isUnmounted = true + } + + _isUnmounted = false + + safeSetState = (...args: *) => { + if (this._isUnmounted) { + return + } + this.setState(...args) + } + verifyAddress = async ({ device, account }: { device: Device, account: Account }) => { try { // TODO: this will work only for BTC-like accounts @@ -49,10 +62,10 @@ class CheckAddress extends PureComponent { throw new Error('Confirmed address is different') } - this.setState({ isVerified: true }) + this.safeSetState({ isVerified: true }) this.props.onCheck(true) } catch (err) { - this.setState({ isVerified: false }) + this.safeSetState({ isVerified: false }) this.props.onCheck(false) } } diff --git a/yarn.lock b/yarn.lock index cc07b02a..f3e7fa88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1473,9 +1473,9 @@ npm "^5.7.1" prebuild-install "^2.2.2" -"@ledgerhq/live-common@^2.7.2": - version "2.7.2" - resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-2.7.2.tgz#abfa71428c186220006d35baca44261a1c3ef9ed" +"@ledgerhq/live-common@^2.7.5": + version "2.7.5" + resolved "https://registry.yarnpkg.com/@ledgerhq/live-common/-/live-common-2.7.5.tgz#5434bf2e708aaca471be4ca823e613cf27ba700c" dependencies: axios "^0.18.0" invariant "^2.2.2" @@ -12051,9 +12051,9 @@ rx@2.3.24: version "2.3.24" resolved "https://registry.yarnpkg.com/rx/-/rx-2.3.24.tgz#14f950a4217d7e35daa71bbcbe58eff68ea4b2b7" -rxjs-compat@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/rxjs-compat/-/rxjs-compat-6.2.0.tgz#2eb49cc6ac20d0d7057c6887d1895beaab0966f9" +rxjs-compat@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/rxjs-compat/-/rxjs-compat-6.1.0.tgz#935059623ee4c167728c9dd03ee6e4468cc5b583" rxjs@^5.1.1, rxjs@^5.4.2, rxjs@^5.5.2: version "5.5.10"