From bc4672760c09cfcd49f1ee2d608ea6be8153dd4a Mon Sep 17 00:00:00 2001 From: Patrick Nagurny Date: Tue, 15 Sep 2015 16:51:54 -0400 Subject: [PATCH] get blocks by date --- lib/blocks.js | 124 ++++++++++++++++++++++++++++++++++++------------- test/blocks.js | 20 ++++++-- 2 files changed, 106 insertions(+), 38 deletions(-) diff --git a/lib/blocks.js b/lib/blocks.js index d922d43..97e4394 100644 --- a/lib/blocks.js +++ b/lib/blocks.js @@ -83,50 +83,108 @@ BlockController.prototype.blockIndex = function(req, res, next, height) { BlockController.prototype.list = function(req, res) { var self = this; - // TODO actually get blocks by date instead of just the last blocks - // TODO pagination + var dateStr; + var todayStr = this.formatTimestamp(new Date()); + var isToday; + if (req.query.blockDate) { + dateStr = req.query.blockDate; + isToday = dateStr === todayStr; + } else { + dateStr = todayStr; + isToday = true; + } + + var gte = Math.round((new Date(dateStr)).getTime() / 1000); + + //pagination + var lte = parseInt(req.query.startTimestamp) || gte + 86400; + var prev = this.formatTimestamp(new Date((gte - 86400) * 1000)); + var next = lte ? this.formatTimestamp(new Date(lte * 1000)) : null; var limit = parseInt(req.query.limit || BLOCK_LIMIT); + var more = false; + var moreTs = lte; - var blocks = []; - var lastHash = this.node.services.db.tip.hash; - - async.timesSeries(limit, function(n, next) { - self.node.getBlock(lastHash, function(err, block) { - if(err) { - return next(err); - } - - var info = self.node.services.bitcoind.getBlockIndex(block.hash); - block.__height = info.height; - blocks.push(block); - lastHash = BufferUtil.reverse(block.header.prevHash).toString('hex'); - next(); - }); - }, function(err) { + self.node.services.db.getBlockHashesByTimestamp(gte, lte, function(err, hashes) { if(err) { return common.handleErrors(err, res); } - var data = { - blocks: blocks.map(function(block) { - return { - height: block.__height, - size: block.toBuffer().length, - hash: block.hash, - time: block.header.time, - txlength: block.transactions.length, - poolInfo: {} - }; - }), - length: blocks.length, - pagination: {} - }; + hashes.reverse(); - res.jsonp(data); + if(hashes.length > limit) { + more = true; + hashes = hashes.slice(0, limit); + } + + async.mapSeries( + hashes, + function(hash, next) { + self.node.getBlock(hash, function(err, block) { + if(err) { + return next(err); + } + + var info = self.node.services.bitcoind.getBlockIndex(hash); + block.__height = info.height; + + if(moreTs > block.header.timestamp) { + moreTs = block.header.timestamp; + } + + return next(null, block); + }); + }, + function(err, blocks) { + if(err) { + return common.handleErrors(err, res); + } + + blocks.sort(function(a, b) { + return b.__height - a.__height; + }); + + var data = { + blocks: blocks.map(function(block) { + return { + height: block.__height, + size: block.toBuffer().length, + hash: block.hash, + time: block.header.time, + txlength: block.transactions.length, + poolInfo: {} + }; + }), + length: blocks.length, + pagination: { + next: next, + prev: prev, + currentTs: lte - 1, + current: dateStr, + isToday: isToday, + more: more + } + }; + + if(more) { + data.pagination.moreTs = moreTs; + } + + res.jsonp(data); + } + ); }); }; +//helper to convert timestamps to yyyy-mm-dd format +BlockController.prototype.formatTimestamp = function(date) { + var yyyy = date.getUTCFullYear().toString(); + var mm = (date.getUTCMonth() + 1).toString(); // getMonth() is zero-based + var dd = date.getUTCDate().toString(); + + return yyyy + '-' + (mm[1] ? mm : '0' + mm[0]) + '-' + (dd[1] ? dd : '0' + dd[0]); //padding +}; + BlockController.prototype.getBlockReward = function(height) { var halvings = Math.floor(height / 210000); // Force block reward to zero when right shift is undefined. diff --git a/test/blocks.js b/test/blocks.js index 4eab00a..7eff9e6 100644 --- a/test/blocks.js +++ b/test/blocks.js @@ -125,13 +125,24 @@ describe('Blocks', function() { } ], "length": 2, - "pagination": {} + "pagination": { + "current": "2015-08-30", + "currentTs": 1440979199, + "isToday": false, + "more": false, + "next": "2015-08-31", + "prev": "2015-08-29" + } }; var stub = sinon.stub(); stub.onFirstCall().callsArgWith(1, null, bitcore.Block.fromBuffer(blocks['000000000008fbb2e358e382a6f6948b2da24563bba183af447e6e2542e8efc7'], 'hex')); stub.onSecondCall().callsArgWith(1, null, bitcore.Block.fromBuffer(blocks['00000000000006bd8fe9e53780323c0e85719eca771022e1eb6d10c62195c441'], 'hex')) + var hashes = [ + '00000000000006bd8fe9e53780323c0e85719eca771022e1eb6d10c62195c441', + '000000000008fbb2e358e382a6f6948b2da24563bba183af447e6e2542e8efc7' + ]; var node = { getBlock: stub, services: { @@ -141,9 +152,7 @@ describe('Blocks', function() { } }, db: { - tip: { - hash: '000000000008fbb2e358e382a6f6948b2da24563bba183af447e6e2542e8efc7' - } + getBlockHashesByTimestamp: sinon.stub().callsArgWith(2, null, hashes) } } }; @@ -153,7 +162,8 @@ describe('Blocks', function() { var req = { query: { - limit: 2 + limit: 2, + blockDate: '2015-08-30' } };