Loëck Vézien
7 years ago
committed by
GitHub
7 changed files with 274 additions and 76 deletions
@ -0,0 +1,135 @@ |
|||
import { getBalanceHistoryForAccount, getBalanceHistoryForAccounts } from 'helpers/balance' |
|||
|
|||
const counterValues = { |
|||
'BTC-USD': { |
|||
'2018-01-01': 1000, |
|||
'2018-01-02': 2000, |
|||
'2018-01-03': 3000, |
|||
'2018-01-04': 4000, |
|||
'2018-01-05': 5000, |
|||
}, |
|||
} |
|||
|
|||
describe('helpers > balance', () => { |
|||
describe('getBalanceHistoryForAccount', () => { |
|||
test('should handle a simple case', () => { |
|||
const account = { |
|||
coinType: 0, |
|||
balanceByDay: { |
|||
'2018-01-01': 100000000, |
|||
'2018-01-02': 200000000, |
|||
}, |
|||
} |
|||
|
|||
const interval = { |
|||
start: '2018-01-01', |
|||
end: '2018-01-02', |
|||
} |
|||
|
|||
const balances = getBalanceHistoryForAccount({ |
|||
fiat: 'USD', |
|||
account, |
|||
counterValues, |
|||
interval, |
|||
}) |
|||
|
|||
expect(balances).toEqual([ |
|||
{ date: '2018-01-01', balance: 1000 }, |
|||
{ date: '2018-01-02', balance: 4000 }, |
|||
]) |
|||
}) |
|||
|
|||
test('should handle empty days', () => { |
|||
const account = { |
|||
coinType: 0, |
|||
balanceByDay: { |
|||
'2018-01-01': 100000000, |
|||
'2018-01-03': 200000000, |
|||
}, |
|||
} |
|||
|
|||
const interval = { |
|||
start: '2018-01-01', |
|||
end: '2018-01-03', |
|||
} |
|||
|
|||
const balances = getBalanceHistoryForAccount({ |
|||
fiat: 'USD', |
|||
account, |
|||
counterValues, |
|||
interval, |
|||
}) |
|||
|
|||
expect(balances).toEqual([ |
|||
{ date: '2018-01-01', balance: 1000 }, |
|||
{ date: '2018-01-02', balance: 2000 }, |
|||
{ date: '2018-01-03', balance: 6000 }, |
|||
]) |
|||
}) |
|||
|
|||
test('should work if interval dont contain transactions', () => { |
|||
const account = { |
|||
coinType: 0, |
|||
balanceByDay: { |
|||
'2018-01-01': 100000000, |
|||
}, |
|||
} |
|||
|
|||
const interval = { |
|||
start: '2018-01-02', |
|||
end: '2018-01-03', |
|||
} |
|||
|
|||
const balances = getBalanceHistoryForAccount({ |
|||
fiat: 'USD', |
|||
account, |
|||
counterValues, |
|||
interval, |
|||
}) |
|||
|
|||
expect(balances).toEqual([ |
|||
{ date: '2018-01-02', balance: 2000 }, |
|||
{ date: '2018-01-03', balance: 3000 }, |
|||
]) |
|||
}) |
|||
}) |
|||
|
|||
describe('getBalanceHistoryForAccounts', () => { |
|||
test('should merge multiple accounts balance', () => { |
|||
const account1 = { |
|||
coinType: 0, |
|||
balanceByDay: { |
|||
'2018-01-01': 100000000, |
|||
'2018-01-02': 200000000, |
|||
}, |
|||
} |
|||
|
|||
const account2 = { |
|||
coinType: 0, |
|||
balanceByDay: { |
|||
'2018-01-02': 500000000, |
|||
'2018-01-04': 600000000, |
|||
}, |
|||
} |
|||
|
|||
const interval = { |
|||
start: '2018-01-01', |
|||
end: '2018-01-04', |
|||
} |
|||
|
|||
const balances = getBalanceHistoryForAccounts({ |
|||
fiat: 'USD', |
|||
accounts: [account1, account2], |
|||
counterValues, |
|||
interval, |
|||
}) |
|||
|
|||
expect(balances).toEqual([ |
|||
{ date: '2018-01-01', balance: 1000 }, |
|||
{ date: '2018-01-02', balance: 14000 }, |
|||
{ date: '2018-01-03', balance: 21000 }, |
|||
{ date: '2018-01-04', balance: 32000 }, |
|||
]) |
|||
}) |
|||
}) |
|||
}) |
@ -0,0 +1,117 @@ |
|||
// @flow
|
|||
|
|||
import moment from 'moment' |
|||
import isUndefined from 'lodash/isUndefined' |
|||
import { getDefaultUnitByCoinType } from '@ledgerhq/currencies' |
|||
|
|||
import type { Accounts, Account } from 'types/common' |
|||
|
|||
type DateInterval = { |
|||
start: string, |
|||
end: string, |
|||
} |
|||
|
|||
type BalanceHistoryDay = { |
|||
date: string, |
|||
balance: number, |
|||
} |
|||
|
|||
// Map the given date interval
|
|||
// iteratee is given day, index, and currently constructed array
|
|||
// (exactly like Array.map)
|
|||
function mapInterval(iv: DateInterval, cb: Function) { |
|||
const res = [] |
|||
let startDate = moment(iv.start) |
|||
let i = 0 |
|||
const endDate = moment(iv.end) |
|||
res.push(cb(startDate.format('YYYY-MM-DD'), i, res)) |
|||
while (!startDate.isSame(endDate, 'day')) { |
|||
startDate = startDate.add(1, 'day') |
|||
res.push(cb(startDate.format('YYYY-MM-DD'), ++i, res)) |
|||
} |
|||
return res |
|||
} |
|||
|
|||
function getBalanceAtIntervalStart(account: Account, interval: DateInterval): number | null { |
|||
const target = moment(interval.start) |
|||
let res = 0 |
|||
for (const i in account.balanceByDay) { |
|||
if (account.balanceByDay.hasOwnProperty(i)) { |
|||
const d = moment(i) |
|||
if (!d.isBefore(target, 'day')) { |
|||
break |
|||
} |
|||
res = account.balanceByDay[i] || 0 |
|||
} |
|||
} |
|||
return res |
|||
} |
|||
|
|||
export function getBalanceHistoryForAccount({ |
|||
account, |
|||
fiat, |
|||
counterValues, |
|||
interval, |
|||
}: { |
|||
fiat: string, |
|||
account: Account, |
|||
counterValues: Object, |
|||
interval: DateInterval, |
|||
}): Array<BalanceHistoryDay> { |
|||
const unit = getDefaultUnitByCoinType(account.coinType) |
|||
const counterVals = counterValues[`${unit.code}-${fiat}`] |
|||
let lastBalance = getBalanceAtIntervalStart(account, interval) |
|||
return mapInterval(interval, date => { |
|||
let balance = 0 |
|||
|
|||
if (!counterVals) { |
|||
return { balance, date } |
|||
} |
|||
|
|||
// if we don't have data on account balance for that day,
|
|||
// we take the prev day
|
|||
if (isUndefined(account.balanceByDay[date])) { |
|||
balance = lastBalance === null ? 0 : lastBalance / 10 ** unit.magnitude * counterVals[date] |
|||
} else { |
|||
const b = account.balanceByDay[date] |
|||
lastBalance = b |
|||
balance = b / 10 ** unit.magnitude * counterVals[date] |
|||
} |
|||
|
|||
return { date, balance } |
|||
}) |
|||
} |
|||
|
|||
export function getBalanceHistoryForAccounts({ |
|||
accounts, |
|||
fiat, |
|||
counterValues, |
|||
interval, |
|||
}: { |
|||
fiat: string, |
|||
accounts: Accounts, |
|||
counterValues: Object, |
|||
interval: DateInterval, |
|||
}): Array<BalanceHistoryDay> { |
|||
// calculate balance history for each account on the given interval
|
|||
const balances = accounts.map(account => |
|||
getBalanceHistoryForAccount({ |
|||
fiat, |
|||
account, |
|||
counterValues, |
|||
interval, |
|||
}), |
|||
) |
|||
|
|||
// if more than one account, addition all balances, day by day
|
|||
// and returns a big summed up array
|
|||
return balances.length > 1 |
|||
? balances[0].map((item, i) => { |
|||
let b = item.balance |
|||
for (let j = 1; j < balances.length; j++) { |
|||
b += balances[j][i].balance |
|||
} |
|||
return { ...item, balance: b } |
|||
}) |
|||
: balances.length > 0 ? balances[0] : [] |
|||
} |
Loading…
Reference in new issue