const csvToJson = require('convert-csv-to-json') const converter = require('json-2-csv') const fs = require('fs') const BN = require('bignumber.js') const txs = csvToJson.fieldDelimiter(',').getJsonFromCsv(`../Ledger.csv`) let utxos = [] let dispositions = [] const handleBuy = (tx, i) => { const { Date: date, Asset, Received, Price } = tx utxos.push({ Date: date, Id: i, Asset, Amount: Received, Price, Remaining: new BN(Received), }) } const createDisposition = (tx, utxo, amount) => { const st = new Date(tx.Date).valueOf() - new Date(utxo.Date).valueOf() < 31556926000 const costBasis = amount.times(utxo.Price) const proceeds = amount.times(tx.Price) const gainLoss = proceeds.minus(costBasis) const disposition = { Date: tx.Date, Asset: tx.Asset, Utxo: utxo.Id, Amount: amount.toFixed(8), PurchasePrice: utxo.Price, DateAcquired: utxo.Date, SalePrice: tx.Price, CostBasis: costBasis.toFixed(2), Proceeds: proceeds.toFixed(2), GainLoss: gainLoss.toFixed(2), ShortTerm: st ? 'true' : '', Tax: gainLoss.gt(0) ? gainLoss.times(st ? .24 : .15).toFixed(2) : 0 } dispositions.push(disposition) } const consumeUtxos = (tx) => { for (let i = 0; i < utxos.length; i++) { let utxo = utxos[i] if (!utxo) { console.error(`WARNING: No utxo available! Assuming $0 cost basis:\n-Date:${tx.Date}\n-Asset: ${tx.Asset}\n-Sent: ${tx.Sent}\n-Remaining: ${tx.Remaining.toFixed(8)}\n`) utxo = { Date: '2017-01-01', Id: -1, Asset: tx.Asset, Amount: tx.Remaining.toFixed(8), Price: '0', Remaining: tx.Remaining, } } if (utxo.Asset !== tx.Asset || utxo.Remaining.isZero()) continue if (utxo.Remaining.gte(tx.Remaining)) { createDisposition(tx, utxo, tx.Remaining) utxo.Remaining = utxo.Remaining.minus(tx.Remaining) return } else { createDisposition(tx, utxo, utxo.Remaining) tx.Remaining = tx.Remaining.minus(utxo.Remaining) utxo.Remaining = new BN(0) return consumeUtxos(tx) } } } txs.forEach((tx, i) => { if (tx.Received) return handleBuy(tx, i) tx.Remaining = new BN(tx.Sent) return consumeUtxos(tx) }) let balances = utxos.reduce((prev, curr) => { const asset = curr.Asset if (prev[asset]) { prev[asset] = prev[asset].plus(curr.Remaining) } else { prev[asset] = curr.Remaining } return prev }, {}) utxos = utxos.map(u => ({ ...u, Remaining: u.Remaining.toFixed(8), })) balances = Object.keys(balances) .filter(asset => !balances[asset].isZero()) .map(asset => ({ Asset: asset, balance: balances[asset].toFixed(8) })) converter.json2csv(utxos).then(csv => fs.appendFileSync(`./utxos.csv`, csv) ) converter.json2csv(dispositions).then(csv => fs.appendFileSync(`./dispositions.csv`, csv) ) converter.json2csv(balances).then(csv => fs.appendFileSync(`./balances.csv`, csv) )