Browse Source

Store lastAdress and lastIndex for better sync

master
Loëck Vézien 7 years ago
parent
commit
6168ea729b
No known key found for this signature in database GPG Key ID: CBCDCE384E853AC4
  1. 5
      src/actions/accounts.js
  2. 2
      src/components/AccountPage.js
  3. 7
      src/components/modals/AddAccount.js
  4. 36
      src/helpers/btc.js
  5. 4
      src/internals/accounts/sync.js
  6. 9
      src/internals/usb/wallet/accounts.js
  7. 29
      src/reducers/accounts.js
  8. 5
      src/renderer/events.js
  9. 2
      src/types/common.js

5
src/actions/accounts.js

@ -20,7 +20,10 @@ export const fetchAccounts: FetchAccounts = () => ({
payload: db('accounts'), 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<*>) => { export const syncAccount: Function = account => async (dispatch: Dispatch<*>) => {
const { id, ...data } = account const { id, ...data } = account

2
src/components/AccountPage.js

@ -39,7 +39,7 @@ class AccountPage extends PureComponent<Props> {
<Card title="Balance">{format(accountData.balance)}</Card> <Card title="Balance">{format(accountData.balance)}</Card>
</Box> </Box>
<Box flex={1}> <Box flex={1}>
<Card title="Receive" /> <Card title="Receive">{accountData.address}</Card>
</Box> </Box>
</Box> </Box>
<Card title="Last operations"> <Card title="Last operations">

7
src/components/modals/AddAccount.js

@ -219,16 +219,13 @@ class AddAccountModal extends PureComponent<Props, State> {
const { inputValue, accounts } = this.state const { inputValue, accounts } = this.state
const { addAccount, closeModal } = this.props const { addAccount, closeModal } = this.props
const { id, balance, transactions } = accounts[index] const { id, ...data } = accounts[index]
addAccount({ addAccount({
id, id,
name: inputValue.accountName, name: inputValue.accountName,
type: inputValue.wallet, type: inputValue.wallet,
data: { data,
balance,
transactions,
},
}) })
closeModal('add-account') closeModal('add-account')

36
src/helpers/btc.js

@ -32,13 +32,26 @@ export const networks = [
] ]
export function computeTransaction(addresses: Array<*>) { 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) => { return (transaction: Object) => {
const outputVal = transaction.outputs const outputVal = transaction.out
.filter(o => addresses.includes(o.address)) .filter(o => addresses.includes(o.addr))
.reduce((acc, cur) => acc + cur.value, 0) .reduce((acc, cur) => acc + cur.value, 0)
const inputVal = transaction.inputs const inputVal = transaction.inputs
.filter(i => addresses.includes(i.address)) .filter(i => addresses.includes(i.prev_out.addr))
.reduce((acc, cur) => acc + cur.value, 0) .reduce((acc, cur) => acc + cur.prev_out.value, 0)
const balance = outputVal - inputVal const balance = outputVal - inputVal
return { return {
...transaction, ...transaction,
@ -47,7 +60,7 @@ export function computeTransaction(addresses: Array<*>) {
} }
} }
export function getTransactions(addresses: Array<Object>) { export function getTransactions(addresses: Array<string>) {
// return axios.get( // return axios.get(
// `http://api.ledgerwallet.com/blockchain/v2/btc_testnet/addresses/${addresses.join( // `http://api.ledgerwallet.com/blockchain/v2/btc_testnet/addresses/${addresses.join(
// ',', // ',',
@ -67,6 +80,7 @@ export async function getAccount({
segwit: boolean, segwit: boolean,
network: Object, network: Object,
}) { }) {
const gapLimit = 20
const script = segwit ? parseInt(network.scriptHash, 10) : parseInt(network.pubKeyHash, 10) const script = segwit ? parseInt(network.scriptHash, 10) : parseInt(network.pubKeyHash, 10)
let transactions = [] let transactions = []
@ -105,11 +119,9 @@ export async function getAccount({
return getAddress({ type: 'external', index: address.index + 1 }) return getAddress({ type: 'external', index: address.index + 1 })
} }
const nextPath = (index = 0) => { const nextPath = (index = 0) =>
const gapLimit = 20 Promise.all(
Array.from(new Array(gapLimit).keys()).map(v =>
return Promise.all(
Array.from(Array(gapLimit).keys()).map(v =>
Promise.all([ Promise.all([
getAddress({ type: 'external', index: v + index }), getAddress({ type: 'external', index: v + index }),
getAddress({ type: 'internal', index: v + index }), getAddress({ type: 'internal', index: v + index }),
@ -117,13 +129,14 @@ export async function getAccount({
), ),
).then(async results => { ).then(async results => {
const addresses = results.reduce((result, v) => [...result, ...v], []) const addresses = results.reduce((result, v) => [...result, ...v], [])
const listAddresses = addresses.map(a => a.address) const listAddresses = addresses.map(a => a.address)
const { txs } = await getTransactions(listAddresses) const { txs } = await getTransactions(listAddresses)
const hasTransactions = txs.length > 0 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 lastAddress = hasTransactions ? getLastAddress(addresses, txs[0].out[0]) : lastAddress
if (hasTransactions) { if (hasTransactions) {
@ -144,7 +157,6 @@ export async function getAccount({
: {}), : {}),
} }
}) })
}
return nextPath(currentIndex) return nextPath(currentIndex)
} }

4
src/internals/accounts/sync.js

@ -8,9 +8,9 @@ export default (send: Function) => ({
send('accounts.sync.progress', null, { kill: false }) send('accounts.sync.progress', null, { kill: false })
const syncAccount = ({ id }) => { const syncAccount = ({ id, currentIndex }) => {
const hdnode = getHDNode({ xpub58: id, network }) const hdnode = getHDNode({ xpub58: id, network })
return getAccount({ hdnode, network, segwit: true }).then(account => ({ return getAccount({ currentIndex, hdnode, network, segwit: true }).then(account => ({
id, id,
...account, ...account,
})) }))

9
src/internals/usb/wallet/accounts.js

@ -113,21 +113,20 @@ export default async ({
} }
const hdnode = getHDNode({ xpub58, network }) const hdnode = getHDNode({ xpub58, network })
const { transactions, balance } = await getAccount({ hdnode, network, segwit }) const account = await getAccount({ hdnode, network, segwit })
onProgress({ onProgress({
account: currentAccount, 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 the first account is empty we still add it
if (currentAccount === 0 || hasTransactions) { if (currentAccount === 0 || hasTransactions) {
accounts[currentAccount] = { accounts[currentAccount] = {
id: xpub58, id: xpub58,
balance, ...account,
transactions,
} }
} }

29
src/reducers/accounts.js

@ -22,13 +22,28 @@ const handlers: Object = {
SET_ACCOUNT_DATA: ( SET_ACCOUNT_DATA: (
state: AccountsState, state: AccountsState,
{ payload: { accountID, data } }: { payload: { accountID: string, data: AccountData } }, { payload: { accountID, data } }: { payload: { accountID: string, data: AccountData } },
): AccountsState => ({ ): AccountsState => {
...state, const account = state[accountID]
[accountID]: {
...state[accountID], const balance = get(account.data, 'balance', 0)
data, 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 // Selectors

5
src/renderer/events.js

@ -14,7 +14,7 @@ type MsgPayload = {
// wait a bit before launching update check // wait a bit before launching update check
const CHECK_UPDATE_TIMEOUT = 3e3 const CHECK_UPDATE_TIMEOUT = 3e3
const SYNC_ACCOUNT_TIMEOUT = 1e3 const SYNC_ACCOUNT_TIMEOUT = 5e3
export function sendEvent(channel: string, msgType: string, data: any) { export function sendEvent(channel: string, msgType: string, data: any) {
ipcRenderer.send(channel, { ipcRenderer.send(channel, {
@ -32,8 +32,9 @@ export function sendSyncEvent(channel: string, msgType: string, data: any): any
function syncAccounts(accounts) { function syncAccounts(accounts) {
sendEvent('accounts', 'sync.all', { sendEvent('accounts', 'sync.all', {
accounts: Object.entries(accounts).map(([id]: [string, any]) => ({ accounts: Object.entries(accounts).map(([id, account]: [string, any]) => ({
id, id,
currentIndex: account.data.currentIndex,
})), })),
}) })
} }

2
src/types/common.js

@ -18,7 +18,9 @@ export type Transaction = {
// -------------------- Accounts // -------------------- Accounts
export type AccountData = { export type AccountData = {
address: string,
balance: number, balance: number,
currentIndex: number,
transactions: Array<Transaction>, transactions: Array<Transaction>,
} }

Loading…
Cancel
Save