Fixed: APIs giving incorrect data

- Fixed: addr API giving decimals in satoshi values
- Fixed: Incorrect balance, totalSent, totalReceived values returned in API calls (issue: duplication)
- Fixed: incorrect totalCount value in addr API and duplication of tx list
This commit is contained in:
sairajzero 2023-01-28 20:18:23 +05:30
parent dbfe39991f
commit 3fbcbbe7bc

View File

@ -180,7 +180,7 @@ AddressService.prototype.getAddressHistory = function(addresses, options, stream
options.from = options.from || 0;
options.to = options.to || 0xffffffff;
if(!callback){ //if only 3 args, then streamer is callback
if(typeof callback !== 'function'){ //if only 3 args, then streamer is callback
callback = streamer;
streamer = () => null; //NULL fn
}
@ -202,13 +202,15 @@ AddressService.prototype.getAddressHistory = function(addresses, options, stream
self._streamAddressSummary(address, options, function(err, tx){
results.totalCount++;
if(err)
return log.error(err);
if(!options.txNotNeeded && results.items.length < MAX_TX_QUERY_LIMIT)
results.items.push(tx);
if(!options.txNotNeeded) {
let count = self._getOccurrenceCount(tx, address);
results.totalCount += 1 / count; //fix for duplication
if(results.items.length < MAX_TX_QUERY_LIMIT && !results.items.some(x => x.txid() === tx.txid())) //push only if tx not already in array
results.items.push(tx);
}
streamer(null, tx);
@ -220,7 +222,10 @@ AddressService.prototype.getAddressHistory = function(addresses, options, stream
return callback(err);
}
//TODO: sorting of tx list (results.items)
//sort items in desc block-height, then asc txid (if same height)
results.items.sort((a, b) => b.__height - a.__height || a.txid().localeCompare(b.txid()));
results.totalCount = parseInt(results.totalCount.toFixed());
callback(null, results);
})
@ -285,7 +290,7 @@ AddressService.prototype.getAddressSummary = function(address, options, streamer
options.queryMempool = true;
}
if(!callback){ //if only 3 args, then streamer is callback
if(typeof callback !== 'function'){ //if only 3 args, then streamer is callback
callback = streamer;
streamer = () => null; //NULL fn
}
@ -320,6 +325,11 @@ AddressService.prototype.getAddressSummary = function(address, options, streamer
return callback(err);
}
result.balanceSat = parseInt(result.balanceSat.toFixed());
result.totalReceivedSat = parseInt(result.totalReceivedSat.toFixed());
result.totalSentSat = parseInt(result.totalSentSat.toFixed());
result.txApperances = parseInt(result.txApperances.toFixed());
result.balance = Unit.fromSatoshis(result.balanceSat).toBTC();
result.totalReceived = Unit.fromSatoshis(result.totalReceivedSat).toBTC();
result.totalSent = Unit.fromSatoshis(result.totalSentSat).toBTC();
@ -373,10 +383,13 @@ AddressService.prototype._setInputResults = function(tx, address, result) {
}
};
AddressService.prototype._aggregateAddressSummaryResult = function (tx, address, result, options){
AddressService.prototype._getAddressSummaryResult = function(txs, address, result, options) {
var self = this;
for(var i = 0; i < txs.length; i++) {
var tx = txs[i];
self._setOutputResults(tx, address, result);
self._setInputResults(tx, address, result);
@ -387,20 +400,122 @@ AddressService.prototype._aggregateAddressSummaryResult = function (tx, address,
result.transactions.push(tx.txid());
}
}
AddressService.prototype._getAddressSummaryResult = function(txs, address, result, options) {
var self = this;
for(var i = 0; i < txs.length; i++) {
var tx = txs[i];
self._aggregateAddressSummaryResult(tx, address, result, options);
}
return result;
};
AddressService.prototype._getOccurrenceCount = function(tx, address) {
let count = 0;
for(var i = 0; i < tx.inputs.length; i++) {
var input = tx.inputs[i];
if(utils.getAddress(input, this._network) === address)
count++;
}
for(var j = 0; j < tx.outputs.length; j++) {
var output = tx.outputs[j];
if(utils.getAddress(output, this._network) === address)
count++;
}
return count;
}
AddressService.prototype._getOutputResults = function(tx, address) {
let result = { value: 0, count:0 };
for(var j = 0; j < tx.outputs.length; j++) {
var output = tx.outputs[j];
if (utils.getAddress(output, this._network) !== address) {
continue;
}
result.value += output.value;
result.count++;
}
return result;
};
AddressService.prototype._getInputResults = function(tx, address) {
let result = { value: 0, count:0 };
for(var i = 0; i < tx.inputs.length; i++) {
var input = tx.inputs[i];
if (utils.getAddress(input, this._network) !== address) {
continue;
}
result.value += tx.__inputValues[i];
result.count++;
}
return result;
};
AddressService.prototype._aggregateAddressSummaryResult = function (tx, address, result, options){
var self = this;
let output = self._getOutputResults(tx, address);
let input = self._getInputResults(tx, address);
//Since tx with multiple (x) input/output occurances of address will invoke this fn x time(s), (as we are not storing txid and hence cannot check for duplications)
//we divide the values by x and aggregate it to result.
//eg. tx with 1 input, 1 output => x=1+1=2.... input_val = 2, output_val = 1.
//the values will be aggregated 2 times, hence, we divide values by x i.e, 2.
//now agg_input_val = 2/2 =1, agg_output_val = 1/2 =0.5
//the fn ll be called x times, hence the total result will be, result=agg*x: input(1*2=2), output(0.5*2=1)
let total_count = input.count + output.count;
let div_input_val = input.value / total_count,
div_output_val = output.value / total_count;
//aggregate the result
result.txApperances += 1/total_count;
result.totalReceivedSat += div_output_val;
result.balanceSat += div_output_val;
result.totalSentSat += div_input_val;
result.balanceSat -= div_input_val;
if(!tx.confirmations){
result.unconfirmedTxApperances += 1/total_count;
result.unconfirmedBalanceSat += div_output_val;
result.unconfirmedBalanceSat -= div_input_val;
}
if (!options.noTxList) {
if (!result.transactions) {
result.transactions = [];
}
let txid = tx.txid();
if(!result.transactions.includes(txid) && result.transactions.length < MAX_TX_QUERY_LIMIT) //push txid only if its not in the array (list limit not maxed out)
result.transactions.push(txid);
}
}
AddressService.prototype.getAddressUnspentOutputs = function(address, options, callback) {
var self = this;