Merge pull request #96 from cubedro/develop
Moved miners chart logic on server
This commit is contained in:
commit
f6c45086ff
11
.travis.yml
11
.travis.yml
@ -1,3 +1,14 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- "0.12"
|
- "0.12"
|
||||||
|
- "0.11"
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- secure: Qdkmi13nqcXskABBhbuGZmRakh4orOW1dalkSCyUbzGuYf0OdYF8ttNVuJa0WSWI4KhNXhtz2p3I8dM95wL++LCVqXFmIvZtX8Nca36KlNxIPNXPjn0odayh+c4pgrhrbz8TDmDXl9IPuZmNz8HHtN7xmIn6YDcm13wA3gTmfwo=
|
||||||
|
- RPC_HOST=localhost
|
||||||
|
- RPC_PORT=8080
|
||||||
|
- LISTENING_PORT=30303
|
||||||
|
- INSTANCE_NAME="Travis Node"
|
||||||
|
- CONTACT_DETAILS="marian@ethdev.com"
|
||||||
|
- WS_SERVER="wss://eth-netstats.herokuapp.com"
|
||||||
|
- NODE_ENV="production"
|
||||||
|
283
lib/node.js
283
lib/node.js
@ -89,14 +89,10 @@ function Node()
|
|||||||
pending: 0,
|
pending: 0,
|
||||||
gasPrice: 0,
|
gasPrice: 0,
|
||||||
block: {},
|
block: {},
|
||||||
blocktimeAvg: 0,
|
|
||||||
difficulty: [],
|
|
||||||
txDensity: [],
|
|
||||||
blockTimes: [],
|
|
||||||
gasSpending: [],
|
|
||||||
miners: [],
|
miners: [],
|
||||||
uptime: 0
|
uptime: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
this._lastStats = JSON.stringify(this.stats);
|
this._lastStats = JSON.stringify(this.stats);
|
||||||
|
|
||||||
this._tries = 0;
|
this._tries = 0;
|
||||||
@ -118,26 +114,41 @@ function Node()
|
|||||||
this._lastLatestLog = 0;
|
this._lastLatestLog = 0;
|
||||||
this._lastPendingLog = 0;
|
this._lastPendingLog = 0;
|
||||||
|
|
||||||
socket.on('open', function open() {
|
socket.on('open', function open()
|
||||||
socket.emit('hello', { id: self.id, info: self.info, secret: WS_SECRET });
|
{
|
||||||
console.info('The connection has been opened.');
|
console.info('The connection has been opened.');
|
||||||
console.info('Trying to login');
|
console.info('Trying to login');
|
||||||
|
|
||||||
|
socket.emit('hello', {
|
||||||
|
id: self.id,
|
||||||
|
info: self.info,
|
||||||
|
secret: WS_SECRET
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.on('end', function end() {
|
.on('end', function end()
|
||||||
|
{
|
||||||
self._socket = false;
|
self._socket = false;
|
||||||
console.error('Socket connection closed');
|
console.error('Socket connection closed');
|
||||||
})
|
})
|
||||||
.on('error', function error(err) {
|
.on('error', function error(err)
|
||||||
|
{
|
||||||
console.error("socket:", err);
|
console.error("socket:", err);
|
||||||
})
|
})
|
||||||
.on('reconnecting', function reconnecting(opts) {
|
.on('reconnecting', function reconnecting(opts)
|
||||||
|
{
|
||||||
console.warn('We are scheduling a reconnect operation', opts);
|
console.warn('We are scheduling a reconnect operation', opts);
|
||||||
})
|
})
|
||||||
.on('node-pong', function(data) {
|
.on('node-pong', function(data)
|
||||||
var latency = Math.ceil(((new Date()).getTime() - self._latency)/2);
|
{
|
||||||
socket.emit('latency', { id: self.id, latency: latency });
|
var latency = Math.ceil( (_.now() - self._latency) / 2 );
|
||||||
|
|
||||||
|
socket.emit('latency', {
|
||||||
|
id: self.id,
|
||||||
|
latency: latency
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.on('data', function incoming(data) {
|
.on('data', function incoming(data)
|
||||||
|
{
|
||||||
console.info('Received some data', data);
|
console.info('Received some data', data);
|
||||||
})
|
})
|
||||||
.on('ready', function()
|
.on('ready', function()
|
||||||
@ -147,13 +158,16 @@ function Node()
|
|||||||
|
|
||||||
console.info('The connection has been established.');
|
console.info('The connection has been established.');
|
||||||
})
|
})
|
||||||
.on('history', function(data)
|
.on('history', function (data)
|
||||||
{
|
{
|
||||||
console.info('Getting history.');
|
console.info('Getting history.');
|
||||||
var reqHistory = self.getHistory(data);
|
var reqHistory = self.getHistory( data );
|
||||||
|
|
||||||
console.info('Sending history.');
|
console.info('Sending history.');
|
||||||
socket.emit('history', {id: self.id, history: reqHistory});
|
socket.emit('history', {
|
||||||
|
id: self.id,
|
||||||
|
history: reqHistory
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
@ -198,7 +212,7 @@ Node.prototype.getBlock = function(number)
|
|||||||
timestamp: 0
|
timestamp: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
if(typeof number === 'undefined'){
|
if( _.isUndefined(number) ){
|
||||||
try {
|
try {
|
||||||
number = web3.eth.blockNumber;
|
number = web3.eth.blockNumber;
|
||||||
|
|
||||||
@ -213,23 +227,27 @@ Node.prototype.getBlock = function(number)
|
|||||||
try {
|
try {
|
||||||
block = web3.eth.getBlock(number, true);
|
block = web3.eth.getBlock(number, true);
|
||||||
|
|
||||||
if(block.hash != '?' && typeof block.difficulty !== 'undefined')
|
if(block.hash != '?' && !_.isUndefined(block.difficulty) )
|
||||||
{
|
{
|
||||||
block.difficulty = web3.toDecimal(block.difficulty);
|
block.difficulty = web3.toDecimal( block.difficulty );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
console.error("getBlock(" + number + "):", err);
|
console.error("getBlock(" + number + "):", err);
|
||||||
if(number > 0){
|
|
||||||
|
if(number > 0)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
number -= 1;
|
number--;
|
||||||
|
|
||||||
block = web3.eth.getBlock(number, true);
|
block = web3.eth.getBlock(number, true);
|
||||||
|
|
||||||
if(block.hash != '?' && typeof block.difficulty !== 'undefined')
|
if(block.hash !== '?' && !_.isUndefined(block.difficulty) )
|
||||||
{
|
{
|
||||||
block.difficulty = web3.toDecimal(block.difficulty);
|
block.difficulty = web3.toDecimal( block.difficulty );
|
||||||
}
|
}
|
||||||
} catch (err) {
|
}
|
||||||
|
catch (err) {
|
||||||
console.error("getBlock(" + number + "):", err);
|
console.error("getBlock(" + number + "):", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,99 +256,6 @@ Node.prototype.getBlock = function(number)
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node.prototype.getLatestBlocks = function()
|
|
||||||
{
|
|
||||||
var bestBlock = this.stats.block.number;
|
|
||||||
var maxIterations = MAX_BLOCKS_HISTORY;
|
|
||||||
var minBlock = 0;
|
|
||||||
|
|
||||||
if(this.blocks.length > 0)
|
|
||||||
{
|
|
||||||
maxIterations = Math.min(bestBlock - this.blocks[0].number, MAX_BLOCKS_HISTORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
minBlock = Math.max(0, parseInt(bestBlock) - maxIterations);
|
|
||||||
|
|
||||||
for (var i = minBlock; i < bestBlock; i++)
|
|
||||||
{
|
|
||||||
this.addBlockHistory(this.getBlock(i));
|
|
||||||
};
|
|
||||||
|
|
||||||
this.addBlockHistory(this.stats.block);
|
|
||||||
|
|
||||||
this.stats.blockTimes = this.calculateBlockTimes();
|
|
||||||
this.stats.blocktimeAvg = this.blockTimesAvg();
|
|
||||||
this.stats.difficulty = this.difficultyChart();
|
|
||||||
this.stats.txDensity = this.txDensityChart();
|
|
||||||
this.stats.gasSpending = this.gasSpendingChart();
|
|
||||||
this.stats.miners = this.minersChart();
|
|
||||||
}
|
|
||||||
|
|
||||||
Node.prototype.addBlockHistory = function(block)
|
|
||||||
{
|
|
||||||
if(this.blocks.length === 0 || (block !== null && block.number !== this.blocks[0].number))
|
|
||||||
{
|
|
||||||
if(this.blocks.length === MAX_BLOCKS_HISTORY)
|
|
||||||
{
|
|
||||||
this.blocks.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.blocks.unshift(block);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Node.prototype.calculateBlockTimes = function()
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
var blockTimes = _.map(this.blocks, function(block, key, list)
|
|
||||||
{
|
|
||||||
var diff = (key > 0 ? list[key - 1].timestamp : Math.floor(Date.now()/1000)) - block.timestamp;
|
|
||||||
|
|
||||||
diff = Math.max(diff, 0);
|
|
||||||
|
|
||||||
return diff;
|
|
||||||
});
|
|
||||||
|
|
||||||
blockTimes.shift();
|
|
||||||
|
|
||||||
return blockTimes;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node.prototype.blockTimesAvg = function()
|
|
||||||
{
|
|
||||||
var sum = _.reduce(this.stats.blockTimes, function(memo, time) { return memo + time;}, 0);
|
|
||||||
|
|
||||||
return sum/this.stats.blockTimes.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node.prototype.difficultyChart = function()
|
|
||||||
{
|
|
||||||
return difficulty = _.map(this.blocks, function(block)
|
|
||||||
{
|
|
||||||
return block.difficulty;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Node.prototype.txDensityChart = function()
|
|
||||||
{
|
|
||||||
return txDensity = _.map(this.blocks, function(block)
|
|
||||||
{
|
|
||||||
if(typeof block.transactions !== 'undefined')
|
|
||||||
return block.transactions.length;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Node.prototype.gasSpendingChart = function()
|
|
||||||
{
|
|
||||||
return gasSpending = _.map(this.blocks, function(block)
|
|
||||||
{
|
|
||||||
return block.gasUsed;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Node.prototype.getMinerName = function(miner)
|
Node.prototype.getMinerName = function(miner)
|
||||||
{
|
{
|
||||||
var result = _.find(this._knownMiners, {miner: miner});
|
var result = _.find(this._knownMiners, {miner: miner});
|
||||||
@ -358,27 +283,6 @@ Node.prototype.getMinerName = function(miner)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node.prototype.minersChart = function()
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
var miners = _.countBy(this.blocks, function(block)
|
|
||||||
{
|
|
||||||
return block.miner;
|
|
||||||
});
|
|
||||||
|
|
||||||
var minersArray = [];
|
|
||||||
|
|
||||||
_.forEach(miners, function(cnt, miner)
|
|
||||||
{
|
|
||||||
var name = self.getMinerName(miner);
|
|
||||||
minersArray.push({miner: miner, name: name, blocks: cnt});
|
|
||||||
});
|
|
||||||
|
|
||||||
var minersArray = _.sortBy(minersArray, 'blocks').reverse();
|
|
||||||
|
|
||||||
return minersArray.slice(0, MINERS_LIMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
Node.prototype.uptime = function()
|
Node.prototype.uptime = function()
|
||||||
{
|
{
|
||||||
this.stats.uptime = ((this._tries - this._down) / this._tries) * 100;
|
this.stats.uptime = ((this._tries - this._down) / this._tries) * 100;
|
||||||
@ -393,16 +297,17 @@ Node.prototype.getStats = function()
|
|||||||
{
|
{
|
||||||
var block = this.getBlock();
|
var block = this.getBlock();
|
||||||
|
|
||||||
if(block.hash !== '?') {
|
if( !_.isUndefined(block) && !_.isUndefined(block.number) && !_.isUndefined(block.hash) && block.hash !== '?' )
|
||||||
|
{
|
||||||
this.stats.block = block;
|
this.stats.block = block;
|
||||||
// Get last MAX_BLOCKS_HISTORY blocks for calculations
|
|
||||||
if(this.stats.block.number > 0)
|
|
||||||
this.getLatestBlocks();
|
|
||||||
|
|
||||||
if(PENDING_WORKS) {
|
if(PENDING_WORKS) {
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
this.stats.pending = web3.eth.getBlockTransactionCount('pending');
|
this.stats.pending = web3.eth.getBlockTransactionCount('pending');
|
||||||
} catch (err) {
|
}
|
||||||
|
catch (err)
|
||||||
|
{
|
||||||
PENDING_WORKS = false;
|
PENDING_WORKS = false;
|
||||||
console.error("getBlockTransactionCount('pending'):", err);
|
console.error("getBlockTransactionCount('pending'):", err);
|
||||||
}
|
}
|
||||||
@ -422,12 +327,12 @@ Node.prototype.getStats = function()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
this.stats.hashrate = 0;
|
this.stats.hashrate = 0;
|
||||||
}
|
|
||||||
|
|
||||||
this.stats.gasPrice = web3.toBigNumber(web3.eth.gasPrice).toString(10);
|
this.stats.gasPrice = web3.toBigNumber(web3.eth.gasPrice).toString(10);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
console.error("getStats: couldn't fetch block...");
|
console.error("getStats: couldn't fetch block...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -435,25 +340,34 @@ Node.prototype.getStats = function()
|
|||||||
this.uptime();
|
this.uptime();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node.prototype.getHistory = function(interval)
|
Node.prototype.getHistory = function(range)
|
||||||
{
|
{
|
||||||
var history = [];
|
var history = [];
|
||||||
console.log('interval', interval);
|
var interv = {};
|
||||||
if(typeof interval === 'undefined' || interval === null)
|
|
||||||
|
if( _.isUndefined(range) || range === null)
|
||||||
{
|
{
|
||||||
interval = {
|
interv = {
|
||||||
min: this.stats.block.number - MAX_HISTORY_UPDATE,
|
min: this.stats.block.number - MAX_HISTORY_UPDATE,
|
||||||
max: this.stats.block.number - 1
|
max: this.stats.block.number - 1
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var number = interval.min; number <= interval.max; number++)
|
if( !_.isUndefined(range.list) )
|
||||||
{
|
{
|
||||||
var block = this.getBlock(number);
|
interv = {
|
||||||
|
min: 0,
|
||||||
|
max: range.list.length - 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if(block !== null && block.number !== this.blocks[0].number)
|
for(var i = interv.min; i <= interv.max; i++)
|
||||||
|
{
|
||||||
|
var block = this.getBlock(( !_.isUndefined(range.list) ? range.list[i] : i));
|
||||||
|
|
||||||
|
if( block !== null && !_.isUndefined(block.number) )
|
||||||
{
|
{
|
||||||
history.push(block);
|
history.push( block );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,7 +376,7 @@ Node.prototype.getHistory = function(interval)
|
|||||||
|
|
||||||
Node.prototype.changed = function()
|
Node.prototype.changed = function()
|
||||||
{
|
{
|
||||||
var changed = ! _.isEqual(this._lastStats, JSON.stringify(this.stats));
|
var changed = ! _.isEqual( this._lastStats, JSON.stringify(this.stats) );
|
||||||
|
|
||||||
if(this._tries - this._lastSent > 5)
|
if(this._tries - this._lastSent > 5)
|
||||||
{
|
{
|
||||||
@ -484,7 +398,7 @@ Node.prototype.prepareStats = function()
|
|||||||
|
|
||||||
Node.prototype.sendUpdate = function(force)
|
Node.prototype.sendUpdate = function(force)
|
||||||
{
|
{
|
||||||
if(this.changed() || force)
|
if( this.changed() || force )
|
||||||
this.emit('update', this.prepareStats());
|
this.emit('update', this.prepareStats());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,11 +413,13 @@ Node.prototype.update = function()
|
|||||||
|
|
||||||
Node.prototype.updatePending = function()
|
Node.prototype.updatePending = function()
|
||||||
{
|
{
|
||||||
if(PENDING_WORKS) {
|
if(PENDING_WORKS)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
this.stats.pending = web3.eth.getBlockTransactionCount('pending');
|
this.stats.pending = web3.eth.getBlockTransactionCount('pending');
|
||||||
this.sendUpdate();
|
this.sendUpdate();
|
||||||
} catch (err) {
|
}
|
||||||
|
catch (err) {
|
||||||
PENDING_WORKS = false;
|
PENDING_WORKS = false;
|
||||||
console.error("getBlockTransactionCount('pending'):", err);
|
console.error("getBlockTransactionCount('pending'):", err);
|
||||||
}
|
}
|
||||||
@ -512,7 +428,7 @@ Node.prototype.updatePending = function()
|
|||||||
|
|
||||||
Node.prototype.ping = function()
|
Node.prototype.ping = function()
|
||||||
{
|
{
|
||||||
this._latency = (new Date()).getTime();
|
this._latency = _.now();
|
||||||
this.emit('node-ping', { id: this.id });
|
this.emit('node-ping', { id: this.id });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -522,9 +438,10 @@ Node.prototype.setWatches = function()
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
this.pendingFilter = web3.eth.filter('pending');
|
this.pendingFilter = web3.eth.filter('pending');
|
||||||
this.pendingFilter.watch( function(log) {
|
this.pendingFilter.watch( function (log)
|
||||||
|
{
|
||||||
if(PENDING_WORKS) {
|
if(PENDING_WORKS) {
|
||||||
var now = (new Date()).getTime();
|
var now = _.now();
|
||||||
var time = now - self._lastPendingLog;
|
var time = now - self._lastPendingLog;
|
||||||
|
|
||||||
if(time > 50)
|
if(time > 50)
|
||||||
@ -548,45 +465,19 @@ Node.prototype.setWatches = function()
|
|||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try {
|
this.updateInterval = setInterval( function(){
|
||||||
// this.chainFilter = web3.eth.filter('latest');
|
|
||||||
// this.chainFilter.watch(function(log)
|
|
||||||
// {
|
|
||||||
// var now = (new Date()).getTime();
|
|
||||||
// var time = now - self._lastLatestLog;
|
|
||||||
|
|
||||||
// if(time > 50)
|
|
||||||
// {
|
|
||||||
// self.update();
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// debounce(function() {
|
|
||||||
// self.update();
|
|
||||||
// }, 50);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// self._lastLatestLog = now;
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// catch (err)
|
|
||||||
// {
|
|
||||||
// console.error("Couldn't set up chain filter");
|
|
||||||
// console.error(err);
|
|
||||||
// }
|
|
||||||
|
|
||||||
this.updateInterval = setInterval(function(){
|
|
||||||
self.update();
|
self.update();
|
||||||
}, UPDATE_INTERVAL);
|
}, UPDATE_INTERVAL);
|
||||||
|
|
||||||
this.pingInterval = setInterval(function(){
|
this.pingInterval = setInterval( function(){
|
||||||
self.ping();
|
self.ping();
|
||||||
}, PING_INTERVAL);
|
}, PING_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node.prototype.emit = function(message, payload)
|
Node.prototype.emit = function(message, payload)
|
||||||
{
|
{
|
||||||
if(this._socket){
|
if(this._socket)
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
socket.emit(message, payload);
|
socket.emit(message, payload);
|
||||||
}
|
}
|
||||||
@ -599,8 +490,8 @@ Node.prototype.emit = function(message, payload)
|
|||||||
Node.prototype.installContract = function()
|
Node.prototype.installContract = function()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Contract = web3.eth.contract(registrar.desc);
|
Contract = web3.eth.contract( registrar.desc );
|
||||||
this._Registrar = new Contract(registrar.address);
|
this._Registrar = new Contract( registrar.address );
|
||||||
}
|
}
|
||||||
catch (err)
|
catch (err)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user