Added gettransactions.

This commit is contained in:
Chris Kleeschulte 2017-02-01 13:14:54 -05:00
parent 7862481df5
commit 1ccf4e9741

View File

@ -5,11 +5,6 @@ var BaseService = require('../../service');
var inherits = require('util').inherits;
var index = require('../../');
var log = index.log;
var errors = index.errors;
var bitcore = require('bitcore-lib');
var Networks = bitcore.Networks;
var levelup = require('levelup');
var leveldown = require('leveldown');
var multer = require('multer');
var storage = multer.memoryStorage();
var upload = multer({ storage: storage });
@ -20,13 +15,12 @@ var bodyParser = require('body-parser');
var LRU = require('lru-cache');
var Encoding = require('../../encoding'); // TODO this needs to be split out by service
var WalletService = function(options) {
BaseService.call(this, options);
this._cache = LRU({
max: 500 * 1024 * 1024,
length: function(n, key) {
length: function(n) {
return Buffer.byteLength(n, 'utf8');
},
maxAge: 30 * 60 * 1000
@ -210,7 +204,6 @@ WalletService.prototype.concurrentBlockHandler = function(block, connectBlock, c
var self = this;
var txs = block.transactions;
var height = block.__height;
var action = 'put';
if (!connectBlock) {
@ -247,7 +240,7 @@ WalletService.prototype.concurrentBlockHandler = function(block, connectBlock, c
type: action,
key: self._encoding.encodeWalletTransactionKey(walletId, block.__height),
value: self._encoding.encodeWalletTransactionValue(tx.id)
})
});
});
}
@ -270,9 +263,9 @@ WalletService.prototype.concurrentBlockHandler = function(block, connectBlock, c
continue;
}
var walletIds = self._addressMap[inputAddress];
var inputWalletIds = self._addressMap[inputAddress];
walletIds.forEach(function(walletId) {
inputWalletIds.forEach(function(walletId) {
operations.push({
type: action,
key: self._encoding.encodeWalletTransactionKey(walletId, block.__height),
@ -433,8 +426,12 @@ WalletService.prototype._endpointPostAddresses = function() {
var self = this;
return function(req, res) {
var addresses = req.addresses;
if (!addresses || !addresses.length) {
return utils.sendError(new Error('addresses are required when creating a wallet.'));
}
var walletId = utils.getWalletId();
// TODO make imdempotent
self._importAddresses(walletId, addresses, function(err) {
if(err) {
return utils.sendError(err, res);
@ -492,6 +489,7 @@ WalletService.prototype._endpointPutAddresses = function() {
var addAddresses = _.without(newAddresses, oldAddresses);
var amountAdded = addAddresses.length;
//TODO this may take too long
self._importAddresses(walletId, addAddresses, function(err) {
if(err) {
return utils.sendError(err, res);
@ -565,54 +563,90 @@ WalletService.prototype._chunkAdresses = function(addresses) {
WalletService.prototype._getTransactions = function(walletId, options, callback) {
var self = this;
var transactions = [];
var txids = [];
var opts = {
start: options.start,
end: options.end
start: options.start || 0,
end: options.end || Math.pow(2, 32) - 1
};
var key = walletId + opts.start + opts.end;
function finish(transactions) {
var from = options.from || 0;
var to = options.to || transactions.length;
callback(null, transactions.slice(from, to), transactions.length);
}
if (!self._cache.peek(key)) {
self._getAddresses(walletId, function(err, addresses) {
if(err) {
return callback(err);
}
if (!addresses) {
return callback(new Error('wallet not found'));
}
var addressGroups = self._chunkAdresses(addresses);
async.eachSeries(addressGroups, function(addresses, next) {
self.node.services.bitcoind.getAddressHistory(addresses, opts, function(err, history) {
if(err) {
return next(err);
}
var groupTransactions = history.items.map(function(item) {
return item.tx;
});
transactions = _.union(transactions, groupTransactions);
next();
});
}, function(err) {
var stream = self.store.createReadStream({
gte: self._encoding.encodeWalletTransactionKey(walletId, opts.start),
lt: self._encoding.encodeWalletTransactionKey(walletId, opts.end)
});
var streamErr;
stream.on('error', function(err) {
streamErr = err;
});
stream.on('data', function(data) {
txids.push(self._encoding.decodeWalletTransactionValue(data.value));
});
stream.on('end', function() {
async.mapLimit(txids, function(txid, next) {
self.node.services.transaction.getTransaction(txid, options, next);
}, function(err, transactions) {
if(err) {
return callback(err);
}
self._cache.set(key, JSON.stringify(transactions));
finish();
finish(transactions);
});
});
} else {
try {
transactions = JSON.parse(self._cache.get(key));
finish();
finish(transactions);
} catch(e) {
self._cache.del(key);
return callback(e);
}
}
function finish() {
var from = options.from || 0;
var to = options.to || transactions.length;
callback(null, transactions.slice(from, to), transactions.length);
}
//if (!self._cache.peek(key)) {
// self._getAddresses(walletId, function(err, addresses) {
// if(err) {
// return callback(err);
// }
// if (!addresses) {
// return callback(new Error('wallet not found'));
// }
// var addressGroups = self._chunkAdresses(addresses);
// async.eachSeries(addressGroups, function(addresses, next) {
// self.node.services.bitcoind.getAddressHistory(addresses, opts, function(err, history) {
// if(err) {
// return next(err);
// }
// var groupTransactions = history.items.map(function(item) {
// return item.tx;
// });
// transactions = _.union(transactions, groupTransactions);
// next();
// });
// }, function(err) {
// if(err) {
// return callback(err);
// }
// self._cache.set(key, JSON.stringify(transactions));
// finish();
// });
// });
//} else {
// try {
// transactions = JSON.parse(self._cache.get(key));
// finish();
// } catch(e) {
// self._cache.del(key);
// return callback(e);
// }
//}
};
WalletService.prototype._getAddresses = function(walletId, callback) {
@ -738,7 +772,7 @@ WalletService.prototype._getTxidIndexOperations = function(walletId, addresses,
return callback(err);
}
operations = Object.keys(txids).map(function(txid) {
var operations = Object.keys(txids).map(function(txid) {
return {
type: 'put',
key: self._encoding.encodeWalletTransactionKey(walletId, txids[txid]),
@ -767,7 +801,8 @@ WalletService.prototype._endpointGetInfo = function() {
res.jsonp({result: 'ok'});
};
};
WalletService.prototype.setupRoutes = function(app, express) {
WalletService.prototype.setupRoutes = function(app) {
var s = this;
var v = validators;