diff --git a/app/controllers/addresses.js b/app/controllers/addresses.js index e13000c..30671ee 100644 --- a/app/controllers/addresses.js +++ b/app/controllers/addresses.js @@ -4,30 +4,32 @@ * Module dependencies. */ -var Address = require('../models/Address'); +var Address = require('../models/Address'), + common = require('./common'); -/** - * Find block by hash ... - */ exports.address = function(req, res, next, addr) { - var a = Address.new(addr); + + + var a; + try { + a = Address.new(addr); + } catch (e) { + return common.handleErrors({message: 'Invalid address:' + e.message, code: 1}, res, next); + } a.update(function(err) { - if (err && !a.totalReceivedSat) { - console.log(err); - res.status(404).send('Invalid address'); - return next(); - } - - req.address = a; - return next(); - }); + if (err) + return common.handleErrors(err, res); + else { + req.address = a; + return next(); + } + }); }; /** - * Show block */ exports.show = function(req, res) { if (req.address) { diff --git a/app/controllers/blocks.js b/app/controllers/blocks.js index a21d52e..37324a0 100644 --- a/app/controllers/blocks.js +++ b/app/controllers/blocks.js @@ -4,7 +4,8 @@ * Module dependencies. */ var mongoose = require('mongoose'), - Block = mongoose.model('Block'); + Block = mongoose.model('Block'), + common = require('./common'); /** @@ -12,14 +13,12 @@ var mongoose = require('mongoose'), */ exports.block = function(req, res, next, hash) { Block.fromHashWithInfo(hash, function(err, block) { - if (err && !block) { - console.log(err); - res.status(404).send('Not found'); + if (err || ! block) + return common.handleErrors(err, res, next); + else { + req.block = block.info; return next(); } - - req.block = block.info; - return next(); }); }; diff --git a/app/controllers/common.js b/app/controllers/common.js new file mode 100644 index 0000000..b44756b --- /dev/null +++ b/app/controllers/common.js @@ -0,0 +1,16 @@ +'use strict'; + + +exports.handleErrors = function (err, res) { + if (err) { + if (err.code) { + res.status(400).send(err.message + '. Code:' + err.code); + } + else { + res.status(503).send(err.message); + } + } + else { + res.status(404).send('Not found'); + } +}; diff --git a/app/controllers/socket.js b/app/controllers/socket.js index f6e9e92..acfa2c9 100644 --- a/app/controllers/socket.js +++ b/app/controllers/socket.js @@ -27,5 +27,5 @@ module.exports.broadcast_address_tx = function(address, tx) { }; module.exports.broadcastSyncInfo = function(syncInfo) { - ios.sockets.emit('status', syncInfo); + ios.sockets.emit('sync', syncInfo); }; diff --git a/app/controllers/status.js b/app/controllers/status.js index 6652359..1874605 100644 --- a/app/controllers/status.js +++ b/app/controllers/status.js @@ -4,7 +4,8 @@ * Module dependencies. */ -var Status = require('../models/Status'); +var Status = require('../models/Status'), + common = require('./common'); /** * Status @@ -19,8 +20,11 @@ exports.show = function(req, res, next) { var statusObject = Status.new(); var returnJsonp = function (err) { - if(err) return next(err); - res.jsonp(statusObject); + if (err || ! statusObject) + return common.handleErrors(err, res); + else { + res.jsonp(statusObject); + } }; switch(option) { diff --git a/app/controllers/transactions.js b/app/controllers/transactions.js index 7276db4..5676790 100644 --- a/app/controllers/transactions.js +++ b/app/controllers/transactions.js @@ -7,6 +7,7 @@ var Transaction = require('../models/Transaction'); var Block = require('../models/Block'); var Address = require('../models/Address'); var async = require('async'); +var common = require('./common'); /** @@ -14,15 +15,12 @@ var async = require('async'); */ exports.transaction = function(req, res, next, txid) { Transaction.fromIdWithInfo(txid, function(err, tx) { - if (err) { - console.log(err); - res.status(404).send('Not found'); + if (err || ! tx) + return common.handleErrors(err, res); + else { + req.transaction = tx.info; return next(); } - - if (!tx) return next(new Error('Failed to load TX ' + txid)); - req.transaction = tx.info; - next(); }); }; diff --git a/app/models/Address.js b/app/models/Address.js index 05d1a78..e054ff1 100644 --- a/app/models/Address.js +++ b/app/models/Address.js @@ -19,11 +19,8 @@ function spec() { this.transactions = []; var a = new BitcoreAddress(addrStr); - try { - a.validate(); - this.addrStr = addrStr; - } catch(e){ - } + a.validate(); + this.addrStr = addrStr; Object.defineProperty(this, 'totalSent', { @@ -58,11 +55,6 @@ function spec() { } Address.prototype.update = function(next) { - - if (! this.addrStr) { - return next(new Error('Invalid or undefined address string')); - } - var that = this; async.series([ // TODO TXout! diff --git a/app/models/Block.js b/app/models/Block.js index e4d84d3..3f4bcbc 100644 --- a/app/models/Block.js +++ b/app/models/Block.js @@ -81,16 +81,33 @@ BlockSchema.statics.fromHash = function(hash, cb) { BlockSchema.statics.fromHashWithInfo = function(hash, cb) { + var That = this; + this.fromHash(hash, function(err, block) { if (err) return cb(err); - if (!block) { return cb(new Error('Block not found')); } - block.getInfo(function(err) { return cb(err,block); } ); + if (!block) { + // No in mongo...but maybe in bitcoind... lets query it + block = new That(); + + block.hash = hash; + block.getInfo(function(err, blockInfo) { + if (err) return cb(err); + if (!blockInfo) return cb(); + + block.save(function(err) { + return cb(err,block); + }); + }); + } + else { + block.getInfo(function(err) { + return cb(err,block); + }); + } }); }; - - // TODO: Can we store the rpc instance in the Block object? BlockSchema.methods.getInfo = function (next) { @@ -98,6 +115,9 @@ BlockSchema.methods.getInfo = function (next) { var rpc = new RpcClient(config.bitcoind); rpc.getBlock(this.hash, function(err, blockInfo) { + // Not found? + if (err && err.code === -5) return next(); + if (err) return next(err); /* diff --git a/app/models/Status.js b/app/models/Status.js index 321e227..517b51c 100644 --- a/app/models/Status.js +++ b/app/models/Status.js @@ -9,11 +9,6 @@ function spec() { var rpc = new RpcClient(config.bitcoind); function Status() { - this.info = {}; - this.difficulty = {}; - this.txoutsetinfo = {}; - this.bestblockhash = {}; - this.lastblockhash = {}; } Status.prototype.getInfo = function(next) { diff --git a/app/models/Transaction.js b/app/models/Transaction.js index b4f67f2..5e418ad 100644 --- a/app/models/Transaction.js +++ b/app/models/Transaction.js @@ -74,8 +74,8 @@ TransactionSchema.statics.fromIdWithInfo = function(txid, cb) { tx.txid = txid; tx.fillInfo(function(err, txInfo) { - if (!txInfo) - return cb(new Error('TX not found')); + if (err) return cb(err); + if (!txInfo) return cb(); tx.save(function(err) { return cb(err,tx); @@ -251,6 +251,10 @@ TransactionSchema.statics.queryInfo = function(txid, cb) { var rpc = new RpcClient(config.bitcoind); rpc.getRawTransaction(txid, 1, function(err, txInfo) { + + // Not found? + if (err && err.code === -5) return cb(); + if (err) return cb(err); var info = txInfo.result; diff --git a/lib/HistoricSync.js b/lib/HistoricSync.js index f9d3d0a..b33b4bd 100644 --- a/lib/HistoricSync.js +++ b/lib/HistoricSync.js @@ -142,13 +142,17 @@ function spec() { } if (opts.upToExisting && existed ) { - if (self.syncInfo.blocksToSync <= self.syncInfo.syncedBlocks) { + var diff = self.syncInfo.blocksToSync - self.syncInfo.syncedBlocks; + if (diff <= 0) { self.status = 'finished'; p('DONE. Found existing block: ', blockHash); return cb(err); } else { - p('WARN found target block\n\tbut blockChain Height is still higher that ours. Previous light sync must be interrupted.\n\tWill keep syncing.', self.syncInfo.syncedBlocks); + self.syncInfo.skipped_blocks = self.syncInfo.skipped_blocks || 1; + if ((self.syncInfo.skipped_blocks++ % 1000) === 1 ) { + p('WARN found target block\n\tbut blockChain Height is still higher that ours. Previous light sync must be interrupted.\n\tWill keep syncing.', self.syncInfo.syncedBlocks, self.syncInfo.blocksToSync, self.syncInfo.skipped_blocks); + } } } @@ -161,7 +165,7 @@ function spec() { // Continue if (blockInfo && blockInfo.result) { - self.syncInfo.syncedBlocks++; + if (! existed) self.syncInfo.syncedBlocks++; if (opts.prev && blockInfo.result.previousblockhash) { return self.getPrevNextBlock(blockInfo.result.previousblockhash, blockEnd, opts, cb); } diff --git a/public/js/controllers/address.js b/public/js/controllers/address.js index 6276230..664c2ba 100644 --- a/public/js/controllers/address.js +++ b/public/js/controllers/address.js @@ -16,8 +16,16 @@ angular.module('insight.address').controller('AddressController', addrStr: $routeParams.addrStr }, function(address) { $scope.address = address; - }, function() { - $rootScope.flashMessage = 'Address Not Found'; + }, function(e) { + if (e.status === 400) { + $rootScope.flashMessage = 'Invalid Address: ' + $routeParams.addrStr; + } + else if (e.status === 503) { + $rootScope.flashMessage = 'Backend Error. ' + e.data; + } + else { + $rootScope.flashMessage = 'Address Not Found'; + } $location.path('/'); }); }; diff --git a/public/js/controllers/blocks.js b/public/js/controllers/blocks.js index b398ef3..e300299 100644 --- a/public/js/controllers/blocks.js +++ b/public/js/controllers/blocks.js @@ -17,8 +17,16 @@ angular.module('insight.blocks').controller('BlocksController', ['$scope', '$roo blockHash: $routeParams.blockHash }, function(block) { $scope.block = block; - }, function() { - $rootScope.flashMessage = 'Block Not Found'; + }, function(e) { + if (e.status === 400) { + $rootScope.flashMessage = 'Invalid Transaction ID: ' + $routeParams.txId; + } + else if (e.status === 503) { + $rootScope.flashMessage = 'Backend Error. ' + e.data; + } + else { + $rootScope.flashMessage = 'Block Not Found'; + } $location.path('/'); }); }; diff --git a/public/js/controllers/status.js b/public/js/controllers/status.js index 8b5b538..8fa2f24 100644 --- a/public/js/controllers/status.js +++ b/public/js/controllers/status.js @@ -1,30 +1,31 @@ 'use strict'; -angular.module('insight.status').controller('StatusController', ['$scope', '$routeParams', '$location', 'Global', 'Status', function ($scope, $routeParams, $location, Global, Status) { +angular.module('insight.status').controller('StatusController', ['$scope', '$routeParams', '$location', '$rootScope', 'Global', 'Status', 'Sync', function ($scope, $routeParams, $location, $rootScope, Global, Status, Sync) { $scope.global = Global; - $scope.getData = function(q) { + $scope.getStatus = function(q) { Status.get({ - q: q + q: 'get' + q }, function(d) { - if (q === 'getInfo') { - $scope.info = d.info; + $rootScope.infoError = null; + angular.extend($scope, d); + }, function(e) { + if (e.status === 503) { + $rootScope.infoError = 'Backend Error. ' + e.data; } - if (q === 'getDifficulty') { - $scope.difficulty = d.difficulty; + else { + $rootScope.infoError = 'Unknown error:' + e.data; } - if (q === 'getTxOutSetInfo') { - $scope.txoutsetinfo = d.txoutsetinfo; - } - if (q === 'getBestBlockHash') { - $scope.bestblockhash = d.bestblockhash; - } - if (q === 'getLastBlockHash') { - $scope.lastblockhash = d.lastblockhash; - } - }); }; + $scope.getSync = function() { + Sync.get({}, function(sync) { + $rootScope.syncError = null; + $scope.sync = sync; + }, function(e) { + $rootScope.syncError = 'Could not get sync information' + e; + }); + }; }]); diff --git a/public/js/controllers/transactions.js b/public/js/controllers/transactions.js index 0658c5c..132881b 100644 --- a/public/js/controllers/transactions.js +++ b/public/js/controllers/transactions.js @@ -22,10 +22,23 @@ angular.module('insight.transactions').controller('transactionsController', txId: txid }, function(tx) { $scope.tx = tx; +<<<<<<< HEAD console.log(console.log(tx)); $scope.txs.push(tx); }, function() { $rootScope.flashMessage = 'Transaction Not Found'; +======= + }, function(e) { + if (e.status === 400) { + $rootScope.flashMessage = 'Invalid Transaction ID: ' + $routeParams.txId; + } + else if (e.status === 503) { + $rootScope.flashMessage = 'Backend Error. ' + e.data; + } + else { + $rootScope.flashMessage = 'Transaction Not Found'; + } +>>>>>>> matiu/feature/11showsyncstatus $location.path('/'); }); }; diff --git a/public/js/services/status.js b/public/js/services/status.js index f911c33..67d7004 100644 --- a/public/js/services/status.js +++ b/public/js/services/status.js @@ -6,3 +6,7 @@ angular.module('insight.status').factory('Status', ['$resource', function($resou }); }]); +angular.module('insight.status').factory('Sync', ['$resource', function($resource) { + return $resource('/api/sync'); +}]); + diff --git a/public/views/status.html b/public/views/status.html index 9009f92..7195119 100644 --- a/public/views/status.html +++ b/public/views/status.html @@ -7,11 +7,12 @@

getInfo

- +
- - - + + + @@ -65,19 +66,72 @@ - - + +
Loading...
Loading... +
{{infoError}}
Version {{info.version}}{{info.paytxfee}}
errors{{info.errors}}infoErrors{{info.infoErrors}}
-

getTxOutSetInfo

- +

sync status

+
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{ syncError }} +
{{ sync.err }} +
Sync Progress {{(100 * sync.syncedBlocks/sync.blocksToSync)| number:2}}% +
blocksToSync{{sync.blocksToSync}}
syncedBlocks{{sync.syncedBlocks}}
start{{sync.start}} + (genesisBlock) +
end{{sync.end}} + (genesisBlock) +
Sync Type +
    +
  • Stops at existing block +
  • + scanningBackward + scanningForward +
+
+ +

getTxOutSetInfo

+ + + + + + @@ -114,11 +168,15 @@

getDifficulty

-
Loading...
{{infoError}}
Height {{txoutsetinfo.height}}
+
- + + + + + @@ -128,12 +186,16 @@

getLastBlockHash

-
Loading...
{{infoError}}
Difficulty {{difficulty}}
+
- - + + + + + +
Loading...
Loading...
{{infoError}}
Last block hash {{lastblockhash}}