diff --git a/js/controllers/history.js b/js/controllers/history.js index 34fba24a4..d2ce29f93 100644 --- a/js/controllers/history.js +++ b/js/controllers/history.js @@ -27,89 +27,13 @@ angular.module('copayApp.controllers').controller('HistoryController', if (!w) return; $scope.generating = true; - w.getTransactionHistory(function(err, res) { - if (err) { - $scope.generating = false; - throw err; - } - if (!res) { - $scope.generating = false; - return; - } + //getTransactionHistoryCSV - 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"; - - if (w.isShared()) { - csvContent += ",Signers\n"; - } else { - csvContent += "\n"; - } - - data.forEach(function(it, index) { - if (!it) { - console.log('Error on tx with index ', index); - return; - } else { - console.log('Txid with index ', it.txid, 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(); + w.getTransactionHistoryCsv(function() { $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; - } - }) }; @@ -147,11 +71,17 @@ angular.module('copayApp.controllers').controller('HistoryController', } var items = res.items; +<<<<<<< HEAD var now = new Date(); _.each(items, function(tx) { tx.ts = tx.minedTs || tx.sentTs; tx.rateTs = Math.floor((tx.ts || now) / 1000); tx.amount = $filter('noFractionNumber')(tx.amount); +======= + + _.each(items, function(r, index) { + r.ts = r.minedTs || r.sentTs; +>>>>>>> Move function getTransactionHistoryCsv to wallet }); var index = _.indexBy(items, 'rateTs'); diff --git a/js/models/Wallet.js b/js/models/Wallet.js index a4d604ff4..3d25c3101 100644 --- a/js/models/Wallet.js +++ b/js/models/Wallet.js @@ -2567,6 +2567,207 @@ Wallet.prototype.isComplete = function() { return this.publicKeyRing.isComplete(); }; +/** + * @desc Sign a JSON + * + * @TODO: THIS WON'T WORK ALLWAYS! JSON.stringify doesn't warants an order + * @param {Object} payload - the payload to verify + * @return {string} base64 encoded string + */ +Wallet.prototype.signJson = function(payload) { + var key = new bitcore.Key(); + key.private = new Buffer(this.getMyCopayerIdPriv(), 'hex'); + key.regenerateSync(); + var sign = bitcore.Message.sign(JSON.stringify(payload), key); + return sign.toString('hex'); +} + +/** + * @desc Verify that a JSON object is correctly signed + * + * @TODO: THIS WON'T WORK ALLWAYS! JSON.stringify doesn't warants an order + * + * @param {string} senderId - a sender's public key, hex encoded + * @param {Object} payload - the object to verify + * @param {string} signature - a sender's public key, hex encoded + * @return {boolean} + */ +Wallet.prototype.verifySignedJson = function(senderId, payload, signature) { + var pubkey = new Buffer(senderId, 'hex'); + var sign = new Buffer(signature, 'hex'); + var v = bitcore.Message.verifyWithPubKey(pubkey, JSON.stringify(payload), sign); + return v; +} + +/** + * @desc Create a HTTP request + * @TODO: This shouldn't be a wallet responsibility + */ +Wallet.request = function(options, callback) { + if (_.isString(options)) { + options = { + uri: options + }; + } + + options.method = options.method || 'GET'; + options.headers = options.headers || {}; + + var ret = { + success: function(cb) { + this._success = cb; + return this; + }, + error: function(cb) { + this._error = cb; + return this; + }, + _success: function() {; + }, + _error: function(_, err) { + throw err; + } + }; + + var method = (options.method || 'GET').toUpperCase(); + var uri = options.uri || options.url; + var req = options; + + req.headers = req.headers || {}; + req.body = req.body || req.data || {}; + + var xhr = new XMLHttpRequest(); + xhr.open(method, uri, true); + + Object.keys(req.headers).forEach(function(key) { + var val = req.headers[key]; + if (key === 'Content-Length') return; + if (key === 'Content-Transfer-Encoding') return; + xhr.setRequestHeader(key, val); + }); + + if (req.responseType) { + xhr.responseType = req.responseType; + } + + xhr.onload = function(event) { + var response = xhr.response; + var buf = new Uint8Array(response); + var headers = {}; + (xhr.getAllResponseHeaders() || '').replace( + /(?:\r?\n|^)([^:\r\n]+): *([^\r\n]+)/g, + function($0, $1, $2) { + headers[$1.toLowerCase()] = $2; + } + ); + return ret._success(buf, xhr.status, headers, options); + }; + + xhr.onerror = function(event) { + var status; + if (xhr.status === 0 || !xhr.statusText) { + status = 'HTTP Request Error: This endpoint likely does not support cross-origin requests.'; + } else { + status = xhr.statusText; + } + return ret._error(null, status, null, options); + }; + + if (req.body) { + xhr.send(req.body); + } else { + xhr.send(null); + } + + return ret; +}; + + + +Wallet.prototype.getTransactionHistoryCsv = function(cb) { + var self = this; + self.getTransactionHistory(function(err, res) { + if (err) { + return cb(err); + } + + if (!res) { + return cb('Error'); + } + + var unit = self.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"; + + if (self.isShared()) { + csvContent += ",Signers\n"; + } else { + csvContent += "\n"; + } + + data.forEach(function(it, index) { + if (!it) { + return cb('Error'); + } + 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; + }); + + var encodedUri = encodeURI(csvContent); + var link = document.createElement("a"); + link.setAttribute("href", encodedUri); + link.setAttribute("download", filename); + + link.click(); + + return cb(null); + + 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 ? self.publicKeyRing.nicknameForCopayer(it.cId) : '|' + self.publicKeyRing.nicknameForCopayer(it.cId); + }); + return str; + } + + }); + +} + + /** * @desc Return a list of past transactions * @@ -2592,7 +2793,6 @@ Wallet.prototype.getTransactionHistory = function(opts, cb) { function extractInsOuts(tx) { // Inputs - console.log('extractInsOuts'); var inputs = _.map(tx.vin, function(item) { return { type: 'in', @@ -2715,7 +2915,6 @@ Wallet.prototype.getTransactionHistory = function(opts, cb) { self.blockchain.getTransactions(addresses, from, to, function(err, res) { if (err) return cb(err); - console.log(res.items); _.each(res.items, function(tx) { if (tx) { decorateTx(tx);