diff --git a/lib/services/address/index.js b/lib/services/address/index.js index 94c4db9f..da903766 100644 --- a/lib/services/address/index.js +++ b/lib/services/address/index.js @@ -90,7 +90,8 @@ AddressService.prototype.start = function(callback) { }, function(next) { self.mempoolIndex = levelup( - self.mempoolIndexPath, { + self.mempoolIndexPath, + { db: self.levelupStore, keyEncoding: 'binary', valueEncoding: 'binary', @@ -155,17 +156,20 @@ AddressService.prototype.getAPIMethods = function() { * Called by the Bus to get the available events for this service. */ AddressService.prototype.getPublishEvents = function() { - return [{ - name: 'address/transaction', - scope: this, - subscribe: this.subscribe.bind(this, 'address/transaction'), - unsubscribe: this.unsubscribe.bind(this, 'address/transaction') - }, { - name: 'address/balance', - scope: this, - subscribe: this.subscribe.bind(this, 'address/balance'), - unsubscribe: this.unsubscribe.bind(this, 'address/balance') - }]; + return [ + { + name: 'address/transaction', + scope: this, + subscribe: this.subscribe.bind(this, 'address/transaction'), + unsubscribe: this.unsubscribe.bind(this, 'address/transaction') + }, + { + name: 'address/balance', + scope: this, + subscribe: this.subscribe.bind(this, 'address/balance'), + unsubscribe: this.unsubscribe.bind(this, 'address/balance') + } + ]; }; /** @@ -305,7 +309,7 @@ AddressService.prototype.updateMempoolIndex = function(tx, add, callback) { var hashBufferHex = addressInfo.hashBuffer.toString('hex'); - if (add) { + if(add) { this.mempoolAddressIndex[hashBufferHex] = true; } else { delete this.mempoolAddressIndex[hashBufferHex]; @@ -404,7 +408,7 @@ AddressService.prototype.updateMempoolIndex = function(tx, add, callback) { }); var inputHashBufferHex = inputHashBuffer.toString('hex'); - if (add) { + if(add) { this.mempoolAddressIndex[inputHashBufferHex] = true; } else { delete this.mempoolAddressIndex[inputHashBufferHex]; @@ -458,7 +462,7 @@ AddressService.prototype.blockHandler = function(block, addOutput, callback) { var script = output.script; - if (!script) { + if(!script) { log.debug('Invalid script'); continue; } @@ -474,7 +478,7 @@ AddressService.prototype.blockHandler = function(block, addOutput, callback) { // less than the mean of the 11 previous blocks) and not greater than 2 // hours in the future. var key = encoding.encodeOutputKey(addressInfo.hashBuffer, addressInfo.hashTypeBuffer, - height, txidBuffer, outputIndex); + height, txidBuffer, outputIndex); var value = encoding.encodeOutputValue(output.satoshis, output._scriptBuffer); operations.push({ type: action, @@ -506,11 +510,11 @@ AddressService.prototype.blockHandler = function(block, addOutput, callback) { this.transactionEventHandler(txmessages[addressKey]); } - if (tx.isCoinbase()) { + if(tx.isCoinbase()) { continue; } - for (var inputIndex = 0; inputIndex < inputs.length; inputIndex++) { + for(var inputIndex = 0; inputIndex < inputs.length; inputIndex++) { var input = inputs[inputIndex]; var inputHash; @@ -572,14 +576,14 @@ AddressService.prototype.blockHandler = function(block, addOutput, callback) { * @param {Boolean} obj.rejected - If the transaction was not accepted in the mempool */ AddressService.prototype.transactionEventHandler = function(obj) { - if (this.subscriptions['address/transaction'][obj.addressInfo.hashHex]) { + if(this.subscriptions['address/transaction'][obj.addressInfo.hashHex]) { var emitters = this.subscriptions['address/transaction'][obj.addressInfo.hashHex]; var address = new Address({ hashBuffer: obj.addressInfo.hashBuffer, network: this.node.network, type: obj.addressInfo.addressType }); - for (var i = 0; i < emitters.length; i++) { + for(var i = 0; i < emitters.length; i++) { emitters[i].emit('address/transaction', { rejected: obj.rejected, height: obj.height, @@ -603,7 +607,7 @@ AddressService.prototype.transactionEventHandler = function(obj) { * @param {String} obj.addressType */ AddressService.prototype.balanceEventHandler = function(block, obj) { - if (this.subscriptions['address/balance'][obj.hashHex]) { + if(this.subscriptions['address/balance'][obj.hashHex]) { var emitters = this.subscriptions['address/balance'][obj.hashHex]; var address = new Address({ hashBuffer: obj.hashBuffer, @@ -611,10 +615,10 @@ AddressService.prototype.balanceEventHandler = function(block, obj) { type: obj.addressType }); this.getBalance(address, true, function(err, balance) { - if (err) { + if(err) { return this.emit(err); } - for (var i = 0; i < emitters.length; i++) { + for(var i = 0; i < emitters.length; i++) { emitters[i].emit('address/balance', address, balance, block); } }); @@ -633,9 +637,9 @@ AddressService.prototype.subscribe = function(name, emitter, addresses) { $.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter'); $.checkArgument(Array.isArray(addresses), 'Second argument is expected to be an Array of addresses'); - for (var i = 0; i < addresses.length; i++) { + for(var i = 0; i < addresses.length; i++) { var hashHex = bitcore.Address(addresses[i]).hashBuffer.toString('hex'); - if (!this.subscriptions[name][hashHex]) { + if(!this.subscriptions[name][hashHex]) { this.subscriptions[name][hashHex] = []; } this.subscriptions[name][hashHex].push(emitter); @@ -653,16 +657,16 @@ AddressService.prototype.unsubscribe = function(name, emitter, addresses) { $.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter'); $.checkArgument(Array.isArray(addresses) || _.isUndefined(addresses), 'Second argument is expected to be an Array of addresses or undefined'); - if (!addresses) { + if(!addresses) { return this.unsubscribeAll(name, emitter); } - for (var i = 0; i < addresses.length; i++) { + for(var i = 0; i < addresses.length; i++) { var hashHex = bitcore.Address(addresses[i]).hashBuffer.toString('hex'); - if (this.subscriptions[name][hashHex]) { + if(this.subscriptions[name][hashHex]) { var emitters = this.subscriptions[name][hashHex]; var index = emitters.indexOf(emitter); - if (index > -1) { + if(index > -1) { emitters.splice(index, 1); } } @@ -677,10 +681,10 @@ AddressService.prototype.unsubscribe = function(name, emitter, addresses) { AddressService.prototype.unsubscribeAll = function(name, emitter) { $.checkArgument(emitter instanceof EventEmitter, 'First argument is expected to be an EventEmitter'); - for (var hashHex in this.subscriptions[name]) { + for(var hashHex in this.subscriptions[name]) { var emitters = this.subscriptions[name][hashHex]; var index = emitters.indexOf(emitter); - if (index > -1) { + if(index > -1) { emitters.splice(index, 1); } } @@ -695,7 +699,7 @@ AddressService.prototype.unsubscribeAll = function(name, emitter) { */ AddressService.prototype.getBalance = function(address, queryMempool, callback) { this.getUnspentOutputs(address, queryMempool, function(err, outputs) { - if (err) { + if(err) { return callback(err); } @@ -864,7 +868,7 @@ AddressService.prototype.getInputs = function(addressStr, options, callback) { stream.on('data', function(input) { inputs.push(input); if (inputs.length > self.maxInputsQueryLength) { - log.warn('Tried to query too many inputs (' + self.maxInputsQueryLength + ') for address ' + addressStr); + log.warn('Tried to query too many inputs (' + self.maxInputsQueryLength + ') for address '+ addressStr); error = new Error('Maximum number of inputs (' + self.maxInputsQueryLength + ') per query reached'); stream.end(); } @@ -883,7 +887,7 @@ AddressService.prototype.getInputs = function(addressStr, options, callback) { return callback(error); } - if (options.queryMempool) { + if(options.queryMempool) { self._getInputsMempool(addressStr, hashBuffer, hashTypeBuffer, function(err, mempoolInputs) { if (err) { return callback(err); @@ -1104,7 +1108,7 @@ AddressService.prototype.getOutputs = function(addressStr, options, callback) { return callback(error); } - if (options.queryMempool) { + if(options.queryMempool) { self._getOutputsMempool(addressStr, hashBuffer, hashTypeBuffer, function(err, mempoolOutputs) { if (err) { return callback(err); @@ -1188,7 +1192,7 @@ AddressService.prototype._getOutputsMempool = function(addressStr, hashBuffer, h AddressService.prototype.getUnspentOutputs = function(addresses, queryMempool, callback) { var self = this; - if (!Array.isArray(addresses)) { + if(!Array.isArray(addresses)) { addresses = [addresses]; } @@ -1196,9 +1200,9 @@ AddressService.prototype.getUnspentOutputs = function(addresses, queryMempool, c async.eachSeries(addresses, function(address, next) { self.getUnspentOutputsForAddress(address, queryMempool, function(err, unspents) { - if (err && err instanceof errors.NoOutputs) { + if(err && err instanceof errors.NoOutputs) { return next(); - } else if (err) { + } else if(err) { return next(err); } @@ -1220,12 +1224,10 @@ AddressService.prototype.getUnspentOutputsForAddress = function(address, queryMe var self = this; - this.getOutputs(address, { - queryMempool: queryMempool - }, function(err, outputs) { + this.getOutputs(address, {queryMempool: queryMempool}, function(err, outputs) { if (err) { return callback(err); - } else if (!outputs.length) { + } else if(!outputs.length) { return callback(new errors.NoOutputs('Address ' + address + ' has no outputs'), []); } @@ -1350,7 +1352,6 @@ AddressService.prototype.getAddressSummary = function(addressArg, options, callb } async.waterfall([ - function(next) { self._getAddressConfirmedSummary(address, options, next); }, @@ -1372,7 +1373,9 @@ AddressService.prototype.getAddressSummary = function(addressArg, options, callb var seconds = Math.round(timeDelta / 1000); log.warn('Slow (' + seconds + 's) getAddressSummary request for address: ' + address.toString()); } + callback(null, summary); + }); }; @@ -1388,7 +1391,6 @@ AddressService.prototype._getAddressConfirmedSummary = function(address, options }; async.waterfall([ - function(next) { self._getAddressConfirmedInputsSummary(address, baseResult, options, next); }, @@ -1435,8 +1437,8 @@ AddressService.prototype._getAddressConfirmedInputsSummary = function(address, r AddressService.prototype._getAddressConfirmedOutputsSummary = function(address, result, options, callback) { $.checkArgument(address instanceof Address); $.checkArgument(!_.isUndefined(result) && - !_.isUndefined(result.appearanceIds) && - !_.isUndefined(result.unconfirmedAppearanceIds)); + !_.isUndefined(result.appearanceIds) && + !_.isUndefined(result.unconfirmedAppearanceIds)); var self = this; var count = 0; @@ -1450,16 +1452,16 @@ AddressService.prototype._getAddressConfirmedOutputsSummary = function(address, result.totalReceived += output.satoshis; result.appearanceIds[txid] = output.height; - if (!options.noBalance) { + if(!options.noBalance) { // Bitcoind's isSpent only works for confirmed transactions var spentDB = self.node.services.bitcoind.isSpent(txid, outputIndex); - if (!spentDB) { + if(!spentDB) { result.balance += output.satoshis; } - if (options.queryMempool) { + if(options.queryMempool) { // Check to see if this output is spent in the mempool and if so // we will subtract it from the unconfirmedBalance (a.k.a unconfirmedDelta) var spentIndexSyncKey = encoding.encodeSpentIndexSyncKey( @@ -1467,7 +1469,7 @@ AddressService.prototype._getAddressConfirmedOutputsSummary = function(address, outputIndex ); var spentMempool = self.mempoolSpentIndex[spentIndexSyncKey]; - if (spentMempool) { + if(spentMempool) { result.unconfirmedBalance -= output.satoshis; } } @@ -1523,43 +1525,41 @@ AddressService.prototype._getAddressMempoolSummary = function(address, options, var hashTypeBuffer = constants.HASH_TYPES_MAP[address.type]; var hashBufferHex = hashBuffer.toString('hex'); - if (!this.mempoolAddressIndex[hashBufferHex]) { + if(!this.mempoolAddressIndex[hashBufferHex]) { return callback(null, result); } async.waterfall([ - function(next) { self._getInputsMempool(addressStr, hashBuffer, hashTypeBuffer, function(err, mempoolInputs) { if (err) { return next(err); } - for (var i = 0; i < mempoolInputs.length; i++) { + for(var i = 0; i < mempoolInputs.length; i++) { var input = mempoolInputs[i]; result.unconfirmedAppearanceIds[input.txid] = input.timestamp; } next(null, result); }); - }, - function(result, next) { + }, function(result, next) { self._getOutputsMempool(addressStr, hashBuffer, hashTypeBuffer, function(err, mempoolOutputs) { if (err) { return next(err); } - for (var i = 0; i < mempoolOutputs.length; i++) { + for(var i = 0; i < mempoolOutputs.length; i++) { var output = mempoolOutputs[i]; result.unconfirmedAppearanceIds[output.txid] = output.timestamp; - if (!options.noBalance) { + if(!options.noBalance) { var spentIndexSyncKey = encoding.encodeSpentIndexSyncKey( new Buffer(output.txid, 'hex'), // TODO: get buffer directly output.outputIndex ); var spentMempool = self.mempoolSpentIndex[spentIndexSyncKey]; // Only add this to the balance if it's not spent in the mempool already - if (!spentMempool) { + if(!spentMempool) { result.unconfirmedBalance += output.satoshis; } } diff --git a/test/services/address/history.unit.js b/test/services/address/history.unit.js index 917ac735..ab3ee5c8 100644 --- a/test/services/address/history.unit.js +++ b/test/services/address/history.unit.js @@ -122,7 +122,9 @@ describe('Address Service History', function() { history.get(function() { history.node.services.address.getAddressSummary.callCount.should.equal(1); history.node.services.address.getAddressSummary.args[0][0].should.equal(address); - history.node.services.address.getAddressSummary.args[0][1].should.equal(options); + history.node.services.address.getAddressSummary.args[0][1].should.equal({ + noBalance: true, + }); history._paginateWithDetails.callCount.should.equal(1); history._paginateWithDetails.args[0][0].should.equal(txids); history._mergeAndSortTxids.callCount.should.equal(0); @@ -155,7 +157,6 @@ describe('Address Service History', function() { history.node.services.address.getAddressSummary.args[0][0].should.equal(address); history.node.services.address.getAddressSummary.args[0][1].should.deep.equal({ fullTxList: true, - noBalance: true, }); history._paginateWithDetails.callCount.should.equal(1); history._paginateWithDetails.args[0][0].should.equal(txids);