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'),
})
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

2
src/components/AccountPage.js

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

36
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<Object>) {
export function getTransactions(addresses: Array<string>) {
// 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)
}

4
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,
}))

9
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,
}
}

29
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

5
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,
})),
})
}

2
src/types/common.js

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

Loading…
Cancel
Save