From 3b83dc095f5efdeb7504f500c3355034fcb72f8b Mon Sep 17 00:00:00 2001 From: Ivan Socolsky Date: Sun, 22 Feb 2015 23:26:21 -0300 Subject: [PATCH] bit-history --- bit-wallet/bit | 1 + bit-wallet/bit-history | 38 ++++++++++++++++++++++++++++++++++++++ lib/client/api.js | 9 ++++----- lib/expressapp.js | 1 + lib/server.js | 27 ++++++++++++++++++++++----- package.json | 1 + 6 files changed, 67 insertions(+), 10 deletions(-) create mode 100755 bit-wallet/bit-history diff --git a/bit-wallet/bit b/bit-wallet/bit index fbd840b..c4607a6 100755 --- a/bit-wallet/bit +++ b/bit-wallet/bit @@ -15,6 +15,7 @@ program .command('reject [reason]', 'reject a transaction proposal') .command('broadcast ', 'broadcast a transaction proposal to the Bitcoin network') .command('rm ', 'remove a transaction proposal') + .command('history', 'list of past incoming and outgoing transactions') .command('export', 'export wallet critical data') .command('import', 'import wallet critical data') .command('confirm', 'show copayer\'s data for confirmation') diff --git a/bit-wallet/bit-history b/bit-wallet/bit-history new file mode 100755 index 0000000..b00c101 --- /dev/null +++ b/bit-wallet/bit-history @@ -0,0 +1,38 @@ +#!/usr/bin/env node + +var _ = require('lodash'); +var fs = require('fs'); +var moment = require('moment'); +var program = require('commander'); +var Utils = require('./cli-utils'); +program = Utils.configureCommander(program); + +program + .parse(process.argv); + +var args = program.args; +var client = Utils.getClient(program); + +var txData; + +client.getTxHistory({}, function (err, txs) { + if (_.isEmpty(txs)) + return; + + console.log("* TX History:") + + _.each(txs, function(tx) { + var time = moment().fromNow(tx.time); + switch (tx.action) { + case 'received': + console.log("\t%s: <= %s", time, Utils.renderAmount(tx.amount)); + break; + case 'sent': + console.log("\t%s: %s => %s", time, Utils.renderAmount(tx.amount), tx.addressTo); + break; + case 'moved': + console.log("\t%s: == %s", time, Utils.renderAmount(tx.amount)); + break; + } + }); +}); diff --git a/lib/client/api.js b/lib/client/api.js index 5d1b14a..2ddc878 100644 --- a/lib/client/api.js +++ b/lib/client/api.js @@ -36,6 +36,7 @@ function _decryptMessage(message, encryptingKey) { }; function _processTxps(txps, encryptingKey) { + if (!txps) return; _.each([].concat(txps), function(txp) { txp.encryptedMessage = txp.message; txp.message = _decryptMessage(txp.message, encryptingKey); @@ -482,10 +483,6 @@ API.prototype.getMainAddresses = function(opts, cb) { }); }; -API.prototype.history = function(limit, cb) { - -}; - API.prototype.getBalance = function(cb) { var self = this; @@ -591,8 +588,10 @@ API.prototype.parseTxProposals = function(txData, cb) { }, function(err, wcd) { if (err) return cb(err); + << << << < HEAD var txps = txData.txps; - _processTxps(txps, wcd.sharedEncryptingKey); + _processTxps(txps, wcd.sharedEncryptingKey); === === = + _processTxps(txps, data.sharedEncryptingKey); >>> >>> > bit - history var fake = _.any(txps, function(txp) { return (!Verifier.checkTxProposal(wcd, txp)); diff --git a/lib/expressapp.js b/lib/expressapp.js index 6e88da0..24458ce 100644 --- a/lib/expressapp.js +++ b/lib/expressapp.js @@ -268,6 +268,7 @@ ExpressApp.start = function(opts) { server.getTxHistory({}, function(err, txs) { if (err) return returnError(err, res, req); res.json(txs); + res.end(); }); }); }); diff --git a/lib/server.js b/lib/server.js index e211872..f0a2619 100644 --- a/lib/server.js +++ b/lib/server.js @@ -80,8 +80,7 @@ WalletService.getInstanceWithAuth = function(opts, cb) { if (!copayer) return cb(new ClientError('NOTAUTHORIZED', 'Copayer not found')); var pubKey = opts.readOnly ? copayer.roPubKey : copayer.rwPubKey; - var isValid = server._verifySignature(opts.message, opts.signature, - pubKey); + var isValid = server._verifySignature(opts.message, opts.signature, pubKey); if (!isValid) return cb(new ClientError('NOTAUTHORIZED', 'Invalid signature')); @@ -324,6 +323,20 @@ WalletService.prototype.verifyMessageSignature = function(opts, cb) { WalletService.prototype._getBlockExplorer = function(provider, network) { var url; + function getTransactionsInsight(url, addresses, cb) { + var request = require('request'); + request({ + method: "POST", + url: url + '/api/addrs/txs', + json: { + addrs: [].concat(addresses).join(',') + } + }, function(err, res, body) { + if (err || res.statusCode != 200) return cb(err || res); + return cb(null, body); + }); + }; + if (this.blockExplorer) return this.blockExplorer; @@ -339,7 +352,9 @@ WalletService.prototype._getBlockExplorer = function(provider, network) { url = 'https://test-insight.bitpay.com:443' break; } - return new Explorers.Insight(url, network); + var bc = new Explorers.Insight(url, network); + bc.getTransactions = _.bind(getTransactionsInsight, bc, url); + return bc; break; } }; @@ -874,7 +889,7 @@ WalletService.prototype._normalizeTxHistory = function(txs) { txid: tx.txid, confirmations: tx.confirmations, fees: parseInt((tx.fees * 1e8).toFixed(0)), - minedTs: !_.isNaN(tx.time) ? tx.time * 1000 : undefined, + time: !_.isNaN(tx.time) ? tx.time : Math.floor(Date.now() / 1000), inputs: inputs, outputs: outputs, }; @@ -937,7 +952,9 @@ WalletService.prototype.getTxHistory = function(opts, cb) { var proposal = indexedProposals[tx.txid]; if (proposal) { tx.message = proposal.message; - tx.actions = proposal.actions; + tx.actions = _.map(proposal.actions, function(action) { + return _.pick(action, ['createdOn', 'type', 'copayerId', 'copayerName', 'comment']); + }); // tx.sentTs = proposal.sentTs; // tx.merchant = proposal.merchant; //tx.paymentAckMemo = proposal.paymentAckMemo; diff --git a/package.json b/package.json index 7671316..4f5841e 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "levelup": "^0.19.0", "lodash": "*", "mocha-lcov-reporter": "0.0.1", + "moment": "^2.9.0", "morgan": "*", "npmlog": "^0.1.1", "preconditions": "^1.0.7",