From c177f6485de117e3a9f7b0b86d4eb5d16d64edf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=ABck=20V=C3=A9zien?= Date: Thu, 25 Jan 2018 18:43:08 +0100 Subject: [PATCH] Make getAsyncAddress for limit CPU usage --- src/helpers/btc.js | 92 ++++++++++++++++++---------------- src/internals/accounts/sync.js | 30 +++++++---- 2 files changed, 69 insertions(+), 53 deletions(-) diff --git a/src/helpers/btc.js b/src/helpers/btc.js index 1ea31955..55d858a8 100644 --- a/src/helpers/btc.js +++ b/src/helpers/btc.js @@ -98,6 +98,9 @@ export async function getAccount({ }), }) + const getAsyncAddress = params => + new Promise(resolve => setTimeout(() => resolve(getAddress(params)), 100)) + const getLastAddress = (addresses, txs) => { const txsAddresses = [...txs.inputs.map(tx => tx.prev_out.addr), ...txs.out.map(tx => tx.addr)] const lastAddress = addresses.reverse().find(a => txsAddresses.includes(a.address)) || { @@ -110,48 +113,53 @@ export async function getAccount({ } const nextPath = (index = 0) => - Promise.all( - Array.from(new Array(gapLimit).keys()).map(v => - Promise.all([ - getAddress({ type: 'external', index: v + index }), - getAddress({ type: 'internal', index: v + index }), - ]), - ), - ).then(async results => { - const addresses = results.reduce((result, v) => [...result, ...v], []) - const listAddresses = addresses.map(a => a.address) - - allAddresses = [...new Set([...allAddresses, ...listAddresses])] - - const { txs } = await getTransactions(listAddresses) - - const hasTransactions = txs.length > 0 - - transactions = [...transactions, ...txs.map(computeTransaction(allAddresses))] - lastAddress = hasTransactions ? getLastAddress(addresses, txs[0]) : lastAddress - - if (hasTransactions) { - return nextPath(index + (gapLimit - 1)) - } - - return { - balance: transactions.reduce((result, v) => { - result += v.balance - return result - }, 0), - allAddresses, - transactions, - ...(lastAddress !== null - ? { - currentIndex: lastAddress.index, - address: lastAddress.address, - } - : { - currentIndex: 0, - address: getAddress({ type: 'external', index: 0 }).address, - }), - } - }) + Array.from(new Array(gapLimit).keys()) + .reduce( + (promise, v) => + promise.then(async results => { + const result = await Promise.all([ + getAsyncAddress({ type: 'external', index: v + index }), + getAsyncAddress({ type: 'internal', index: v + index }), + ]) + return [...results, result] + }), + Promise.resolve([]), + ) + .then(async results => { + const addresses = results.reduce((result, v) => [...result, ...v], []) + const listAddresses = addresses.map(a => a.address) + + allAddresses = [...new Set([...allAddresses, ...listAddresses])] + + const { txs } = await getTransactions(listAddresses) + + const hasTransactions = txs.length > 0 + + transactions = [...transactions, ...txs.map(computeTransaction(allAddresses))] + lastAddress = hasTransactions ? getLastAddress(addresses, txs[0]) : lastAddress + + if (hasTransactions) { + return nextPath(index + (gapLimit - 1)) + } + + return { + balance: transactions.reduce((result, v) => { + result += v.balance + return result + }, 0), + allAddresses, + transactions, + ...(lastAddress !== null + ? { + currentIndex: lastAddress.index, + address: lastAddress.address, + } + : { + currentIndex: 0, + address: getAddress({ type: 'external', index: 0 }).address, + }), + } + }) if (allAddresses.length === 0 && currentIndex > 0) { for (let i = currentIndex; i--; ) { diff --git a/src/internals/accounts/sync.js b/src/internals/accounts/sync.js index c25f55fb..d30d9db6 100644 --- a/src/internals/accounts/sync.js +++ b/src/internals/accounts/sync.js @@ -2,22 +2,30 @@ import { getAccount, getHDNode, networks } from 'helpers/btc' +const network = networks[1] + +function syncAccount({ id, ...currentAccount }) { + const hdnode = getHDNode({ xpub58: id, network }) + return getAccount({ hdnode, network, segwit: true, ...currentAccount }).then(account => ({ + id, + ...account, + })) +} + export default (send: Function) => ({ all: async ({ accounts }: { accounts: Array }) => { - const network = networks[1] - send('accounts.sync.progress', null, { kill: false }) - const syncAccount = ({ id, currentIndex }) => { - const hdnode = getHDNode({ xpub58: id, network }) - return getAccount({ currentIndex, hdnode, network, segwit: true }).then(account => ({ - id, - ...account, - })) - } - try { - const result = await Promise.all(accounts.map(syncAccount)) + const result = await accounts.reduce( + (promise, account) => + promise.then(async results => { + const result = await syncAccount(account) + return [...results, result] + }), + Promise.resolve([]), + ) + send('accounts.sync.success', result) } catch (err) { send('accounts.sync.fail', err.stack || err)