diff --git a/js/controllers/history.js b/js/controllers/history.js index af6bacbe1..82c387d12 100644 --- a/js/controllers/history.js +++ b/js/controllers/history.js @@ -27,76 +27,20 @@ angular.module('copayApp.controllers').controller('HistoryController', if (!w) return; $scope.generating = true; - w.getTransactionHistory(function(err, res) { - if (err) throw err; - if (!res) return; + w.getTransactionHistoryCsv(function(csvContent) { + if (csvContent && csvContent !== 'ERROR') { + var filename = "copay_history.csv"; - var unit = w.settings.unitName; - var data = res.items; - var filename = "copay_history.csv"; - var csvContent = "data:text/csv;charset=utf-8,"; - csvContent += "Date,Amount(" + unit + "),Action,AddressTo,Comment"; + var encodedUri = encodeURI(csvContent); + var link = document.createElement("a"); + link.setAttribute("href", encodedUri); + link.setAttribute("download", filename); - if (w.isShared()) { - csvContent += ",Signers\n"; - } else { - csvContent += "\n"; + link.click(); } - - data.forEach(function(it, index) { - var dataString = formatDate(it.minedTs || it.sentTs) + ',' + it.amount + ',' + it.action + ',' + formatString(it.addressTo) + ',' + formatString(it.comment); - if (it.actionList) { - dataString += ',' + formatSigners(it.actionList); - } - csvContent += index < data.length ? dataString + "\n" : dataString; - }); - - var encodedUri = encodeURI(csvContent); - var link = document.createElement("a"); - link.setAttribute("href", encodedUri); - link.setAttribute("download", filename); - - link.click(); $scope.generating = false; $scope.$digest(); - - function formatDate(date) { - var dateObj = new Date(date); - if (!dateObj) { - log.error('Error formating a date'); - return 'DateError' - } - if (!dateObj.toJSON()) { - return ''; - } - - return dateObj.toJSON().substring(0, 10); - } - - function formatString(str) { - if (!str) return ''; - - if (str.indexOf('"') !== -1) { - //replace all - str = str.replace(new RegExp('"', 'g'), '\''); - } - - //escaping commas - str = '\"' + str + '\"'; - - return str; - } - - function formatSigners(item) { - if (!item) return ''; - var str = ''; - item.forEach(function(it, index) { - str += index == 0 ? w.publicKeyRing.nicknameForCopayer(it.cId) : '|' + w.publicKeyRing.nicknameForCopayer(it.cId); - }); - return str; - } - }) }; diff --git a/js/models/Wallet.js b/js/models/Wallet.js index 1414ddf8f..010294bfc 100644 --- a/js/models/Wallet.js +++ b/js/models/Wallet.js @@ -1367,8 +1367,8 @@ Wallet.prototype.generateAddress = function(isChange) { return addr; }; + /** - * TODO: get this out of here * @desc get list of actions (see {@link getPendingTxProposals}) */ Wallet.prototype._getActionList = function(txp) { @@ -2543,6 +2543,87 @@ Wallet.prototype.isComplete = function() { return this.publicKeyRing.isComplete(); }; +/** + * @desc Return a list of transactions on CSV format + * @return {Object} the list of transactions on CSV format + */ +Wallet.prototype.getTransactionHistoryCsv = function(cb) { + var self = this; + self.getTransactionHistory(function(err, res) { + preconditions.checkState(res); + if (err) { + log.warn(err); + return cb(new Error('TXHISTORY: ' + err.toString())); + } + + var unit = self.settings.unitName; + var data = res.items; + + var csvContent = "data:text/csv;charset=utf-8,"; + csvContent += "Date,Amount(" + unit + "),Action,AddressTo,Comment"; + + if (self.isShared()) { + csvContent += ",Signers\n"; + } else { + csvContent += "\n"; + } + + data.forEach(function(it, index) { + if (!it) { + return cb(new Error('TXHISTORY: The item is null')); + } + var dataString = formatDate(it.minedTs || it.sentTs) + ',' + it.amount + ',' + it.action + ',' + formatString(it.addressTo) + ',' + formatString(it.comment); + if (self.isShared() && it.actionList) { + dataString += ',' + formatSigners(it.actionList); + } + csvContent += index < data.length ? dataString + "\n" : dataString; + }); + + + + return cb(csvContent); + + function formatDate(date) { + var dateObj = new Date(date); + if (!dateObj) { + log.warn('Error formating a date'); + return 'DateError' + } + if (!dateObj.toJSON()) { + return ''; + } + + return dateObj.toJSON().substring(0, 10); + } + + function formatString(str) { + if (!str) return ''; + + if (str.indexOf('"') !== -1) { + //replace all + str = str.replace(new RegExp('"', 'g'), '\''); + } + + //escaping commas + str = '\"' + str + '\"'; + + return str; + } + + function formatSigners(item) { + if (!item) return ''; + var str = ''; + item.forEach(function(it, index) { + str += index == 0 ? self.publicKeyRing.nicknameForCopayer(it.cId) : '|' + self.publicKeyRing.nicknameForCopayer(it.cId); + }); + return str; + } + + }); + +} + + /** * @desc Return a list of past transactions * @@ -2691,7 +2772,9 @@ Wallet.prototype.getTransactionHistory = function(opts, cb) { if (err) return cb(err); _.each(res.items, function(tx) { - decorateTx(tx); + if (tx) { + decorateTx(tx); + } }); return cb(null, paginate(res, opts.currentPage, opts.itemsPerPage)); diff --git a/test/Wallet.js b/test/Wallet.js index 91e14e739..74d5be787 100644 --- a/test/Wallet.js +++ b/test/Wallet.js @@ -2391,14 +2391,6 @@ describe('Wallet model', function() { items: txs, totalItems: txs.length, }); - w.getAddressesInfo = sinon.stub().returns([{ - addressStr: 'addr_in_1' - }, { - addressStr: 'addr_in_2' - }, { - addressStr: 'change', - isChange: true, - }]); w.addressBook = { 'addr_out_1': { @@ -2441,14 +2433,6 @@ describe('Wallet model', function() { items: txs, totalItems: txs.length, }); - w.getAddressesInfo = sinon.stub().returns([{ - addressStr: 'addr_in_1' - }, { - addressStr: 'addr_in_2' - }, { - addressStr: 'change', - isChange: true, - }]); w.txProposals.txps = [{ sentTxid: 'id0', @@ -2472,6 +2456,7 @@ describe('Wallet model', function() { }); }); + // TODO describe.skip('#onPayProPaymentAck', function() { it('should emit', function() { @@ -2484,6 +2469,76 @@ describe('Wallet model', function() { }); }); + describe('#getTransactionHistoryCsv', function() { + it('should return list of txs', function(done) { + var w = cachedCreateW2(); + var txs = [{ + vin: [{ + addr: 'in_1', + valueSat: 1000 + }], + vout: [{ + scriptPubKey: { + addresses: ['out_1'], + }, + value: '0.00000900', + }], + fees: 0.00000100 + }, { + vin: [{ + addr: 'in_2', + valueSat: 2000 + }], + vout: [{ + scriptPubKey: { + addresses: ['out_2'], + }, + value: '0.00001900', + }], + fees: 0.00000100 + }, { + vin: [{ + addr: 'in_3', + valueSat: 3000 + + }], + vout: [{ + scriptPubKey: { + addresses: ['out_3'], + }, + value: '0.00002900', + + }], + fees: 0.00000100 + }]; + + w.blockchain.getTransactions = sinon.stub().yields(null, { + items: txs, + totalItems: txs.length, + }); + + sinon.stub(w, 'getAddresses').returns(['in_1', 'in_2', 'in_3', 'out_1', 'out_2', 'out_3']); + var s = sinon.stub(w.publicKeyRing, 'addressIsOwn'); + s.withArgs('in_1').returns(true); + s.withArgs('out_1').returns(false); + + s.withArgs('in_2').returns(false); + s.withArgs('out_2').returns(true); + + s.withArgs('in_3').returns(true); + s.withArgs('out_3').returns(true); + + + w.getTransactionHistoryCsv(function(data) { + data.should.exist; + data.should.equal('data:text/csv;charset=utf-8,Date,Amount(bits),Action,AddressTo,Comment,Signers\n,9,sent,"out_1",\n,0,moved,"out_2",\n,29,sent,"out_3",\n'); + done(); + }); + }); + + }); + + describe.skip('#read', function() { var network, blockchain; diff --git a/views/history.html b/views/history.html index d438af1b9..eaa23f302 100644 --- a/views/history.html +++ b/views/history.html @@ -130,7 +130,7 @@
-
+
Generating file...