diff --git a/app/controllers/status.js b/app/controllers/status.js new file mode 100644 index 00000000..7fbc189b --- /dev/null +++ b/app/controllers/status.js @@ -0,0 +1,51 @@ +'use strict'; + +/** + * Module dependencies. + */ + +var Status = require('../models/Status'); +var async = require('async'); + +/** + * Status + */ +exports.show = function(req, res) { + + if (! req.query.q) { + res.status(400).send('Bad Request'); + } + else { + var s = req.query.q; + var d = Status.new(); + + if (s == 'getInfo') { + d.getInfo(function(err) { + if (err) next(err); + res.jsonp(d); + }); + } + else if (s == 'getDifficulty') { + d.getDifficulty(function(err) { + if (err) next(err); + res.jsonp(d); + }); + } + else if (s == 'getTxOutSetInfo') { + d.getTxOutSetInfo(function(err) { + if (err) next(err); + res.jsonp(d); + }); + } + else if (s == 'getBestBlockHash') { + d.getBestBlockHash(function(err) { + if (err) next(err); + res.jsonp(d); + }); + } + else { + res.status(400).send('Bad Request'); + } + } +}; + diff --git a/app/models/Status.js b/app/models/Status.js new file mode 100644 index 00000000..fab5fffd --- /dev/null +++ b/app/models/Status.js @@ -0,0 +1,86 @@ +'use strict'; + +require('classtool'); + +function spec() { + var async = require('async'); + var RpcClient = require('bitcore/RpcClient').class(); + var config = require('../../config/config'); + var rpc = new RpcClient(config.bitcoind); + + function Status() { + this.info = {}; + this.difficulty = {}; + this.txoutsetinfo = {}; + this.bestblockhash = {}; + } + + Status.prototype.getInfo = function(next) { + var that = this; + async.series([ + function (cb) { + rpc.getInfo(function(err, info){ + if (err) return cb(err); + + that.info = info.result; + return cb(); + }); + } + ], function (err) { + return next(err); + }); + }; + + Status.prototype.getDifficulty = function(next) { + var that = this; + async.series([ + function (cb) { + rpc.getDifficulty(function(err, df){ + if (err) return cb(err); + + that.difficulty = df.result; + return cb(); + }); + } + ], function (err) { + return next(err); + }); + }; + + Status.prototype.getTxOutSetInfo = function(next) { + var that = this; + async.series([ + function (cb) { + rpc.getTxOutSetInfo(function(err, txout){ + if (err) return cb(err); + + that.txoutsetinfo = txout.result; + return cb(); + }); + } + ], function (err) { + return next(err); + }); + }; + + Status.prototype.getBestBlockHash = function(next) { + var that = this; + async.series([ + function (cb) { + rpc.getBestBlockHash(function(err, bbh){ + if (err) return cb(err); + + that.bestblockhash = bbh.result; + return cb(); + }); + } + ], function (err) { + return next(err); + }); + }; + + return Status; + +} +module.defineClass(spec); + diff --git a/app/views/includes/foot.jade b/app/views/includes/foot.jade index 5ed9cd8a..02578ffb 100755 --- a/app/views/includes/foot.jade +++ b/app/views/includes/foot.jade @@ -27,6 +27,7 @@ script(type='text/javascript', src='/js/directives.js') script(type='text/javascript', src='/js/filters.js') //Application Services +script(type='text/javascript', src='/js/services/status.js') script(type='text/javascript', src='/js/services/address.js') script(type='text/javascript', src='/js/services/transactions.js') script(type='text/javascript', src='/js/services/blocks.js') @@ -40,4 +41,5 @@ script(type='text/javascript', src='/js/controllers/blocks.js') script(type='text/javascript', src='/js/controllers/transactions.js') script(type='text/javascript', src='/js/controllers/address.js') script(type='text/javascript', src='/js/controllers/search.js') +script(type='text/javascript', src='/js/controllers/status.js') script(type='text/javascript', src='/js/init.js') diff --git a/config/routes.js b/config/routes.js index 07086bc9..2f26dc55 100644 --- a/config/routes.js +++ b/config/routes.js @@ -25,4 +25,8 @@ module.exports = function(app) { app.get('/api/addr/:addr', addresses.show); app.param('addr', addresses.address); + // Status route + var st = require('../app/controllers/status'); + app.get('/api/status', st.show); + }; diff --git a/public/js/app.js b/public/js/app.js index c11c807e..452ca7ce 100755 --- a/public/js/app.js +++ b/public/js/app.js @@ -13,7 +13,8 @@ var app = angular.module('mystery', 'mystery.transactions', 'monospaced.qrcode', 'mystery.address', - 'mystery.search' + 'mystery.search', + 'mystery.status' ]); angular.module('mystery.system', []); @@ -22,3 +23,4 @@ angular.module('mystery.blocks', []); angular.module('mystery.transactions', []); angular.module('mystery.address', []); angular.module('mystery.search', []); +angular.module('mystery.status', []); diff --git a/public/js/config.js b/public/js/config.js index 12813859..45fd3dc3 100755 --- a/public/js/config.js +++ b/public/js/config.js @@ -22,6 +22,9 @@ angular.module('mystery').config(['$routeProvider', when('/address/:addrStr', { templateUrl: 'views/address.html' }). + when('/status', { + templateUrl: 'views/status.html' + }). otherwise({ redirectTo: '/' }); diff --git a/public/js/controllers/header.js b/public/js/controllers/header.js index 8dddc143..53df9f8f 100755 --- a/public/js/controllers/header.js +++ b/public/js/controllers/header.js @@ -3,10 +3,16 @@ angular.module('mystery.system').controller('HeaderController', ['$scope', 'Global', function ($scope, Global) { $scope.global = Global; - $scope.menu = [{ - 'title': 'Blocks', - 'link': 'blocks' - }]; + $scope.menu = [ + { + 'title': 'Blocks', + 'link': 'blocks' + }, + { + 'title': 'Status', + 'link': 'status' + } + ]; $scope.isCollapsed = false; }]); diff --git a/public/js/controllers/status.js b/public/js/controllers/status.js new file mode 100644 index 00000000..b37a5aeb --- /dev/null +++ b/public/js/controllers/status.js @@ -0,0 +1,26 @@ +'use strict'; + +angular.module('mystery.status').controller('StatusController', ['$scope', '$routeParams', '$location', 'Global', 'Status', function ($scope, $routeParams, $location, Global, Status) { + $scope.global = Global; + + $scope.getData = function(q) { + Status.get({ + q: q + }, function(d) { + if (q == 'getInfo') { + $scope.info = d.info; + } + if (q == 'getDifficulty') { + $scope.difficulty = d.difficulty; + } + if (q == 'getTxOutSetInfo') { + $scope.txoutsetinfo = d.txoutsetinfo; + } + if (q == 'getBestBlockHash') { + $scope.bestblockhash = d.bestblockhash; + } + }); + }; + +}]); + diff --git a/public/js/services/status.js b/public/js/services/status.js new file mode 100644 index 00000000..2a066bf1 --- /dev/null +++ b/public/js/services/status.js @@ -0,0 +1,8 @@ +'use strict'; + +angular.module('mystery.status').factory('Status', ['$resource', function($resource) { + return $resource('/api/status', { + q: '@q' + }); +}]); + diff --git a/public/views/status.html b/public/views/status.html new file mode 100644 index 00000000..f28e0e40 --- /dev/null +++ b/public/views/status.html @@ -0,0 +1,144 @@ +
+ +
+
+

getInfo

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Loading...
Version{{info.version}}
protocolversion{{info.protocolversion}}
walletversion{{info.walletversion}}
balance{{info.balance}}
blocks{{info.blocks}}
timeoffset{{info.timeoffset}}
connections{{info.connections}}
proxy{{info.proxy}}
difficulty{{info.difficulty}}
testnet{{info.testnet}}
keypoololdest{{info.keypoololdest}}
keypoolsize{{info.keypoolsize}}
paytxfee{{info.paytxfee}}
errors{{info.errors}}
+
+
+

getTxOutSetInfo

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Loading...
Height{{txoutsetinfo.height}}
bestblock{{txoutsetinfo.bestblock}}
transactions{{txoutsetinfo.transactions}}
txouts{{txoutsetinfo.txouts}}
bytes_serialized{{txoutsetinfo.bytes_serialized}}
hash_serialized{{txoutsetinfo.hash_serialized}}
total_amount{{txoutsetinfo.total_amount}}
+
+
+ +
+
+

getDifficulty

+ + + + + + + + + + +
Loading...
Difficulty{{difficulty}}
+
+
+

getBestBlockHash

+ + + + + + + + + +
Loading...
{{bestblockhash}}
+
+
+
+ diff --git a/test/model/status.js b/test/model/status.js new file mode 100644 index 00000000..599d701a --- /dev/null +++ b/test/model/status.js @@ -0,0 +1,65 @@ +#!/usr/bin/env node + +process.env.NODE_ENV = process.env.NODE_ENV || 'development'; + +var + assert = require('assert'), + config = require('../../config/config'), + Status = require('../../app/models/Status').class(), + mongoose= require('mongoose'); + +describe('Status', function(){ + + before(function(done) { + mongoose.connect(config.db); + done(); + }); + + after(function(done) { + mongoose.connection.close(); + done(); + }); + + it('getInfo', function(done) { + var d = new Status(); + + d.getInfo(function(err) { + if (err) done(err); + assert.equal('number', typeof d.info.difficulty); + done(); + }); + }); + + it('getDifficulty', function(done) { + var d = new Status(); + + d.getDifficulty(function(err) { + if (err) done(err); + assert.equal('number', typeof d.difficulty); + done(); + }); + }); + + it('getTxOutSetInfo', function(done) { + var d = new Status(); + + d.getTxOutSetInfo(function(err) { + if (err) done(err); + assert.equal('number', typeof d.txoutsetinfo.txouts); + done(); + }); + }); + + it('getBestBlockHash', function(done) { + var d = new Status(); + + d.getBestBlockHash(function(err) { + if (err) done(err); + assert.equal('string', typeof d.bestblockhash); + done(); + }); + }); + + +}); + diff --git a/util/status_info.js b/util/status_info.js new file mode 100755 index 00000000..1b4deb80 --- /dev/null +++ b/util/status_info.js @@ -0,0 +1,20 @@ +#!/usr/bin/env node +process.env.NODE_ENV = process.env.NODE_ENV || 'development'; + +var RpcClient = require('../node_modules/bitcore/RpcClient').class(); + +var config = require('../config/config'); + +var rpc = new RpcClient(config.bitcoind); + +var block = rpc.getInfo(function(err, block) { + if (err) { + console.log("Err:"); + console.log(err); + } + + console.log("Block info:"); + console.log(block); +}); + +