diff --git a/src/actions/accounts.js b/src/actions/accounts.js index 9336d059..dd859e16 100644 --- a/src/actions/accounts.js +++ b/src/actions/accounts.js @@ -9,7 +9,7 @@ import type { Account } from 'types/common' import { fetchCounterValues } from 'actions/counterValues' -import { startSyncAccounts } from 'renderer/events' +import { startSyncAccounts, startSyncCounterValues } from 'renderer/events' function sortAccounts(accounts, orderAccounts) { const [order, sort] = orderAccounts.split('|') @@ -43,7 +43,7 @@ export const updateOrderAccounts: UpdateOrderAccounts = (orderAccounts: string) export type AddAccount = Account => (Function, Function) => void export const addAccount: AddAccount = payload => (dispatch, getState) => { - const { settings: { orderAccounts }, accounts } = getState() + const { settings: { counterValue, orderAccounts }, accounts } = getState() dispatch({ type: 'ADD_ACCOUNT', payload, @@ -52,7 +52,9 @@ export const addAccount: AddAccount = payload => (dispatch, getState) => { // Start sync accounts the first time you add an account if (accounts.length === 0) { - startSyncAccounts([payload]) + const accounts = [payload] + startSyncCounterValues(counterValue, accounts) + startSyncAccounts(accounts) } } diff --git a/src/actions/counterValues.js b/src/actions/counterValues.js index 22d4c005..e5bc5e70 100644 --- a/src/actions/counterValues.js +++ b/src/actions/counterValues.js @@ -24,6 +24,15 @@ export const updateCounterValues: UpdateCounterValues = payload => ({ payload, }) +export type UpdateLastCounterValueBySymbol = (string, Object) => { type: string, payload: Object } +export const updateLastCounterValueBySymbol: UpdateLastCounterValueBySymbol = (symbol, value) => ({ + type: 'DB:UPDATE_LAST_COUNTER_VALUE', + payload: { + symbol, + value, + }, +}) + export type FetchCounterValues = (?number) => (Dispatch<*>, Function) => Promise export const fetchCounterValues: FetchCounterValues = coinType => (dispatch, getState) => { const { accounts, counterValues, settings } = getState() diff --git a/src/components/CalculateBalance.js b/src/components/CalculateBalance.js index 2bfa370b..3ae67fc4 100644 --- a/src/components/CalculateBalance.js +++ b/src/components/CalculateBalance.js @@ -40,7 +40,6 @@ class CalculateBalance extends PureComponent { const sameAccounts = this.props.accounts === nextProps.accounts const sameCounterValues = this.props.counterValues === nextProps.counterValues const sameDaysCount = this.props.daysCount === nextProps.daysCount - if (!sameAccounts || !sameCounterValues || !sameDaysCount) { this.setState(calculateBalanceToState(nextProps)) } diff --git a/src/components/IsUnlocked.js b/src/components/IsUnlocked.js index 9dae0c42..3401f45d 100644 --- a/src/components/IsUnlocked.js +++ b/src/components/IsUnlocked.js @@ -10,12 +10,18 @@ import type { Settings, Accounts, T } from 'types/common' import get from 'lodash/get' -import { startSyncAccounts, stopSyncAccounts } from 'renderer/events' +import { + startSyncCounterValues, + startSyncAccounts, + stopSyncAccounts, + stopSyncCounterValues, +} from 'renderer/events' import { setEncryptionKey } from 'helpers/db' import { fetchAccounts } from 'actions/accounts' import { getAccounts } from 'reducers/accounts' import { isLocked, unlock } from 'reducers/application' +import { getCounterValue } from 'reducers/settings' import Box from 'components/base/Box' import Input from 'components/base/Input' @@ -27,6 +33,7 @@ type InputValue = { type Props = { accounts: Accounts, children: any, + counterValue: string, fetchAccounts: Function, isLocked: boolean, settings: Settings, @@ -39,8 +46,9 @@ type State = { const mapStateToProps = state => ({ accounts: getAccounts(state), - settings: state.settings, + counterValue: getCounterValue(state), isLocked: isLocked(state), + settings: state.settings, }) const mapDispatchToProps: Object = { @@ -61,16 +69,19 @@ class IsUnlocked extends Component { componentWillMount() { if (this.props.isLocked) { + stopSyncCounterValues() stopSyncAccounts() } } componentWillReceiveProps(nextProps) { if (this.props.isLocked && !nextProps.isLocked) { + startSyncCounterValues(nextProps.counterValue, nextProps.accounts) startSyncAccounts(nextProps.accounts) } if (!this.props.isLocked && nextProps.isLocked) { + stopSyncCounterValues() stopSyncAccounts() } } diff --git a/src/constants.js b/src/constants.js index b776dcd7..a637e9ef 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,5 +1,6 @@ -export const CHECK_UPDATE_TIMEOUT = 5e3 -export const SYNC_ACCOUNT_TIMEOUT = 3e3 +export const CHECK_UPDATE_DELAY = 5e3 +export const SYNC_ACCOUNT_DELAY = 3e3 +export const SYNC_COUNTER_VALUES_DELAY = 60e3 export const MODAL_ADD_ACCOUNT = 'MODAL_ADD_ACCOUNT' export const MODAL_SEND = 'MODAL_SEND' diff --git a/src/main/bridge.js b/src/main/bridge.js index b7d15be4..4e230d54 100644 --- a/src/main/bridge.js +++ b/src/main/bridge.js @@ -8,6 +8,7 @@ import { resolve } from 'path' import cpuUsage from 'helpers/cpuUsage' import setupAutoUpdater, { quitAndInstall } from './autoUpdate' +import counterValuesSync from './counterValuesSync' const { DEV_TOOLS } = process.env @@ -80,6 +81,9 @@ const handlers = { init: setupAutoUpdater, quitAndInstall, }, + counterValues: { + sync: counterValuesSync, + }, kill: { process: (send, { pid }) => { try { diff --git a/src/main/counterValuesSync.js b/src/main/counterValuesSync.js new file mode 100644 index 00000000..09581fc5 --- /dev/null +++ b/src/main/counterValuesSync.js @@ -0,0 +1,24 @@ +// @flow + +import axios from 'axios' + +type SendFunction = (type: string, data: *) => void + +export default async (send: SendFunction, { counterValue, currencies }: Object) => { + const data = await axios + .get( + `https://min-api.cryptocompare.com/data/pricemulti?extraParams=ledger-test&fsyms=${currencies.join( + ',', + )}&tsyms=${counterValue}`, + ) + .then(({ data }) => + currencies.reduce((result, code) => { + result.push({ + symbol: `${code}-${counterValue}`, + value: data[code][counterValue], + }) + return result + }, []), + ) + send('counterValues.update', data) +} diff --git a/src/reducers/counterValues.js b/src/reducers/counterValues.js index ed714024..3c944972 100644 --- a/src/reducers/counterValues.js +++ b/src/reducers/counterValues.js @@ -19,6 +19,24 @@ const handlers = { ...state, ...counterValues, }), + UPDATE_LAST_COUNTER_VALUE: ( + state: CounterValuesState, + { payload: { symbol, value } }: { payload: { symbol: string, value: number } }, + ): CounterValuesState => { + // We update only last value (newer) + if (state[symbol]) { + const [date] = state[symbol].list[0] + // [0] date, [1] value, only update value + state[symbol].list[0][1] = value + // Keep the same value for byDate object + state[symbol].byDate[date] = value + + // Update reference for a proper update + return { ...state } + } + + return state + }, } export function getLastCounterValueBySymbol( diff --git a/src/renderer/events.js b/src/renderer/events.js index f96593d7..cc49ae99 100644 --- a/src/renderer/events.js +++ b/src/renderer/events.js @@ -3,16 +3,20 @@ import { ipcRenderer } from 'electron' import objectPath from 'object-path' import debug from 'debug' +import { getDefaultUnitByCoinType } from '@ledgerhq/currencies' import type { Accounts } from 'types/common' -import { CHECK_UPDATE_TIMEOUT, SYNC_ACCOUNT_TIMEOUT } from 'constants' +import { CHECK_UPDATE_DELAY, SYNC_ACCOUNT_DELAY, SYNC_COUNTER_VALUES_DELAY } from 'constants' -import { updateDevices, addDevice, removeDevice } from 'actions/devices' -import { updateAccount } from 'actions/accounts' -import { setUpdateStatus } from 'reducers/update' import { getAccounts, getAccountById } from 'reducers/accounts' +import { getCounterValue } from 'reducers/settings' import { isLocked } from 'reducers/application' +import { setUpdateStatus } from 'reducers/update' + +import { updateLastCounterValueBySymbol } from 'actions/counterValues' +import { updateAccount } from 'actions/accounts' +import { updateDevices, addDevice, removeDevice } from 'actions/devices' import i18n from 'renderer/i18n/electron' @@ -29,9 +33,11 @@ type MsgPayload = { data: any, } -let syncAccountsInProgress = true +let syncAccountsInProgress = false let syncAccountsTimeout +let syncCounterValuesTimeout + export function sendEvent(channel: string, msgType: string, data: any) { ipcRenderer.send(channel, { type: msgType, @@ -70,9 +76,25 @@ export function stopSyncAccounts() { clearTimeout(syncAccountsTimeout) } +export function startSyncCounterValues(counterValue: string, accounts: Accounts) { + d.sync('Sync counterValues - start') + + sendEvent('msg', 'counterValues.sync', { + counterValue, + currencies: [ + ...new Set(accounts.map(account => getDefaultUnitByCoinType(account.coinType).code)), + ], + }) +} + +export function stopSyncCounterValues() { + d.sync('Sync counterValues - stop') + clearTimeout(syncCounterValuesTimeout) +} + export function checkUpdates() { d.update('Update - check') - setTimeout(() => sendEvent('msg', 'updater.init'), CHECK_UPDATE_TIMEOUT) + setTimeout(() => sendEvent('msg', 'updater.init'), CHECK_UPDATE_DELAY) } export default ({ store, locked }: { store: Object, locked: boolean }) => { @@ -132,7 +154,7 @@ export default ({ store, locked }: { store: Object, locked: boolean }) => { syncAccountsTimeout = setTimeout(() => { const accounts = getAccounts(store.getState()) startSyncAccounts(accounts) - }, SYNC_ACCOUNT_TIMEOUT) + }, SYNC_ACCOUNT_DELAY) } }, }, @@ -152,6 +174,18 @@ export default ({ store, locked }: { store: Object, locked: boolean }) => { store.dispatch(removeDevice(device)) }, }, + counterValues: { + update: counterValues => { + counterValues.map(c => store.dispatch(updateLastCounterValueBySymbol(c.symbol, c.value))) + + syncCounterValuesTimeout = setTimeout(() => { + const state = store.getState() + const accounts = getAccounts(state) + const counterValue = getCounterValue(state) + startSyncCounterValues(counterValue, accounts) + }, SYNC_COUNTER_VALUES_DELAY) + }, + }, updater: { checking: () => store.dispatch(setUpdateStatus('checking')), updateAvailable: info => store.dispatch(setUpdateStatus('available', info)), @@ -177,11 +211,16 @@ export default ({ store, locked }: { store: Object, locked: boolean }) => { // Start detection when we plug/unplug devices sendEvent('usb', 'devices.listen') - if (!locked && !DISABLED_SYNC) { - const accounts = getAccounts(store.getState()) + const state = store.getState() + + if (!locked) { + const accounts = getAccounts(state) + const counterValue = getCounterValue(state) + + startSyncCounterValues(counterValue, accounts) // Start accounts sync only if we have accounts - if (accounts.length > 0) { + if (accounts.length > 0 && !DISABLED_SYNC) { startSyncAccounts(accounts) } }