diff --git a/src/actions/accounts.js b/src/actions/accounts.js index a0642bbb..bb4b20fd 100644 --- a/src/actions/accounts.js +++ b/src/actions/accounts.js @@ -20,7 +20,10 @@ export const fetchAccounts: FetchAccounts = () => ({ payload: db('accounts'), }) -const setAccountData = createAction('SET_ACCOUNT_DATA', (accountID, data) => ({ accountID, data })) +const setAccountData = createAction('DB:SET_ACCOUNT_DATA', (accountID, data) => ({ + accountID, + data, +})) export const syncAccount: Function = account => async (dispatch: Dispatch<*>) => { const { id, ...data } = account diff --git a/src/components/AccountPage.js b/src/components/AccountPage.js index bfcc454c..0d78e4bb 100644 --- a/src/components/AccountPage.js +++ b/src/components/AccountPage.js @@ -39,7 +39,7 @@ class AccountPage extends PureComponent { {format(accountData.balance)} - + {accountData.address} diff --git a/src/components/modals/AddAccount.js b/src/components/modals/AddAccount.js index 9e9ef74a..6639842b 100644 --- a/src/components/modals/AddAccount.js +++ b/src/components/modals/AddAccount.js @@ -219,16 +219,13 @@ class AddAccountModal extends PureComponent { const { inputValue, accounts } = this.state const { addAccount, closeModal } = this.props - const { id, balance, transactions } = accounts[index] + const { id, ...data } = accounts[index] addAccount({ id, name: inputValue.accountName, type: inputValue.wallet, - data: { - balance, - transactions, - }, + data, }) closeModal('add-account') diff --git a/src/helpers/btc.js b/src/helpers/btc.js index c2c49137..92802f1f 100644 --- a/src/helpers/btc.js +++ b/src/helpers/btc.js @@ -32,13 +32,26 @@ export const networks = [ ] export function computeTransaction(addresses: Array<*>) { + // return (transaction: Object) => { + // const outputVal = transaction.outputs + // .filter(o => addresses.includes(o.address)) + // .reduce((acc, cur) => acc + cur.value, 0) + // const inputVal = transaction.inputs + // .filter(i => addresses.includes(i.address)) + // .reduce((acc, cur) => acc + cur.value, 0) + // const balance = outputVal - inputVal + // return { + // ...transaction, + // balance, + // } + // } return (transaction: Object) => { - const outputVal = transaction.outputs - .filter(o => addresses.includes(o.address)) + const outputVal = transaction.out + .filter(o => addresses.includes(o.addr)) .reduce((acc, cur) => acc + cur.value, 0) const inputVal = transaction.inputs - .filter(i => addresses.includes(i.address)) - .reduce((acc, cur) => acc + cur.value, 0) + .filter(i => addresses.includes(i.prev_out.addr)) + .reduce((acc, cur) => acc + cur.prev_out.value, 0) const balance = outputVal - inputVal return { ...transaction, @@ -47,7 +60,7 @@ export function computeTransaction(addresses: Array<*>) { } } -export function getTransactions(addresses: Array) { +export function getTransactions(addresses: Array) { // return axios.get( // `http://api.ledgerwallet.com/blockchain/v2/btc_testnet/addresses/${addresses.join( // ',', @@ -67,6 +80,7 @@ export async function getAccount({ segwit: boolean, network: Object, }) { + const gapLimit = 20 const script = segwit ? parseInt(network.scriptHash, 10) : parseInt(network.pubKeyHash, 10) let transactions = [] @@ -105,11 +119,9 @@ export async function getAccount({ return getAddress({ type: 'external', index: address.index + 1 }) } - const nextPath = (index = 0) => { - const gapLimit = 20 - - return Promise.all( - Array.from(Array(gapLimit).keys()).map(v => + 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 }), @@ -117,13 +129,14 @@ export async function getAccount({ ), ).then(async results => { const addresses = results.reduce((result, v) => [...result, ...v], []) + const listAddresses = addresses.map(a => a.address) const { txs } = await getTransactions(listAddresses) const hasTransactions = txs.length > 0 - transactions = [...transactions, ...txs.map(listAddresses)] + transactions = [...transactions, ...txs.map(computeTransaction(listAddresses))] lastAddress = hasTransactions ? getLastAddress(addresses, txs[0].out[0]) : lastAddress if (hasTransactions) { @@ -144,7 +157,6 @@ export async function getAccount({ : {}), } }) - } return nextPath(currentIndex) } diff --git a/src/internals/accounts/sync.js b/src/internals/accounts/sync.js index f5ccb044..c25f55fb 100644 --- a/src/internals/accounts/sync.js +++ b/src/internals/accounts/sync.js @@ -8,9 +8,9 @@ export default (send: Function) => ({ send('accounts.sync.progress', null, { kill: false }) - const syncAccount = ({ id }) => { + const syncAccount = ({ id, currentIndex }) => { const hdnode = getHDNode({ xpub58: id, network }) - return getAccount({ hdnode, network, segwit: true }).then(account => ({ + return getAccount({ currentIndex, hdnode, network, segwit: true }).then(account => ({ id, ...account, })) diff --git a/src/internals/usb/wallet/accounts.js b/src/internals/usb/wallet/accounts.js index c6202284..f7153446 100644 --- a/src/internals/usb/wallet/accounts.js +++ b/src/internals/usb/wallet/accounts.js @@ -113,21 +113,20 @@ export default async ({ } const hdnode = getHDNode({ xpub58, network }) - const { transactions, balance } = await getAccount({ hdnode, network, segwit }) + const account = await getAccount({ hdnode, network, segwit }) onProgress({ account: currentAccount, - transactions: transactions.length, + transactions: account.transactions.length, }) - const hasTransactions = transactions.length > 0 + const hasTransactions = account.transactions.length > 0 // If the first account is empty we still add it if (currentAccount === 0 || hasTransactions) { accounts[currentAccount] = { id: xpub58, - balance, - transactions, + ...account, } } diff --git a/src/reducers/accounts.js b/src/reducers/accounts.js index 17e2569c..1276bf34 100644 --- a/src/reducers/accounts.js +++ b/src/reducers/accounts.js @@ -22,13 +22,28 @@ const handlers: Object = { SET_ACCOUNT_DATA: ( state: AccountsState, { payload: { accountID, data } }: { payload: { accountID: string, data: AccountData } }, - ): AccountsState => ({ - ...state, - [accountID]: { - ...state[accountID], - data, - }, - }), + ): AccountsState => { + const account = state[accountID] + + const balance = get(account.data, 'balance', 0) + const transactions = get(account.data, 'transactions', []) + const currentIndex = data.currentIndex + ? data.currentIndex + : get(account.data, 'currentIndex', 0) + + account.data = { + ...account.data, + ...data, + balance: balance + data.balance, + currentIndex, + transactions: [...transactions, ...data.transactions], + } + + return { + ...state, + [accountID]: account, + } + }, } // Selectors diff --git a/src/renderer/events.js b/src/renderer/events.js index 231e6357..601eed81 100644 --- a/src/renderer/events.js +++ b/src/renderer/events.js @@ -14,7 +14,7 @@ type MsgPayload = { // wait a bit before launching update check const CHECK_UPDATE_TIMEOUT = 3e3 -const SYNC_ACCOUNT_TIMEOUT = 1e3 +const SYNC_ACCOUNT_TIMEOUT = 5e3 export function sendEvent(channel: string, msgType: string, data: any) { ipcRenderer.send(channel, { @@ -32,8 +32,9 @@ export function sendSyncEvent(channel: string, msgType: string, data: any): any function syncAccounts(accounts) { sendEvent('accounts', 'sync.all', { - accounts: Object.entries(accounts).map(([id]: [string, any]) => ({ + accounts: Object.entries(accounts).map(([id, account]: [string, any]) => ({ id, + currentIndex: account.data.currentIndex, })), }) } diff --git a/src/types/common.js b/src/types/common.js index d1fe6d13..7d8ea066 100644 --- a/src/types/common.js +++ b/src/types/common.js @@ -18,7 +18,9 @@ export type Transaction = { // -------------------- Accounts export type AccountData = { + address: string, balance: number, + currentIndex: number, transactions: Array, }