You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
3.0 KiB
107 lines
3.0 KiB
// @flow
|
|
|
|
import { handleActions } from 'redux-actions'
|
|
import { createAccountModel } from '@ledgerhq/wallet-common/lib/models/account'
|
|
|
|
import every from 'lodash/every'
|
|
import get from 'lodash/get'
|
|
import reduce from 'lodash/reduce'
|
|
import type { Account } from '@ledgerhq/wallet-common/lib/types'
|
|
|
|
import type { State } from 'reducers'
|
|
|
|
export type AccountsState = Account[]
|
|
const state: AccountsState = []
|
|
|
|
const accountModel = createAccountModel()
|
|
|
|
function orderAccountsOperations(account: Account) {
|
|
const { operations } = account
|
|
operations.sort((a, b) => b.date - a.date)
|
|
return {
|
|
...account,
|
|
operations,
|
|
}
|
|
}
|
|
|
|
const handlers: Object = {
|
|
SET_ACCOUNTS: (
|
|
state: AccountsState,
|
|
{ payload: accounts }: { payload: Account[] },
|
|
): AccountsState => accounts,
|
|
|
|
ADD_ACCOUNT: (
|
|
state: AccountsState,
|
|
{ payload: account }: { payload: Account },
|
|
): AccountsState => [...state, orderAccountsOperations(account)],
|
|
|
|
UPDATE_ACCOUNT: (
|
|
state: AccountsState,
|
|
{ payload: account }: { payload: Account },
|
|
): AccountsState =>
|
|
state.map(existingAccount => {
|
|
if (existingAccount.id !== account.id) {
|
|
return existingAccount
|
|
}
|
|
|
|
const updatedAccount = {
|
|
...existingAccount,
|
|
...account,
|
|
}
|
|
|
|
return orderAccountsOperations(updatedAccount)
|
|
}),
|
|
|
|
REMOVE_ACCOUNT: (state: AccountsState, { payload: account }: { payload: Account }) =>
|
|
state.filter(acc => acc.id !== account.id),
|
|
}
|
|
|
|
// Selectors
|
|
|
|
export function getTotalBalance(state: { accounts: AccountsState }) {
|
|
return reduce(
|
|
state.accounts,
|
|
(result, account) => {
|
|
result += get(account, 'balance', 0)
|
|
return result
|
|
},
|
|
0,
|
|
)
|
|
}
|
|
|
|
export function getAccounts(state: { accounts: AccountsState }): Account[] {
|
|
return state.accounts
|
|
}
|
|
|
|
export function getArchivedAccounts(state: { accounts: AccountsState }): Account[] {
|
|
return state.accounts.filter(acc => acc.archived === true)
|
|
}
|
|
|
|
export function getVisibleAccounts(state: { accounts: AccountsState }): Account[] {
|
|
return getAccounts(state).filter(account => account.archived !== true)
|
|
}
|
|
|
|
export function getAccountById(state: { accounts: AccountsState }, id: string): ?Account {
|
|
return getAccounts(state).find(account => account.id === id)
|
|
}
|
|
|
|
export function canCreateAccount(state: State): boolean {
|
|
return every(getAccounts(state), a => get(a, 'operations.length', 0) > 0)
|
|
}
|
|
|
|
// Yeah. `any` should be `AccountRaw[]` but it can also be a map
|
|
// of wrapped accounts. And as flow is apparently incapable of doing
|
|
// such a simple thing, let's put any, right? I don't care.
|
|
export function serializeAccounts(accounts: any): Account[] {
|
|
// ensure that accounts are always wrapped in data key
|
|
if (accounts.length && !accounts[0].data) {
|
|
accounts = accounts.map(account => ({ data: account }))
|
|
}
|
|
return accounts.map(accountModel.decode)
|
|
}
|
|
|
|
export function deserializeAccounts(accounts: Account[]) {
|
|
return accounts.map(accountModel.encode)
|
|
}
|
|
|
|
export default handleActions(handlers, state)
|
|
|