Pagination Optimization
- Sort and paginate before getting full transaction details. - Only get detailed transaction information for items within the current page. - Improves the performance with large sets of transactions.
This commit is contained in:
parent
1cf34f2dd8
commit
d3641f3b0a
@ -21,12 +21,11 @@ function AddressHistory(args) {
|
|||||||
this.addresses = [args.addresses];
|
this.addresses = [args.addresses];
|
||||||
}
|
}
|
||||||
this.transactionInfo = [];
|
this.transactionInfo = [];
|
||||||
this.transactions = {};
|
this.combinedArray = [];
|
||||||
this.sortedArray = [];
|
this.detailedArray = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressHistory.MAX_ADDRESS_QUERIES = 20;
|
AddressHistory.MAX_ADDRESS_QUERIES = 20;
|
||||||
AddressHistory.MAX_TX_QUERIES = 10;
|
|
||||||
|
|
||||||
AddressHistory.prototype.get = function(callback) {
|
AddressHistory.prototype.get = function(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -45,8 +44,11 @@ AddressHistory.prototype.get = function(callback) {
|
|||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.combineTransactionInfo();
|
||||||
|
self.sortAndPaginateCombinedArray();
|
||||||
|
|
||||||
async.eachSeries(
|
async.eachSeries(
|
||||||
self.transactionInfo,
|
self.combinedArray,
|
||||||
function(txInfo, next) {
|
function(txInfo, next) {
|
||||||
self.getDetailedInfo(txInfo, next);
|
self.getDetailedInfo(txInfo, next);
|
||||||
},
|
},
|
||||||
@ -54,9 +56,7 @@ AddressHistory.prototype.get = function(callback) {
|
|||||||
if (err) {
|
if (err) {
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
self.sortTransactionsIntoArray();
|
callback(null, self.detailedArray);
|
||||||
self.paginateSortedArray();
|
|
||||||
callback(null, self.sortedArray);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -103,86 +103,107 @@ AddressHistory.prototype.getTransactionInfo = function(address, next) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function combines results from getInputs and getOutputs by
|
||||||
|
* combining inputIndexes and outputIndexes for address transaction
|
||||||
|
* matching combinations.
|
||||||
|
*/
|
||||||
|
AddressHistory.prototype.combineTransactionInfo = function() {
|
||||||
|
var combinedArrayMap = {};
|
||||||
|
this.combinedArray = [];
|
||||||
|
var l = this.transactionInfo.length;
|
||||||
|
for(var i = 0; i < l; i++) {
|
||||||
|
var item = this.transactionInfo[i];
|
||||||
|
var mapKey = item.address + item.txid;
|
||||||
|
if (combinedArrayMap[mapKey] >= 0) {
|
||||||
|
var combined = this.combinedArray[combinedArrayMap[mapKey]];
|
||||||
|
if (item.outputIndex >= 0) {
|
||||||
|
combined.satoshis += item.satoshis;
|
||||||
|
combined.outputIndexes.push(item.outputIndex);
|
||||||
|
} else if (item.inputIndex >= 0) {
|
||||||
|
combined.inputIndexes.push(item.inputIndex);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.outputIndexes = [];
|
||||||
|
item.inputIndexes = [];
|
||||||
|
if (item.outputIndex >= 0) {
|
||||||
|
item.outputIndexes.push(item.outputIndex);
|
||||||
|
delete item.outputIndex;
|
||||||
|
} else if (item.inputIndex >= 0) {
|
||||||
|
item.inputIndexes.push(item.inputIndex);
|
||||||
|
delete item.inputIndex;
|
||||||
|
}
|
||||||
|
this.combinedArray.push(item);
|
||||||
|
combinedArrayMap[mapKey] = this.combinedArray.length - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AddressHistory.prototype.sortAndPaginateCombinedArray = function() {
|
||||||
|
this.combinedArray.sort(AddressHistory.sortByHeight);
|
||||||
|
if (!_.isUndefined(this.options.from) && !_.isUndefined(this.options.to)) {
|
||||||
|
this.combinedArray = this.combinedArray.slice(this.options.from, this.options.to);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
AddressHistory.sortByHeight = function(a, b) {
|
AddressHistory.sortByHeight = function(a, b) {
|
||||||
// TODO consider timestamp for mempool transactions
|
// TODO consider timestamp for mempool transactions
|
||||||
return a.height < b.height;
|
return a.height < b.height;
|
||||||
};
|
};
|
||||||
|
|
||||||
AddressHistory.prototype.paginateSortedArray = function() {
|
|
||||||
if (!_.isUndefined(this.options.from) && !_.isUndefined(this.options.to)) {
|
|
||||||
this.sortedArray = this.sortedArray.slice(this.options.from, this.options.to);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
AddressHistory.prototype.getDetailedInfo = function(txInfo, next) {
|
AddressHistory.prototype.getDetailedInfo = function(txInfo, next) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var queryMempool = _.isUndefined(self.options.queryMempool) ? true : self.options.queryMempool;
|
var queryMempool = _.isUndefined(self.options.queryMempool) ? true : self.options.queryMempool;
|
||||||
|
|
||||||
if (self.transactions[txInfo.address] && self.transactions[txInfo.address][txInfo.txid]) {
|
self.node.services.db.getTransactionWithBlockInfo(
|
||||||
self.amendDetailedInfoWithSatoshis(txInfo);
|
txInfo.txid,
|
||||||
setImmediate(next);
|
queryMempool,
|
||||||
} else {
|
function(err, transaction) {
|
||||||
self.node.services.db.getTransactionWithBlockInfo(
|
if (err) {
|
||||||
txInfo.txid,
|
return next(err);
|
||||||
queryMempool,
|
}
|
||||||
function(err, transaction) {
|
|
||||||
if (err) {
|
transaction.populateInputs(self.node.services.db, [], function(err) {
|
||||||
|
if(err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
transaction.populateInputs(self.node.services.db, [], function(err) {
|
self.detailedArray.push({
|
||||||
if(err) {
|
address: txInfo.address,
|
||||||
return next(err);
|
satoshis: self.getSatoshisDetail(transaction, txInfo),
|
||||||
}
|
height: transaction.__height,
|
||||||
var confirmations = 0;
|
confirmations: self.getConfirmationsDetail(transaction),
|
||||||
if (transaction.__height >= 0) {
|
timestamp: transaction.__timestamp,
|
||||||
confirmations = self.node.services.db.tip.__height - transaction.__height + 1;
|
// TODO bitcore should return null instead of throwing error on coinbase
|
||||||
}
|
fees: !transaction.isCoinbase() ? transaction.getFee() : null,
|
||||||
|
outputIndexes: txInfo.outputIndexes,
|
||||||
if (!self.transactions[txInfo.address]) {
|
inputIndexes: txInfo.inputIndexes,
|
||||||
self.transactions[txInfo.address] = {};
|
tx: transaction
|
||||||
}
|
|
||||||
|
|
||||||
self.transactions[txInfo.address][txInfo.txid] = {
|
|
||||||
address: txInfo.address,
|
|
||||||
satoshis: 0,
|
|
||||||
height: transaction.__height,
|
|
||||||
confirmations: confirmations,
|
|
||||||
timestamp: transaction.__timestamp,
|
|
||||||
// TODO bitcore should return null instead of throwing error on coinbase
|
|
||||||
fees: !transaction.isCoinbase() ? transaction.getFee() : null,
|
|
||||||
outputIndexes: [],
|
|
||||||
inputIndexes: [],
|
|
||||||
tx: transaction
|
|
||||||
};
|
|
||||||
|
|
||||||
self.amendDetailedInfoWithSatoshis(txInfo);
|
|
||||||
next();
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
);
|
next();
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
AddressHistory.prototype.amendDetailedInfoWithSatoshis = function(txInfo) {
|
AddressHistory.prototype.getConfirmationsDetail = function(transaction) {
|
||||||
var historyItem = this.transactions[txInfo.address][txInfo.txid];
|
var confirmations = 0;
|
||||||
if (txInfo.outputIndex >= 0) {
|
if (transaction.__height >= 0) {
|
||||||
historyItem.outputIndexes.push(txInfo.outputIndex);
|
confirmations = this.node.services.db.tip.__height - transaction.__height + 1;
|
||||||
historyItem.satoshis += txInfo.satoshis;
|
|
||||||
} else if (txInfo.inputIndex >= 0){
|
|
||||||
historyItem.inputIndexes.push(txInfo.inputIndex);
|
|
||||||
historyItem.satoshis -= historyItem.tx.inputs[txInfo.inputIndex].output.satoshis;
|
|
||||||
}
|
}
|
||||||
|
return confirmations;
|
||||||
};
|
};
|
||||||
|
|
||||||
AddressHistory.prototype.sortTransactionsIntoArray = function() {
|
AddressHistory.prototype.getSatoshisDetail = function(transaction, txInfo) {
|
||||||
this.sortedArray = [];
|
var satoshis = txInfo.satoshis || 0;
|
||||||
for(var address in this.transactions) {
|
|
||||||
for(var txid in this.transactions[address]) {
|
if (txInfo.inputIndexes.length >= 0) {
|
||||||
this.sortedArray.push(this.transactions[address][txid]);
|
for(var j = 0; j < txInfo.inputIndexes.length; j++) {
|
||||||
|
satoshis -= transaction.inputs[txInfo.inputIndexes[j]].output.satoshis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.sortedArray.sort(AddressHistory.sortByHeight);
|
return satoshis;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = AddressHistory;
|
module.exports = AddressHistory;
|
||||||
|
|||||||
@ -23,9 +23,9 @@ describe('Address Service History', function() {
|
|||||||
history.node.should.equal(node);
|
history.node.should.equal(node);
|
||||||
history.options.should.equal(options);
|
history.options.should.equal(options);
|
||||||
history.addresses.should.equal(addresses);
|
history.addresses.should.equal(addresses);
|
||||||
history.transactions.should.deep.equal({});
|
|
||||||
history.transactionInfo.should.deep.equal([]);
|
history.transactionInfo.should.deep.equal([]);
|
||||||
history.sortedArray.should.deep.equal([]);
|
history.combinedArray.should.deep.equal([]);
|
||||||
|
history.detailedArray.should.deep.equal([]);
|
||||||
});
|
});
|
||||||
it('will set addresses an array if only sent a string', function() {
|
it('will set addresses an array if only sent a string', function() {
|
||||||
var history = new AddressHistory({
|
var history = new AddressHistory({
|
||||||
@ -46,10 +46,11 @@ describe('Address Service History', function() {
|
|||||||
addresses: addresses
|
addresses: addresses
|
||||||
});
|
});
|
||||||
var expected = [{}];
|
var expected = [{}];
|
||||||
history.sortedArray = expected;
|
history.detailedArray = expected;
|
||||||
history.transactionInfo = [{}];
|
history.combinedArray = [{}];
|
||||||
history.getTransactionInfo = sinon.stub().callsArg(1);
|
history.getTransactionInfo = sinon.stub().callsArg(1);
|
||||||
history.paginateSortedArray = sinon.stub();
|
history.combineTransactionInfo = sinon.stub();
|
||||||
|
history.sortAndPaginateCombinedArray = sinon.stub();
|
||||||
history.getDetailedInfo = sinon.stub().callsArg(1);
|
history.getDetailedInfo = sinon.stub().callsArg(1);
|
||||||
history.sortTransactionsIntoArray = sinon.stub();
|
history.sortTransactionsIntoArray = sinon.stub();
|
||||||
history.get(function(err, results) {
|
history.get(function(err, results) {
|
||||||
@ -58,8 +59,8 @@ describe('Address Service History', function() {
|
|||||||
}
|
}
|
||||||
history.getTransactionInfo.callCount.should.equal(1);
|
history.getTransactionInfo.callCount.should.equal(1);
|
||||||
history.getDetailedInfo.callCount.should.equal(1);
|
history.getDetailedInfo.callCount.should.equal(1);
|
||||||
history.sortTransactionsIntoArray.callCount.should.equal(1);
|
history.combineTransactionInfo.callCount.should.equal(1);
|
||||||
history.paginateSortedArray.callCount.should.equal(1);
|
history.sortAndPaginateCombinedArray.callCount.should.equal(1);
|
||||||
results.should.equal(expected);
|
results.should.equal(expected);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -236,7 +237,7 @@ describe('Address Service History', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('#paginateSortedArray', function() {
|
describe('#sortAndPaginateCombinedArray', function() {
|
||||||
it('from 0 to 2', function() {
|
it('from 0 to 2', function() {
|
||||||
var history = new AddressHistory({
|
var history = new AddressHistory({
|
||||||
node: {},
|
node: {},
|
||||||
@ -246,21 +247,21 @@ describe('Address Service History', function() {
|
|||||||
},
|
},
|
||||||
addresses: []
|
addresses: []
|
||||||
});
|
});
|
||||||
history.sortedArray = [
|
history.combinedArray = [
|
||||||
{
|
{
|
||||||
height: 14
|
height: 13
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
height: 13,
|
height: 14,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
height: 12
|
height: 12
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
history.paginateSortedArray();
|
history.sortAndPaginateCombinedArray();
|
||||||
history.sortedArray.length.should.equal(2);
|
history.combinedArray.length.should.equal(2);
|
||||||
history.sortedArray[0].height.should.equal(14);
|
history.combinedArray[0].height.should.equal(14);
|
||||||
history.sortedArray[1].height.should.equal(13);
|
history.combinedArray[1].height.should.equal(13);
|
||||||
});
|
});
|
||||||
it('from 0 to 4 (exceeds length)', function() {
|
it('from 0 to 4 (exceeds length)', function() {
|
||||||
var history = new AddressHistory({
|
var history = new AddressHistory({
|
||||||
@ -271,22 +272,22 @@ describe('Address Service History', function() {
|
|||||||
},
|
},
|
||||||
addresses: []
|
addresses: []
|
||||||
});
|
});
|
||||||
history.sortedArray = [
|
history.combinedArray = [
|
||||||
{
|
{
|
||||||
height: 14
|
height: 13
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
height: 13,
|
height: 14,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
height: 12
|
height: 12
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
history.paginateSortedArray();
|
history.sortAndPaginateCombinedArray();
|
||||||
history.sortedArray.length.should.equal(3);
|
history.combinedArray.length.should.equal(3);
|
||||||
history.sortedArray[0].height.should.equal(14);
|
history.combinedArray[0].height.should.equal(14);
|
||||||
history.sortedArray[1].height.should.equal(13);
|
history.combinedArray[1].height.should.equal(13);
|
||||||
history.sortedArray[2].height.should.equal(12);
|
history.combinedArray[2].height.should.equal(12);
|
||||||
});
|
});
|
||||||
it('from 0 to 1', function() {
|
it('from 0 to 1', function() {
|
||||||
var history = new AddressHistory({
|
var history = new AddressHistory({
|
||||||
@ -297,20 +298,20 @@ describe('Address Service History', function() {
|
|||||||
},
|
},
|
||||||
addresses: []
|
addresses: []
|
||||||
});
|
});
|
||||||
history.sortedArray = [
|
history.combinedArray = [
|
||||||
{
|
{
|
||||||
height: 14
|
height: 13
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
height: 13,
|
height: 14,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
height: 12
|
height: 12
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
history.paginateSortedArray();
|
history.sortAndPaginateCombinedArray();
|
||||||
history.sortedArray.length.should.equal(1);
|
history.combinedArray.length.should.equal(1);
|
||||||
history.sortedArray[0].height.should.equal(14);
|
history.combinedArray[0].height.should.equal(14);
|
||||||
});
|
});
|
||||||
it('from 2 to 3', function() {
|
it('from 2 to 3', function() {
|
||||||
var history = new AddressHistory({
|
var history = new AddressHistory({
|
||||||
@ -321,20 +322,20 @@ describe('Address Service History', function() {
|
|||||||
},
|
},
|
||||||
addresses: []
|
addresses: []
|
||||||
});
|
});
|
||||||
history.sortedArray = [
|
history.combinedArray = [
|
||||||
{
|
{
|
||||||
height: 14
|
height: 13
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
height: 13,
|
height: 14,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
height: 12
|
height: 12
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
history.paginateSortedArray();
|
history.sortAndPaginateCombinedArray();
|
||||||
history.sortedArray.length.should.equal(1);
|
history.combinedArray.length.should.equal(1);
|
||||||
history.sortedArray[0].height.should.equal(12);
|
history.combinedArray[0].height.should.equal(12);
|
||||||
});
|
});
|
||||||
it('from 10 to 20 (out of range)', function() {
|
it('from 10 to 20 (out of range)', function() {
|
||||||
var history = new AddressHistory({
|
var history = new AddressHistory({
|
||||||
@ -345,19 +346,19 @@ describe('Address Service History', function() {
|
|||||||
},
|
},
|
||||||
addresses: []
|
addresses: []
|
||||||
});
|
});
|
||||||
history.sortedArray = [
|
history.combinedArray = [
|
||||||
{
|
{
|
||||||
height: 14
|
height: 13
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
height: 13,
|
height: 14,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
height: 12
|
height: 12
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
history.paginateSortedArray();
|
history.sortAndPaginateCombinedArray();
|
||||||
history.sortedArray.length.should.equal(0);
|
history.combinedArray.length.should.equal(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -375,13 +376,10 @@ describe('Address Service History', function() {
|
|||||||
options: {},
|
options: {},
|
||||||
addresses: []
|
addresses: []
|
||||||
});
|
});
|
||||||
history.transactions[txid] = {};
|
|
||||||
history.amendDetailedInfoWithSatoshis = sinon.stub();
|
|
||||||
history.getDetailedInfo(txid, function(err) {
|
history.getDetailedInfo(txid, function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
history.amendDetailedInfoWithSatoshis.callCount.should.equal(1);
|
|
||||||
history.node.services.db.getTransactionsWithBlockInfo.callCount.should.equal(0);
|
history.node.services.db.getTransactionsWithBlockInfo.callCount.should.equal(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -460,7 +458,8 @@ describe('Address Service History', function() {
|
|||||||
var transactionInfo = {
|
var transactionInfo = {
|
||||||
txid: txid,
|
txid: txid,
|
||||||
timestamp: 1407292005,
|
timestamp: 1407292005,
|
||||||
outputIndex: 1,
|
outputIndexes: [1],
|
||||||
|
inputIndexes: [],
|
||||||
satoshis: 48020000,
|
satoshis: 48020000,
|
||||||
address: txAddress
|
address: txAddress
|
||||||
};
|
};
|
||||||
@ -468,7 +467,7 @@ describe('Address Service History', function() {
|
|||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
var info = history.transactions[txAddress][txid];
|
var info = history.detailedArray[0];
|
||||||
info.address.should.equal(txAddress);
|
info.address.should.equal(txAddress);
|
||||||
info.satoshis.should.equal(48020000);
|
info.satoshis.should.equal(48020000);
|
||||||
info.height.should.equal(314159);
|
info.height.should.equal(314159);
|
||||||
@ -481,94 +480,47 @@ describe('Address Service History', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('#getConfirmationsDetail', function() {
|
||||||
describe('#amendDetailedInfoWithSatoshis', function() {
|
it('the correct confirmations when included in the tip', function() {
|
||||||
it('will amend info with inputIndex and subtract satoshis', function() {
|
|
||||||
var txid = '46f24e0c274fc07708b781963576c4c5d5625d926dbb0a17fa865dcd9fe58ea0';
|
|
||||||
var history = new AddressHistory({
|
var history = new AddressHistory({
|
||||||
node: {},
|
node: {
|
||||||
options: {},
|
services: {
|
||||||
addresses: []
|
db: {
|
||||||
});
|
tip: {
|
||||||
history.transactions[address] = {};
|
__height: 100
|
||||||
history.transactions[address][txid] = {
|
|
||||||
inputIndexes: [],
|
|
||||||
satoshis: 10,
|
|
||||||
tx: {
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
output: {
|
|
||||||
satoshis: 3000
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
}
|
},
|
||||||
};
|
options: {},
|
||||||
history.amendDetailedInfoWithSatoshis({
|
addresses: []
|
||||||
address: address,
|
|
||||||
txid: txid,
|
|
||||||
inputIndex: 0
|
|
||||||
});
|
});
|
||||||
history.transactions[address][txid].inputIndexes.should.deep.equal([0]);
|
var transaction = {
|
||||||
history.transactions[address][txid].satoshis.should.equal(-2990);
|
__height: 100
|
||||||
|
};
|
||||||
|
history.getConfirmationsDetail(transaction).should.equal(1);
|
||||||
});
|
});
|
||||||
it('will amend info with outputIndex and add satoshis', function() {
|
});
|
||||||
var txid = '46f24e0c274fc07708b781963576c4c5d5625d926dbb0a17fa865dcd9fe58ea0';
|
describe('#getSatoshisDetail', function() {
|
||||||
|
it('subtract inputIndexes satoshis without outputIndexes', function() {
|
||||||
var history = new AddressHistory({
|
var history = new AddressHistory({
|
||||||
node: {},
|
node: {},
|
||||||
options: {},
|
options: {},
|
||||||
addresses: []
|
addresses: []
|
||||||
});
|
});
|
||||||
history.transactions[address] = {};
|
var transaction = {
|
||||||
history.transactions[address][txid] = {
|
inputs: [
|
||||||
outputIndexes: [],
|
{
|
||||||
satoshis: 10
|
output: {
|
||||||
};
|
satoshis: 10000
|
||||||
history.amendDetailedInfoWithSatoshis({
|
}
|
||||||
address: address,
|
|
||||||
txid: txid,
|
|
||||||
outputIndex: 10,
|
|
||||||
satoshis: 2000
|
|
||||||
});
|
|
||||||
history.transactions[address][txid].outputIndexes.should.deep.equal([10]);
|
|
||||||
history.transactions[address][txid].satoshis.should.equal(2010);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('#sortTransactionIntoArray', function() {
|
|
||||||
it('will convert this.transactions into an array and sort by height', function() {
|
|
||||||
var history = new AddressHistory({
|
|
||||||
node: {},
|
|
||||||
options: {
|
|
||||||
from: 10,
|
|
||||||
to: 20
|
|
||||||
},
|
|
||||||
addresses: []
|
|
||||||
});
|
|
||||||
history.transactions = {
|
|
||||||
address1: {
|
|
||||||
txid1: {
|
|
||||||
height: 12
|
|
||||||
},
|
|
||||||
txid2: {
|
|
||||||
height: 14,
|
|
||||||
},
|
|
||||||
txid3: {
|
|
||||||
height: 13
|
|
||||||
}
|
}
|
||||||
},
|
]
|
||||||
address2: {
|
|
||||||
txid4: {
|
|
||||||
height: 15
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
history.sortTransactionsIntoArray();
|
var txInfo = {
|
||||||
history.sortedArray.length.should.equal(4);
|
inputIndexes: [0]
|
||||||
history.sortedArray[0].height.should.equal(15);
|
};
|
||||||
history.sortedArray[1].height.should.equal(14);
|
history.getSatoshisDetail(transaction, txInfo).should.equal(-10000);
|
||||||
history.sortedArray[2].height.should.equal(13);
|
|
||||||
history.sortedArray[3].height.should.equal(12);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user