diff --git a/lib/services/address/index.js b/lib/services/address/index.js index d4f49011..4332657d 100644 --- a/lib/services/address/index.js +++ b/lib/services/address/index.js @@ -203,43 +203,101 @@ AddressService.prototype.getAddressUnspentOutputs = function(address, options, c lt: end }; - var utxoStream = self._db.createReadStream(criteria); + async.waterfall([ - var streamErr; + // query the mempool if necessary + function(next) { - utxoStream.on('end', function() { + if (!options.queryMempool) { + return next(null, []); + } - if (streamErr) { - return callback(streamErr); + self._mempool.getTxsByAddress(address, next); + }, + + // if mempool utxos, then add them first + function(mempoolTxs, next) { + + if (mempoolTxs.length <= 0) { + return next(); + } + + mempoolTxs.forEach(function(tx) { + results = results.concat(self._getMempoolUtxos(tx, address)); + }); + + next(); + + }, + + function(next) { + + var utxoStream = self._db.createReadStream(criteria); + var streamErr; + + utxoStream.on('end', function() { + + if (streamErr) { + return callback(streamErr); + } + + results = utils.orderByConfirmations(results); + next(null, results); + + }); + + utxoStream.on('error', function(err) { + streamErr = err; + }); + + utxoStream.on('data', function(data) { + + var key = self._encoding.decodeUtxoIndexKey(data.key); + var value = self._encoding.decodeUtxoIndexValue(data.value); + + results.push({ + address: address, + txid: key.txid, + vout: key.outputIndex, + ts: value.timestamp, + scriptPubKey: value.script.toString('hex'), + amount: Unit.fromSatoshis(value.satoshis).toBTC(), + height: value.height, + satoshis: value.satoshis, + confirmationsFromCache: true + }); + + }); } + ], callback); - callback(null, results); +}; - }); +AddressService.prototype._getMempoolUtxos = function(tx, address) { - utxoStream.on('error', function(err) { - streamErr = err; - }); + var results = []; - utxoStream.on('data', function(data) { + for(var i = 0; i < tx.outputs.length; i++) { - var key = self._encoding.decodeUtxoIndexKey(data.key); - var value = self._encoding.decodeUtxoIndexValue(data.value); + var output = tx.outputs[i]; + + if (utils.getAddress(output, this._network) !== address) { + continue; + } results.push({ address: address, - txid: key.txid, - vout: key.outputIndex, - ts: value.timestamp, - scriptPubKey: value.script.toString('hex'), - amount: Unit.fromSatoshis(value.satoshis).toBTC(), - height: value.height, - satoshis: value.satoshis, - confirmationsFromCache: true + txid: tx.txid(), + vout: i, + scriptPubKey: output.script.toRaw().toString('hex'), + amount: Unit.fromSatoshis(output.value).toBTC(), + height: null, + satoshis: output.value, + confirmations: 0 }); + } - }); - + return results; }; AddressService.prototype.getAPIMethods = function() { diff --git a/lib/services/transaction/index.js b/lib/services/transaction/index.js index 177bf018..19d0fdec 100644 --- a/lib/services/transaction/index.js +++ b/lib/services/transaction/index.js @@ -162,6 +162,7 @@ TransactionService.prototype.setTxMetaInfo = function(tx, options, callback) { 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) { diff --git a/test/services/address/index.unit.js b/test/services/address/index.unit.js index 0c7663af..4507ed3c 100644 --- a/test/services/address/index.unit.js +++ b/test/services/address/index.unit.js @@ -180,6 +180,7 @@ describe('Address Service', function() { var txidStream = new EventEmitter(); + addressService._mempool = { getTxsByAddress: sinon.stub().callsArgWith(1, null, []) }; var createReadStream = sandbox.stub().returns(txidStream); addressService._db = { createReadStream: createReadStream };