Browse Source

Merge pull request #53 from loeck/master

Update dependencies, fix sync Accounts, few clean
master
Meriadec Pillet 7 years ago
committed by GitHub
parent
commit
7039d170ea
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      flow-defs/process.js
  2. 16
      package.json
  3. 14
      src/components/DashboardPage.js
  4. 2
      src/components/SideBar/Item.js
  5. 32
      src/components/SideBar/index.js
  6. 9
      src/components/UpdateNotifier.js
  7. 2
      src/components/Wrapper.js
  8. 4
      src/components/base/Modal/index.js
  9. 91
      src/components/modals/AddAccount.js
  10. 1
      src/components/modals/Receive.js
  11. 1
      src/components/modals/Send.js
  12. 2
      src/constants.js
  13. 38
      src/helpers/btc.js
  14. 16
      src/i18n/en/translation.yml
  15. 16
      src/i18n/fr/translation.yml
  16. 7
      src/internals/index.js
  17. 4
      src/internals/usb/devices.js
  18. 9
      src/internals/usb/wallet/accounts.js
  19. 2
      src/main/app.js
  20. 8
      src/main/bridge.js
  21. 2
      src/main/index.js
  22. 28
      src/reducers/accounts.js
  23. 7
      src/reducers/settings.js
  24. 28
      src/renderer/events.js
  25. 55
      yarn.lock

1
flow-defs/process.js

@ -5,6 +5,7 @@ declare var process: {
on(event: string, args: any): void,
nextTick(callback: Function): void,
setMaxListeners(any): void,
removeListener(string, Function): void,
title: string,
env: Object,
}

16
package.json

@ -39,16 +39,16 @@
},
"dependencies": {
"@ledgerhq/common": "2.0.5",
"@ledgerhq/hw-app-btc": "^2.0.5",
"@ledgerhq/hw-app-eth": "^2.0.5",
"@ledgerhq/hw-transport": "^2.0.5",
"@ledgerhq/hw-transport-node-hid": "^2.0.6",
"@ledgerhq/hw-app-btc": "^2.1.0",
"@ledgerhq/hw-app-eth": "^2.1.0",
"@ledgerhq/hw-transport": "^2.1.0",
"@ledgerhq/hw-transport-node-hid": "^2.1.0",
"axios": "^0.17.1",
"bcryptjs": "^2.4.3",
"bitcoinjs-lib": "^3.3.2",
"blockchain.info": "^2.11.0",
"bs58check": "^2.1.1",
"color": "^2.0.1",
"color": "^3.0.0",
"cross-env": "^5.1.3",
"downshift": "^1.25.0",
"electron-store": "^1.3.0",
@ -65,7 +65,7 @@
"raven-js": "^3.22.1",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-i18next": "^7.3.1",
"react-i18next": "^7.3.2",
"react-mortal": "^3.0.1",
"react-motion": "^0.5.2",
"react-redux": "^5.0.6",
@ -105,11 +105,11 @@
"eslint-config-airbnb": "^16.1.0",
"eslint-config-prettier": "^2.9.0",
"eslint-import-resolver-babel-module": "^4.0.0",
"eslint-plugin-flowtype": "^2.41.1",
"eslint-plugin-flowtype": "^2.42.0",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.5.1",
"flow-bin": "^0.63.1",
"flow-bin": "^0.64.0",
"flow-typed": "^2.2.3",
"husky": "^0.14.3",
"lint-staged": "^6.0.0",

14
src/components/DashboardPage.js

@ -1,12 +1,14 @@
// @flow
import React, { PureComponent } from 'react'
import { compose } from 'redux'
import { translate } from 'react-i18next'
import { connect } from 'react-redux'
import chunk from 'lodash/chunk'
import { push } from 'react-router-redux'
import type { MapStateToProps } from 'react-redux'
import type { Accounts } from 'types/common'
import type { Accounts, T } from 'types/common'
import { format } from 'helpers/btc'
@ -29,6 +31,7 @@ const mapDispatchToProps = {
}
type Props = {
t: T,
accounts: Accounts,
push: Function,
openModal: Function,
@ -53,7 +56,7 @@ class DashboardPage extends PureComponent<Props, State> {
handleChangeTab = tab => this.setState({ tab })
render() {
const { totalBalance, openModal, push, accounts } = this.props
const { t, totalBalance, openModal, push, accounts } = this.props
const { tab } = this.state
const totalAccounts = Object.keys(accounts).length
@ -123,7 +126,7 @@ class DashboardPage extends PureComponent<Props, State> {
style={{ borderStyle: 'dashed', cursor: 'pointer' }}
onClick={() => openModal('add-account')}
>
{'+ Add account'}
{`+ ${t('addAccount.title')}`}
</Box>
) : (
<Card
@ -132,7 +135,8 @@ class DashboardPage extends PureComponent<Props, State> {
style={{ cursor: 'pointer', height: 200 }}
onClick={() => push(`/account/${key}`)}
>
{accounts[key].name}
<div>{accounts[key].name}</div>
<div>{accounts[key].data && format(accounts[key].data.balance)}</div>
</Card>
),
)}
@ -144,4 +148,4 @@ class DashboardPage extends PureComponent<Props, State> {
}
}
export default connect(mapStateToProps, mapDispatchToProps)(DashboardPage)
export default compose(connect(mapStateToProps, mapDispatchToProps), translate())(DashboardPage)

2
src/components/SideBar/Item.js

@ -53,7 +53,7 @@ type Props = {
linkTo?: string | null,
modal?: string | null,
desc?: string | null,
icon?: Element<*> | null,
icon?: string | null,
location: Location,
isModalOpened: boolean,
push: Function,

32
src/components/SideBar/index.js

@ -1,11 +1,13 @@
// @flow
import React, { PureComponent } from 'react'
import { compose } from 'redux'
import { translate } from 'react-i18next'
import styled from 'styled-components'
import { connect } from 'react-redux'
import type { MapStateToProps } from 'react-redux'
import type { Accounts } from 'types/common'
import type { Accounts, T } from 'types/common'
import { openModal } from 'reducers/modals'
import { getAccounts } from 'reducers/accounts'
@ -45,6 +47,7 @@ const BtnAddAccount = styled(Box).attrs({
`
type Props = {
t: T,
accounts: Accounts,
openModal: Function,
}
@ -59,30 +62,30 @@ const mapDispatchToProps = {
class SideBar extends PureComponent<Props> {
render() {
const { accounts, openModal } = this.props
const { t, accounts, openModal } = this.props
return (
<Container bg="night">
<GrowScroll flow={4} py={4}>
<Box flow={2}>
<CapsSubtitle>{'Menu'}</CapsSubtitle>
<CapsSubtitle>{t('sidebar.menu')}</CapsSubtitle>
<div>
<Item icon="bar-chart" linkTo="/">
{'Dashboard'}
{t('dashboard.title')}
</Item>
<Item icon="upload" modal="send">
{'Send'}
{t('send.title')}
</Item>
<Item icon="download" modal="receive">
{'Receive'}
{t('receive.title')}
</Item>
<Item icon="cog" linkTo="/settings">
{'Settings'}
{t('settings.title')}
</Item>
</div>
</Box>
<Box flow={2}>
<CapsSubtitle>{'Accounts'}</CapsSubtitle>
<CapsSubtitle>{t('sidebar.accounts')}</CapsSubtitle>
<div>
{Object.entries(accounts).map(([id, account]: [string, any]) => (
<Item linkTo={`/account/${id}`} desc={format(account.data.balance)} key={id}>
@ -91,13 +94,18 @@ class SideBar extends PureComponent<Props> {
))}
</div>
</Box>
<BtnAddAccount onClick={() => openModal('add-account')}>{'Add account'}</BtnAddAccount>
<BtnAddAccount onClick={() => openModal('add-account')}>
{t('addAccount.title')}
</BtnAddAccount>
</GrowScroll>
</Container>
)
}
}
export default connect(mapStateToProps, mapDispatchToProps, null, {
pure: false,
})(SideBar)
export default compose(
connect(mapStateToProps, mapDispatchToProps, null, {
pure: false,
}),
translate(),
)(SideBar)

9
src/components/UpdateNotifier.js

@ -7,7 +7,7 @@ import type { MapStateToProps } from 'react-redux'
import styled from 'styled-components'
import { getUpdateStatus, getUpdateData } from 'reducers/update'
import { sendEvent } from 'renderer/events'
import { sendEvent, checkUpdates } from 'renderer/events'
import type { State } from 'reducers'
import type { UpdateStatus } from 'reducers/update'
@ -39,6 +39,12 @@ const Container = styled(Box).attrs({
`
class UpdateNotifier extends PureComponent<Props> {
componentWillReceiveProps(nextProps) {
if (['idle', 'unavailable', 'error'].includes(nextProps.updateStatus)) {
checkUpdates()
}
}
renderStatus() {
const { updateStatus } = this.props
switch (updateStatus) {
@ -68,6 +74,7 @@ class UpdateNotifier extends PureComponent<Props> {
render() {
const { updateStatus } = this.props
const isToggled = updateStatus === 'downloaded'
return (
<Motion

2
src/components/Wrapper.js

@ -36,7 +36,7 @@ class Wrapper extends Component<{}> {
<Box shrink grow bg="cream" color="grey">
<TopBar />
<Box grow relative>
<UpdateNotifier />
{__PROD__ && <UpdateNotifier />}
<GrowScroll p={4}>
<Route path="/" exact component={DashboardPage} />
<Route path="/settings" component={SettingsPage} />

4
src/components/base/Modal/index.js

@ -9,8 +9,6 @@ import Mortal from 'react-mortal'
import styled from 'styled-components'
import noop from 'lodash/noop'
import type { Element } from 'react'
import { rgba } from 'styles/helpers'
import { closeModal, isModalOpened } from 'reducers/modals'
@ -139,7 +137,7 @@ export const ModalBody = ({
onClose,
...props
}: {
children: Element<any> | string,
children: any,
onClose?: Function,
}) => (
<Body>

91
src/components/modals/AddAccount.js

@ -8,7 +8,7 @@ import type { MapStateToProps } from 'react-redux'
import type { Accounts, Device } from 'types/common'
import { closeModal } from 'reducers/modals'
import { getAccounts } from 'reducers/accounts'
import { canCreateAccount, getAccounts } from 'reducers/accounts'
import { getCurrentDevice } from 'reducers/devices'
import { sendEvent } from 'renderer/events'
@ -46,14 +46,18 @@ const Steps = {
</Box>
<Box horizontal justify="flex-end">
<Button primary type="submit">
Create account
Add account
</Button>
</Box>
</Box>
</form>
),
connectDevice: () => <div>Connect your Ledger</div>,
startWallet: (props: Object) => <div>Select {props.wallet.toUpperCase()} App on your Ledger</div>,
connectDevice: (props: Object) => (
<div>
<div>Connect your Ledger: {props.connected ? 'ok' : 'ko'}</div>
<div>Start {props.wallet.toUpperCase()} App on your Ledger: ko</div>
</div>
),
inProgress: (props: Object) => (
<div>
In progress.
@ -65,20 +69,38 @@ const Steps = {
</div>
),
listAccounts: (props: Object) => {
const accounts = Object.entries(props.accounts)
const accounts = []
let newAccount = null
Object.entries(props.accounts).forEach(([, account]: [string, any]) => {
const hasTransactions = account.transactions.length > 0
if (hasTransactions) {
accounts.push(account)
} else {
newAccount = account
}
})
return (
<div>
{accounts.length > 0
? accounts.map(([index, account]: [string, any]) => (
<div key={index}>
<div>Balance: {account.balance}</div>
<div>Transactions: {account.transactions.length}</div>
<div>
<Button onClick={props.onAddAccount(index)}>Import</Button>
</div>
</div>
))
: 'No accounts'}
{accounts.map(account => (
<div key={account.id} style={{ marginBottom: 10 }}>
<div>Balance: {account.balance}</div>
<div>Transactions: {account.transactions.length}</div>
<div>
<Button onClick={props.onAddAccount(account)}>Import</Button>
</div>
</div>
))}
{props.canCreateAccount && newAccount !== null ? (
<div>
<Button onClick={props.onAddAccount(newAccount)}>Create new account</Button>
</div>
) : (
<div>You cannot create new account</div>
)}
</div>
)
},
@ -89,13 +111,14 @@ type InputValue = {
wallet: string,
}
type Step = 'createAccount' | 'connectDevice' | 'inProgress' | 'startWallet' | 'listAccounts'
type Step = 'createAccount' | 'connectDevice' | 'inProgress' | 'listAccounts'
type Props = {
accounts: Accounts,
addAccount: Function,
canCreateAccount: boolean,
closeModal: Function,
currentDevice: Device | null,
accounts: Accounts,
}
type State = {
inputValue: InputValue,
@ -106,6 +129,7 @@ type State = {
const mapStateToProps: MapStateToProps<*, *, *> = state => ({
accounts: getAccounts(state),
canCreateAccount: canCreateAccount(state),
currentDevice: getCurrentDevice(state),
})
@ -133,21 +157,11 @@ class AddAccountModal extends PureComponent<Props, State> {
ipcRenderer.on('msg', this.handleWalletRequest)
}
componentWillReceiveProps(nextProps) {
const { currentDevice } = nextProps
if (this.props.currentDevice === null && this.state.step !== 'createAccount') {
this.setState({
step: currentDevice !== null ? 'startWallet' : 'connectDevice',
})
}
}
componentDidUpdate() {
const { step } = this.state
const { currentDevice } = this.props
if (step === 'startWallet' && currentDevice !== null) {
if (step === 'connectDevice' && currentDevice !== null) {
this.getWalletInfos()
} else {
clearTimeout(this._timeout)
@ -160,8 +174,8 @@ class AddAccountModal extends PureComponent<Props, State> {
}
getWalletInfos() {
const { inputValue } = this.state
const { currentDevice, accounts } = this.props
const { inputValue } = this.state
if (currentDevice === null) {
return
@ -175,6 +189,7 @@ class AddAccountModal extends PureComponent<Props, State> {
}
getStepProps() {
const { currentDevice, canCreateAccount } = this.props
const { inputValue, step, progress, accounts } = this.state
const props = (predicate, props) => (predicate ? props : {})
@ -185,7 +200,8 @@ class AddAccountModal extends PureComponent<Props, State> {
onSubmit: this.handleSubmit,
onChangeInput: this.handleChangeInput,
}),
...props(step === 'startWallet', {
...props(step === 'connectDevice', {
connected: currentDevice !== null,
wallet: inputValue.wallet,
}),
...props(step === 'inProgress', {
@ -193,6 +209,7 @@ class AddAccountModal extends PureComponent<Props, State> {
}),
...props(step === 'listAccounts', {
accounts,
canCreateAccount,
onAddAccount: this.handleAddAccount,
}),
}
@ -218,11 +235,11 @@ class AddAccountModal extends PureComponent<Props, State> {
}
}
handleAddAccount = index => () => {
const { inputValue, accounts } = this.state
handleAddAccount = account => () => {
const { inputValue } = this.state
const { addAccount, closeModal } = this.props
const { id, ...data } = accounts[index]
const { id, ...data } = account
addAccount({
id,
@ -232,6 +249,7 @@ class AddAccountModal extends PureComponent<Props, State> {
})
closeModal('add-account')
this.handleClose()
}
@ -246,7 +264,6 @@ class AddAccountModal extends PureComponent<Props, State> {
handleSubmit = (e: SyntheticEvent<HTMLFormElement>) => {
e.preventDefault()
const { currentDevice } = this.props
const { inputValue } = this.state
if (inputValue.accountName.trim() === '' || inputValue.wallet.trim() === '') {
@ -254,7 +271,7 @@ class AddAccountModal extends PureComponent<Props, State> {
}
this.setState({
step: currentDevice === null ? 'connectDevice' : 'startWallet',
step: 'connectDevice',
})
}
@ -275,7 +292,7 @@ class AddAccountModal extends PureComponent<Props, State> {
return (
<Modal
name="add-account"
preventBackdropClick
preventBackdropClick={step !== 'createAccount'}
onClose={this.handleClose}
render={({ onClose }) => (
<ModalBody onClose={onClose} flow={3}>

1
src/components/modals/Receive.js

@ -11,7 +11,6 @@ class ReceiveModal extends PureComponent<Props> {
return (
<Modal
name="receive"
preventBackdropClick
render={({ onClose }) => <ModalBody onClose={onClose}>receive modal</ModalBody>}
/>
)

1
src/components/modals/Send.js

@ -149,7 +149,6 @@ class Send extends PureComponent<Props, State> {
return (
<Modal
name="send"
preventBackdropClick
onClose={this.handleClose}
render={({ onClose }) => (
<Fragment>

2
src/constants.js

@ -0,0 +1,2 @@
export const CHECK_UPDATE_TIMEOUT = 5e3
export const SYNC_ACCOUNT_TIMEOUT = 5e3

38
src/helpers/btc.js

@ -84,6 +84,7 @@ export async function getAccount({
const script = segwit ? parseInt(network.scriptHash, 10) : parseInt(network.pubKeyHash, 10)
let transactions = []
let allAddresses = []
let lastAddress = null
const pubKeyToSegwitAddress = (pubKey, scriptVersion) => {
@ -111,12 +112,15 @@ export async function getAccount({
}),
})
const getLastAddress = (addresses, lastTx) => {
const address = addresses
.filter(a => a.type === 'external')
.find(a => a.address === lastTx.addr) || { index: 0 }
return getAddress({ type: 'external', index: address.index + 1 })
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)) || {
index: 0,
}
return {
index: lastAddress.index,
address: getAddress({ type: 'external', index: lastAddress.index + 1 }).address,
}
}
const nextPath = (index = 0) =>
@ -129,15 +133,16 @@ export async function getAccount({
),
).then(async results => {
const addresses = results.reduce((result, v) => [...result, ...v], [])
const listAddresses = addresses.map(a => a.address)
allAddresses = [...allAddresses, ...listAddresses]
const { txs } = await getTransactions(listAddresses)
const hasTransactions = txs.length > 0
transactions = [...transactions, ...txs.map(computeTransaction(listAddresses))]
lastAddress = hasTransactions ? getLastAddress(addresses, txs[0].out[0]) : lastAddress
transactions = [...transactions, ...txs.map(computeTransaction(allAddresses))]
lastAddress = hasTransactions ? getLastAddress(addresses, txs[0]) : lastAddress
if (hasTransactions) {
return nextPath(index + (gapLimit - 1))
@ -154,10 +159,23 @@ export async function getAccount({
currentIndex: lastAddress.index,
address: lastAddress.address,
}
: {}),
: {
currentIndex: 0,
address: getAddress({ type: 'external', index: 0 }).address,
}),
}
})
if (currentIndex > 0) {
for (let i = currentIndex; i--; ) {
allAddresses = [
...allAddresses,
getAddress({ type: 'internal', index: i }).address,
getAddress({ type: 'external', index: i }).address,
]
}
}
return nextPath(currentIndex)
}

16
src/i18n/en/translation.yml

@ -9,6 +9,22 @@ language:
en: English
fr: French
sidebar:
menu: Menu
accounts: Accounts
dashboard:
title: Dashboard
send:
title: Send
receive:
title: Receive
addAccount:
title: Add account
settings:
title: Settings

16
src/i18n/fr/translation.yml

@ -9,6 +9,22 @@ language:
en: Anglais
fr: Français
sidebar:
menu: Menu
accounts: Comptes
dashboard:
title: Tableau de bord
send:
title: Envoyer
receive:
title: Recevoir
addAccount:
title: Ajouter un compte
settings:
title: Réglages

7
src/internals/index.js

@ -16,12 +16,13 @@ const handlers = Object.keys(func).reduce((result, key) => {
return result
}, {})
process.on('message', payload => {
const onMessage = payload => {
const { type, data } = payload
const handler = objectPath.get(handlers, type)
if (!handler) {
return
}
handler(data)
})
}
process.on('message', onMessage)

4
src/internals/usb/devices.js

@ -1,8 +1,6 @@
// @flow
import CommNodeHid from '@ledgerhq/hw-transport-node-hid'
export default (send: Function) => ({
export default send => ({
listen: () => {
CommNodeHid.listen({
next: e => {

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

@ -122,12 +122,9 @@ export default async ({
const hasTransactions = account.transactions.length > 0
// If the first account is empty we still add it
if (currentAccount === 0 || hasTransactions) {
accounts[currentAccount] = {
id: xpub58,
...account,
}
accounts[currentAccount] = {
id: xpub58,
...account,
}
if (hasTransactions) {

2
src/main/app.js

@ -2,8 +2,6 @@
import { app, BrowserWindow } from 'electron'
process.setMaxListeners(100)
// necessary to prevent win from being garbage collected
let mainWindow

8
src/main/bridge.js

@ -24,8 +24,7 @@ function onForkChannel(forkType, callType) {
}
}
compute.send({ type, data })
compute.on('message', payload => {
const onMessage = payload => {
const { type, data, options = {} } = payload
if (callType === 'async') {
event.sender.send('msg', { type, data })
@ -36,7 +35,10 @@ function onForkChannel(forkType, callType) {
if (options.kill && compute) {
kill()
}
})
}
compute.on('message', onMessage)
compute.send({ type, data })
process.on('exit', kill)
}

2
src/main/index.js

@ -1,5 +1,7 @@
// @flow
process.setMaxListeners(0)
require('../globals')
require('./bridge')
require('./app')

28
src/reducers/accounts.js

@ -1,8 +1,11 @@
// @flow
import { handleActions } from 'redux-actions'
import every from 'lodash/every'
import get from 'lodash/get'
import reduce from 'lodash/reduce'
import uniqBy from 'lodash/uniqBy'
import type { State } from 'reducers'
import type { Account, Accounts, AccountData } from 'types/common'
@ -12,11 +15,15 @@ export type AccountsState = Accounts
const state: AccountsState = {}
function getAccount(account: Account) {
const transactions = get(account.data, 'transactions', [])
transactions.sort((a, b) => b.time - a.time)
return {
...account,
data: {
...account.data,
transactions: get(account.data, 'transactions', []).sort((a, b) => b.time - a.time),
...(account.data || {}),
transactions,
},
}
}
@ -34,16 +41,21 @@ const handlers: Object = {
const account = state[accountID]
const { data: accountData } = account
const balance = get(accountData, 'balance', 0)
const transactions = get(accountData, 'transactions', [])
const transactions = uniqBy(
[...get(accountData, 'transactions', []), ...data.transactions],
tx => tx.hash,
)
const currentIndex = data.currentIndex ? data.currentIndex : get(accountData, 'currentIndex', 0)
account.data = {
...accountData,
...data,
balance: balance + data.balance,
balance: transactions.reduce((result, v) => {
result += v.balance
return result
}, 0),
currentIndex,
transactions: [...transactions, ...data.transactions],
transactions,
}
return {
@ -81,4 +93,8 @@ export function getAccountData(state: State, id: string): AccountData | null {
return get(getAccountById(state, id), 'data', null)
}
export function canCreateAccount(state: State): boolean {
return every(getAccounts(state), a => a.data.transactions.length > 0)
}
export default handleActions(handlers, state)

7
src/reducers/settings.js

@ -8,7 +8,12 @@ import type { Settings } from 'types/common'
export type SettingsState = Object
const state: SettingsState = {}
const state: SettingsState = {
language: 'en',
password: {
state: false,
},
}
const handlers: Object = {
SAVE_SETTINGS: (state: SettingsState, { payload: settings }: { payload: Settings }) => ({

28
src/renderer/events.js

@ -6,6 +6,8 @@ import get from 'lodash/get'
import type { Accounts } from 'types/common'
import { CHECK_UPDATE_TIMEOUT, SYNC_ACCOUNT_TIMEOUT } from 'constants'
import { updateDevices, addDevice, removeDevice } from 'actions/devices'
import { syncAccount } from 'actions/accounts'
import { setUpdateStatus } from 'reducers/update'
@ -16,10 +18,6 @@ type MsgPayload = {
data: any,
}
// wait a bit before launching update check
const CHECK_UPDATE_TIMEOUT = 3e3
const SYNC_ACCOUNT_TIMEOUT = 5e3
let syncAccounts = true
let syncTimeout
@ -39,11 +37,15 @@ export function sendSyncEvent(channel: string, msgType: string, data: any): any
export function startSyncAccounts(accounts: Accounts) {
syncAccounts = true
sendEvent('accounts', 'sync.all', {
accounts: Object.entries(accounts).map(([id, account]: [string, any]) => ({
id,
currentIndex: get(account, 'data.currentIndex', 0),
})),
accounts: Object.entries(accounts).map(([id, account]: [string, any]) => {
const currentIndex = get(account, 'data.currentIndex', 0)
return {
id,
currentIndex,
}
}),
})
}
@ -52,13 +54,19 @@ export function stopSyncAccounts() {
clearTimeout(syncTimeout)
}
export function checkUpdates() {
setTimeout(() => sendEvent('msg', 'updater.init'), CHECK_UPDATE_TIMEOUT)
}
export default ({ store, locked }: { store: Object, locked: boolean }) => {
const handlers = {
accounts: {
sync: {
success: accounts => {
if (syncAccounts) {
accounts.forEach(account => store.dispatch(syncAccount(account)))
accounts.forEach(
account => account.transactions.length > 0 && store.dispatch(syncAccount(account)),
)
syncTimeout = setTimeout(() => {
const newAccounts = getAccounts(store.getState())
startSyncAccounts(newAccounts)
@ -107,6 +115,6 @@ export default ({ store, locked }: { store: Object, locked: boolean }) => {
if (__PROD__) {
// Start check of eventual updates
setTimeout(() => sendEvent('msg', 'updater.init'), CHECK_UPDATE_TIMEOUT)
checkUpdates()
}
}

55
yarn.lock

@ -93,31 +93,30 @@
redux "^3.7.2"
redux-thunk "^2.2.0"
"@ledgerhq/hw-app-btc@^2.0.5":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-2.0.5.tgz#44dabd18c4dcc68127869d384b06f0601c4a7a0e"
"@ledgerhq/hw-app-btc@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-2.1.0.tgz#6f7354ac4838eda4d78252b4fe984cd034a317bf"
dependencies:
"@ledgerhq/hw-transport" "^2.0.5"
"@ledgerhq/hw-transport" "^2.1.0"
"@ledgerhq/hw-app-eth@^2.0.5":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-2.0.5.tgz#844d938d7985f498058e7bd5cd48bc86b510d5ec"
"@ledgerhq/hw-app-eth@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-2.1.0.tgz#66dfbe4b11be9e22ab5574db603cd70aa9b82bf0"
dependencies:
"@ledgerhq/hw-transport" "^2.0.5"
"@ledgerhq/hw-transport" "^2.1.0"
"@ledgerhq/hw-transport-node-hid@^2.0.6":
version "2.0.6"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-2.0.6.tgz#29e76b05156218ccd1fe4c78c887829ac9598f98"
"@ledgerhq/hw-transport-node-hid@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-2.1.0.tgz#bcaeab27feb7d869f8a8d96cee1e4934f3c87040"
dependencies:
"@ledgerhq/hw-transport" "^2.0.5"
"@ledgerhq/hw-transport" "^2.1.0"
node-hid "^0.7.2"
"@ledgerhq/hw-transport@^2.0.5":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-2.0.5.tgz#5070a0e8dfb22f365b08dcf10fb03a8bf44fa5bf"
"@ledgerhq/hw-transport@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-2.1.0.tgz#7d8460a2ea8d5344796482458b6adb11c1cfc706"
dependencies:
events "^1.1.1"
invariant "^2.2.0"
"@storybook/addon-actions@^3.3.10":
version "3.3.10"
@ -2411,9 +2410,9 @@ color@^0.11.0:
color-convert "^1.3.0"
color-string "^0.3.0"
color@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color/-/color-2.0.1.tgz#e4ed78a3c4603d0891eba5430b04b86314f4c839"
color@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a"
dependencies:
color-convert "^1.9.1"
color-string "^1.5.2"
@ -3570,9 +3569,9 @@ eslint-module-utils@^2.1.1:
debug "^2.6.8"
pkg-dir "^1.0.0"
eslint-plugin-flowtype@^2.41.1:
version "2.41.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.41.1.tgz#0996e1ea1d501dfc945802453a304ae9e8098b78"
eslint-plugin-flowtype@^2.42.0:
version "2.42.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.42.0.tgz#7fcc98df4ed9482a22ac10ba4ca48d649c4c733a"
dependencies:
lodash "^4.15.0"
@ -4063,9 +4062,9 @@ flatten@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
flow-bin@^0.63.1:
version "0.63.1"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.63.1.tgz#ab00067c197169a5fb5b4996c8f6927b06694828"
flow-bin@^0.64.0:
version "0.64.0"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.64.0.tgz#ddd3fb3b183ab1ab35a5d5dec9caf5ebbcded167"
flow-typed@^2.2.3:
version "2.2.3"
@ -7323,9 +7322,9 @@ react-html-attributes@^1.3.0:
dependencies:
html-element-attributes "^1.0.0"
react-i18next@^7.3.1:
version "7.3.1"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-7.3.1.tgz#b0ca03db9cc4d4067b6481d09d902a5166d620a0"
react-i18next@^7.3.2:
version "7.3.2"
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-7.3.2.tgz#5036dc0371808bd8afe0c9a4a738ebd39721e33b"
dependencies:
hoist-non-react-statics "2.3.1"
html-parse-stringify2 "2.0.1"

Loading…
Cancel
Save