Fixed mempool gathering.
This commit is contained in:
parent
fba71ee1aa
commit
5007104a4f
@ -11,7 +11,6 @@ var _ = bitcore.deps._;
|
||||
var Encoding = require('./encoding');
|
||||
var Transform = require('stream').Transform;
|
||||
var assert = require('assert');
|
||||
var Stream = require('stream');
|
||||
var utils = require('../../utils');
|
||||
|
||||
var AddressService = function(options) {
|
||||
@ -373,17 +372,34 @@ AddressService.prototype._getAddressHistory = function(address, options, callbac
|
||||
|
||||
async.waterfall([
|
||||
|
||||
// query the mempool for relevant txs for this address
|
||||
function(next) {
|
||||
|
||||
if (!options.queryMempool) {
|
||||
return next();
|
||||
return next(null, []);
|
||||
}
|
||||
|
||||
self._mempool.getTxidsByAddress(address, next);
|
||||
self._mempool.getTxsByAddress(address, next);
|
||||
},
|
||||
|
||||
// add the meta data such as input values, etc.
|
||||
function(mempoolTxs, next) {
|
||||
|
||||
if (mempoolTxs.length <= 0) {
|
||||
return next();
|
||||
}
|
||||
async.mapSeries(mempoolTxs, function(tx, next) {
|
||||
self._transaction.setTxMetaInfo(tx, options, next);
|
||||
}, function(err, txs) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
options.results = txs;
|
||||
next();
|
||||
});
|
||||
},
|
||||
// stream the rest of the confirmed txids out of the address index
|
||||
function(mempoolTxids, next) {
|
||||
function(next) {
|
||||
|
||||
var txStream = self._getTxStream(address, options);
|
||||
|
||||
@ -395,20 +411,6 @@ AddressService.prototype._getAddressHistory = function(address, options, callbac
|
||||
log.error('Address Service: txstream err: ' + err);
|
||||
txStream.unpipe();
|
||||
});
|
||||
|
||||
if (mempoolTxids.length > 0) {
|
||||
|
||||
var mempoolTxidStream = new Stream.Readable({ objectMode: true });
|
||||
|
||||
mempoolTxidStream.pipe(txStream);
|
||||
|
||||
mempoolTxids.forEach(function(txid) {
|
||||
mempoolTxidStream.push(txid);
|
||||
});
|
||||
|
||||
mempoolTxidStream.push(null);
|
||||
}
|
||||
|
||||
var txidStream = self._getTxidStream(address, options);
|
||||
txidStream.pipe(txStream);
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ MempoolService.prototype.getMempoolTransaction = function(txid, callback) {
|
||||
};
|
||||
|
||||
// TODO optimize this using another index?
|
||||
MempoolService.prototype.getTxidsByAddress = function(address, callback) {
|
||||
MempoolService.prototype.getTxsByAddress = function(address, callback) {
|
||||
|
||||
var self = this;
|
||||
var results = [];
|
||||
@ -162,9 +162,9 @@ MempoolService.prototype.getTxidsByAddress = function(address, callback) {
|
||||
|
||||
stream.on('data', function(data) {
|
||||
var tx = self._encoding.decodeMempoolTransactionValue(data.value);
|
||||
var txid = self._involvesAddress(tx, address);
|
||||
if (txid) {
|
||||
results.push(txid);
|
||||
tx = self._involvesAddress(tx, address);
|
||||
if (tx) {
|
||||
results.push(tx);
|
||||
}
|
||||
});
|
||||
|
||||
@ -193,7 +193,7 @@ MempoolService.prototype._involvesAddress = function(tx, address) {
|
||||
for(var i = 0; i < collections.length; i++) {
|
||||
var hasAddress = contains(collections[i], this._network);
|
||||
if (hasAddress) {
|
||||
return tx.txid();
|
||||
return tx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,8 @@ TransactionService.prototype.getAPIMethods = function() {
|
||||
return [
|
||||
['getRawTransaction', this, this.getRawTransaction, 1],
|
||||
['getTransaction', this, this.getTransaction, 1],
|
||||
['getDetailedTransaction', this, this.getDetailedTransaction, 1]
|
||||
['getDetailedTransaction', this, this.getDetailedTransaction, 1],
|
||||
['setTxMetaInfo', this, this.setTxMetaInfo, 2]
|
||||
];
|
||||
};
|
||||
|
||||
@ -119,7 +120,7 @@ TransactionService.prototype.getTransaction = function(txid, options, callback)
|
||||
self._getTransaction.bind(self, txid, options),
|
||||
self._getSupplementaryTransactionInfo.bind(self),
|
||||
self._getMempoolTransaction.bind(self),
|
||||
self._setMetaInfo.bind(self)
|
||||
self.setTxMetaInfo.bind(self)
|
||||
], callback);
|
||||
|
||||
};
|
||||
@ -151,42 +152,75 @@ TransactionService.prototype._getSupplementaryTransactionInfo = function(txid, t
|
||||
});
|
||||
};
|
||||
|
||||
TransactionService.prototype._setMetaInfo = function(tx, options, callback) {
|
||||
TransactionService.prototype.setTxMetaInfo = function(tx, options, callback) {
|
||||
|
||||
var self = this;
|
||||
|
||||
if (!tx) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
|
||||
// output values
|
||||
var outputSatoshis = 0;
|
||||
|
||||
tx.outputs.forEach(function(output) {
|
||||
outputSatoshis += output.value;
|
||||
});
|
||||
|
||||
tx.outputSatoshis = outputSatoshis;
|
||||
|
||||
|
||||
//input values
|
||||
if (!tx.inputs[0].isCoinbase()) {
|
||||
|
||||
var inputSatoshis = 0;
|
||||
|
||||
tx.__inputValues.forEach(function(val) {
|
||||
|
||||
if (val >+ 0) {
|
||||
inputSatoshis += val;
|
||||
async.waterfall([
|
||||
function(next) {
|
||||
if (tx.__inputValues) {
|
||||
return next(null, tx);
|
||||
}
|
||||
});
|
||||
// the tx's that contain these input values could, themselves be unconfirmed
|
||||
// we are also assuming that this tx is from thet mempool
|
||||
self._getInputValues(tx, options, function(err, inputValues) {
|
||||
|
||||
var feeSatoshis = inputSatoshis - outputSatoshis;
|
||||
tx.inputSatoshis = inputSatoshis;
|
||||
tx.feeSatoshis = feeSatoshis;
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
}
|
||||
tx.__inputValues = inputValues;
|
||||
tx.confirmations = 0;
|
||||
tx.blockHash = null;
|
||||
tx.__blockHash = null;
|
||||
next(null, tx);
|
||||
|
||||
callback(null, tx);
|
||||
});
|
||||
},
|
||||
function(tx, next) {
|
||||
|
||||
// output values
|
||||
var outputSatoshis = 0;
|
||||
|
||||
tx.outputs.forEach(function(output) {
|
||||
outputSatoshis += output.value;
|
||||
});
|
||||
|
||||
tx.outputSatoshis = outputSatoshis;
|
||||
|
||||
//input values
|
||||
if (!tx.inputs[0].isCoinbase()) {
|
||||
|
||||
var inputSatoshis = 0;
|
||||
|
||||
assert(tx.__inputValues.length === tx.inputs.length,
|
||||
'Transaction Service: input values length is not the same as the number of inputs.');
|
||||
|
||||
tx.__inputValues.forEach(function(val) {
|
||||
|
||||
if (val >+ 0) {
|
||||
inputSatoshis += val;
|
||||
}
|
||||
});
|
||||
|
||||
var feeSatoshis = inputSatoshis - outputSatoshis;
|
||||
tx.inputSatoshis = inputSatoshis;
|
||||
tx.feeSatoshis = feeSatoshis;
|
||||
|
||||
}
|
||||
|
||||
next(null, tx);
|
||||
}
|
||||
], function(err, tx) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, tx);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
@ -209,21 +243,7 @@ TransactionService.prototype._getMempoolTransaction = function(txid, tx, options
|
||||
return callback(null, tx, options);
|
||||
}
|
||||
|
||||
// the tx's that contain these input values could, themselves be unconfirmed
|
||||
self._getInputValues(tx, options, function(err, inputValues) {
|
||||
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
tx.__inputValues = inputValues;
|
||||
tx.confirmations = 0;
|
||||
tx.blockHash = null;
|
||||
tx.__blockHash = null;
|
||||
callback(null, tx, options);
|
||||
|
||||
});
|
||||
|
||||
callback(null, tx, options);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
18
package-lock.json
generated
18
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bitcore-node",
|
||||
"version": "5.0.0-beta.15",
|
||||
"version": "5.0.0-beta.16",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -4266,14 +4266,6 @@
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
|
||||
"integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4="
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"string-length": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz",
|
||||
@ -4293,6 +4285,14 @@
|
||||
"strip-ansi": "3.0.1"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.1"
|
||||
}
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"author": "BitPay <dev@bitpay.com>",
|
||||
"version": "5.0.0-beta.15",
|
||||
"version": "5.0.0-beta.16",
|
||||
"main": "./index.js",
|
||||
"repository": "git://github.com/bitpay/bitcore-node.git",
|
||||
"homepage": "https://github.com/bitpay/bitcore-node",
|
||||
|
||||
@ -81,8 +81,8 @@ describe('Address Service', function() {
|
||||
|
||||
var getHeaderHash = sandbox.stub().callsArgWith(1, null, 'aa');
|
||||
var getBlockHeader = sandbox.stub().callsArgWith(1, null, 'aa');
|
||||
var getTxidsByAddress = sandbox.stub().callsArgWith(1, null, []);
|
||||
addressService._mempool = { getTxidsByAddress: getTxidsByAddress };
|
||||
var getTxsByAddress = sandbox.stub().callsArgWith(1, null, []);
|
||||
addressService._mempool = { getTxsByAddress: getTxsByAddress };
|
||||
|
||||
addressService._header = {
|
||||
getHeaderHash: getHeaderHash,
|
||||
@ -108,7 +108,7 @@ describe('Address Service', function() {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
expect(getTxidsByAddress.calledOnce).to.be.true;
|
||||
expect(getTxsByAddress.calledOnce).to.be.true;
|
||||
expect(getTransaction.calledOnce).to.be.true;
|
||||
expect(res).to.deep.equal([
|
||||
{
|
||||
|
||||
@ -111,4 +111,21 @@ describe('Transaction Service', function() {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setMetaTxInfo', function() {
|
||||
it('should set the appropriate meta data on a tx.', function(done) {
|
||||
sandbox.stub(txService, '_getInputValues').callsArgWith(2, null, [2]);
|
||||
var tx = { outputs: [ { value: 1 } ], inputs: [ { value: 2, isCoinbase: sinon.stub().returns(false) } ] };
|
||||
|
||||
txService.setTxMetaInfo(tx, {}, function(err, _tx) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
_tx.__inputValues.should.deep.equal([2]);
|
||||
_tx.confirmations.should.equal(0);
|
||||
_tx.inputSatoshis.should.equal(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user