From 06ffa05ba273eafdabf5682e44f155b0ff7a7560 Mon Sep 17 00:00:00 2001 From: Chris Kleeschulte Date: Thu, 30 Mar 2017 15:24:08 -0400 Subject: [PATCH] Added code for tx list. --- lib/services/address/index.js | 21 +++++++-- lib/services/timestamp/index.js | 29 +++++++++++++ lib/services/wallet-api/index.js | 74 ++++++++++++++++++++++++-------- lib/services/wallet-api/utils.js | 6 +++ 4 files changed, 107 insertions(+), 23 deletions(-) diff --git a/lib/services/address/index.js b/lib/services/address/index.js index c513c0b5..593d07e4 100644 --- a/lib/services/address/index.js +++ b/lib/services/address/index.js @@ -1136,10 +1136,11 @@ AddressService.prototype.getAddressHistory = function(addresses, options, callba AddressService.prototype.getAddressTxids = function(address, options, callback) { var self = this; + var opts = options || { start: 0, end: 0xffffffff, txid: new Array(65).join('0') }; var txids = {}; - var start = self._encoding.encodeAddressIndexKey(address, options.start); - var end = self._encoding.encodeAddressIndexKey(address, options.end); + var start = self._encoding.encodeAddressIndexKey(address, opts.start, opts.txid); + var end = self._encoding.encodeAddressIndexKey(address, opts.end, opts.txid); var stream = self.store.createKeyStream({ gte: start, @@ -1147,17 +1148,25 @@ AddressService.prototype.getAddressTxids = function(address, options, callback) }); var streamErr = null; + stream.on('close', function() { +console.log('close'); + }); + stream.on('data', function(buffer) { + +console.log(buffer); var key = self._encoding.decodeAddressIndexKey(buffer); txids[key.txid] = true; }); stream.on('end', function() { +console.log(txids); callback(streamErr, Object.keys(txids)); }); stream.on('error', function(err) { +console.log(err); streamErr = err; }); }; @@ -1165,10 +1174,11 @@ AddressService.prototype.getAddressTxids = function(address, options, callback) AddressService.prototype.getAddressTxidsWithHeights = function(address, options, callback) { var self = this; + var opts = options || { start: 0, end: 0xffffffff, txid: new Array(65).join('0') }; var txids = {}; - var start = self._encoding.encodeAddressIndexKey(address, options.start); - var end = self._encoding.encodeAddressIndexKey(address, options.end); + var start = self._encoding.encodeAddressIndexKey(address, opts.start, opts.txid); + var end = self._encoding.encodeAddressIndexKey(address, opts.end, opts.txid); var stream = self.store.createKeyStream({ gte: start, @@ -1177,6 +1187,9 @@ AddressService.prototype.getAddressTxidsWithHeights = function(address, options, var streamErr = null; + stream.on('close', function(buffer) { + }); + stream.on('data', function(buffer) { var key = self._encoding.decodeAddressIndexKey(buffer); txids[key.txid] = key.height; diff --git a/lib/services/timestamp/index.js b/lib/services/timestamp/index.js index 05430ffb..c670a97c 100644 --- a/lib/services/timestamp/index.js +++ b/lib/services/timestamp/index.js @@ -106,4 +106,33 @@ TimestampService.prototype.getTimestamp = function(hash, callback) { }); }; +TimestampService.prototype.getBlockHeights = function(timestamps, callback) { + var self = this; + timestamps.sort(); + var stream = self.store.createReadStream({ + gte: self.encoding.encodeTimestampBlockKey(timestamps[0]), + lte: self.encoding.encodeTimestampBlockKey(timestamps[1]) + }); + + var hashes = []; + var streamErr = null; + + stream.on('data', function(data) { + hashes.push(self.encoding.decodeTimestampBlockValue(data.value)); + }); + + stream.on('error', function(err) { + streamErr = err; + }); + + stream.on('end', function() { + if (!streamErr && hashes.length > 1) { + var hashTuple = [ hashes[0], hashes[hashes.length - 1] ]; + return callback(null, hashTuple); + } + callback(streamErr); + }); + +}; + module.exports = TimestampService; diff --git a/lib/services/wallet-api/index.js b/lib/services/wallet-api/index.js index e9f19de7..b616cf13 100644 --- a/lib/services/wallet-api/index.js +++ b/lib/services/wallet-api/index.js @@ -9,8 +9,8 @@ var multer = require('multer'); var storage = multer.memoryStorage(); var upload = multer({ storage: storage }); var validators = require('./validators'); -var mainUtils = require('../../utils') -var utils = require('./utils') +var mainUtils = require('../../utils'); +var utils = require('./utils'); var _ = require('lodash'); var bodyParser = require('body-parser'); var LRU = require('lru-cache'); @@ -48,7 +48,8 @@ WalletService.dependencies = [ 'bitcoind', 'web', 'address', - 'transaction' + 'transaction', + 'timestamp' ]; WalletService.prototype.getAPIMethods = function() { @@ -585,19 +586,21 @@ WalletService.prototype._endpointGetTransactions = function() { return function(req, res) { req.setTimeout(600000); var walletId = req.params.walletId; - var options = { - start: req.query.start, - end : req.query.end, - from: req.query.from, - to: req.query.to - }; - self._getTransactions(walletId, options, function(err, transactions, totalCount) { - if(err) { - return utils.sendError(err, res); - } - res.status(200).jsonp({ - transactions: transactions, - totalCount: totalCount + self._processStartEndOptions(req, function(err, heights) { + var options = { + start: heights[0], + end : heights[1], + from: req.query.from, + to: req.query.to + }; + self._getTransactions(walletId, options, function(err, transactions, totalCount) { + if(err) { + return utils.sendError(err, res); + } + res.status(200).jsonp({ + transactions: transactions, + totalCount: totalCount + }); }); }); }; @@ -734,6 +737,10 @@ WalletService.prototype._getTransactions = function(walletId, options, callback) }); var streamErr; + stream.on('close', function() { + finish(txids); + }); + stream.on('error', function(err) { streamErr = err; }); @@ -993,15 +1000,13 @@ WalletService.prototype._getUTXOIndexOperations = function(walletId, addresses, WalletService.prototype._getTxidIndexOperations = function(walletId, addresses, jobId, callback) { var self = this; - var txids = {}; async.eachLimit(addresses, 10, function(address, next) { - self.node.services.address.getAddressTxidsWithHeights(address, {}, function(err, tmpTxids) { + self.node.services.address.getAddressTxidsWithHeights(address, null, function(err, tmpTxids) { if(err) { return next(err); } - txids = _.merge(txids, tmpTxids); return next(); }); @@ -1034,6 +1039,37 @@ WalletService.prototype._storeBalance = function(walletId, balance, callback) { this.store.put(key, value, callback); }; +WalletService.prototype._processStartEndOptions = function(req, callback) { + var self = this; + var heights = []; + if (!(req.query.start && req.query.start < (500 * 1E6))) { + var times = []; + var heights = []; + times.push(utils.normalizeTimeStamp(req.query.start)); + times.push(utils.normalizeTimeStamp(req.query.end)); + self.node.services.timestamp.getBlockHeights(times, function(err, hashTuple) { + hashTuple.forEach(function(hash) { + self.node.services.bitcoind._tryAllClients(function(client, done) { + client.getBlock(hash, function(err, response) { + if (err) { + return callback(err); + } + done(null, heights.push(response.result.height)); + }); + }, function(err, obj) { + if (heights.length > 1) { + callback(null, heights); + } + }); + }); + }); + } else { + setImmediate(function() { + callback(null, [req.query.start, req.query.end]); + }); + } +}; + WalletService.prototype._endpointJobs = function() { var self = this; diff --git a/lib/services/wallet-api/utils.js b/lib/services/wallet-api/utils.js index 3c944724..02c66eaa 100644 --- a/lib/services/wallet-api/utils.js +++ b/lib/services/wallet-api/utils.js @@ -23,6 +23,12 @@ exports.isInteger = function(value) { Math.floor(value) === value; }; +exports.normalizeTimeStamp = function(value) { + if (value > 0xffffffff) { + value = Math.round(value/1000); + } + return value; +}; /** * Will create a directory if it does not already exist. *