add meteor frontend app
@@ -0,0 +1,26 @@
|
||||
(function(){/* Services */
|
||||
|
||||
_ = lodash;
|
||||
|
||||
socket = new Primus({url: 'wss://stats.ethdev.com'});
|
||||
|
||||
toastr = window.toastr;
|
||||
toastr.options = {
|
||||
"closeButton": false,
|
||||
"debug": false,
|
||||
"progressBar": false,
|
||||
"newestOnTop": true,
|
||||
"positionClass": "toast-top-right",
|
||||
"preventDuplicates": false,
|
||||
"onclick": null,
|
||||
"showDuration": "300",
|
||||
"hideDuration": "1000",
|
||||
"timeOut": "5000",
|
||||
"extendedTimeOut": "1000",
|
||||
"showEasing": "swing",
|
||||
"hideEasing": "linear",
|
||||
"showMethod": "fadeIn",
|
||||
"hideMethod": "fadeOut"
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,670 @@
|
||||
(function(){// Collections
|
||||
|
||||
Blockchain = new Mongo.Collection('blockchain', {connection: null});
|
||||
Nodes = new Mongo.Collection('nodes', {connection: null});
|
||||
Map = new Mongo.Collection('map', {connection: null});
|
||||
|
||||
|
||||
|
||||
/* Controllers */
|
||||
|
||||
|
||||
var MAX_BINS = 40;
|
||||
|
||||
// Main Stats init
|
||||
// ---------------
|
||||
|
||||
Blockchain.insert({
|
||||
_id: 'meta',
|
||||
frontierHash: '0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa',
|
||||
nodesTotal: 0,
|
||||
nodesActive: 0,
|
||||
bestBlock: 0,
|
||||
lastBlock: 0,
|
||||
lastDifficulty: 0,
|
||||
upTimeTotal: 0,
|
||||
avgBlockTime: 0,
|
||||
blockPropagationAvg: 0,
|
||||
avgHashrate: 0,
|
||||
uncleCount: 0,
|
||||
bestStats: {},
|
||||
|
||||
lastBlocksTime: _.fill(Array(MAX_BINS), 2),
|
||||
difficultyChart: _.fill(Array(MAX_BINS), 2),
|
||||
transactionDensity: _.fill(Array(MAX_BINS), 2),
|
||||
gasSpending: _.fill(Array(MAX_BINS), 2),
|
||||
miners: [],
|
||||
|
||||
map: [],
|
||||
blockPropagationChart: [],
|
||||
uncleCountChart: _.fill(Array(MAX_BINS), 2),
|
||||
coinbases: [],
|
||||
|
||||
latency: 0,
|
||||
|
||||
currentApiVersion: "0.0.16",
|
||||
|
||||
predicate: localStorage.predicate || ['-pinned', '-stats.active', '-stats.block.number', 'stats.block.propagation'],
|
||||
reverse: localStorage.reverse || false,
|
||||
pinned: localStorage.pinned || [],
|
||||
|
||||
prefixPredicate: ['-pinned', '-stats.active'],
|
||||
originalPredicate: ['-stats.block.number', 'stats.block.propagation']
|
||||
});
|
||||
|
||||
|
||||
// $scope.orderTable = function(predicate, reverse)
|
||||
// {
|
||||
// if(!_.isEqual(predicate, $scope.originalPredicate))
|
||||
// {
|
||||
// $scope.reverse = reverse;
|
||||
// $scope.originalPredicate = predicate;
|
||||
// $scope.predicate = _.union($scope.prefixPredicate, predicate);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// $scope.reverse = !$scope.reverse;
|
||||
|
||||
// if($scope.reverse === true){
|
||||
// _.forEach(predicate, function (value, key) {
|
||||
// predicate[key] = (value[0] === '-' ? value.replace('-', '') : '-' + value);
|
||||
// });
|
||||
// }
|
||||
|
||||
// $scope.predicate = _.union($scope.prefixPredicate, predicate);
|
||||
// }
|
||||
|
||||
// localStorage.predicate = $scope.predicate;
|
||||
// localStorage.reverse = $scope.reverse;
|
||||
// }
|
||||
|
||||
// $scope.pinNode = function(id)
|
||||
// {
|
||||
// index = findIndex({id: id});
|
||||
|
||||
// if( !_.isUndefined($scope.nodes[index]) )
|
||||
// {
|
||||
// $scope.nodes[index].pinned = !$scope.nodes[index].pinned;
|
||||
|
||||
// if($scope.nodes[index].pinned)
|
||||
// {
|
||||
// $scope.pinned.push(id);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// $scope.pinned.splice($scope.pinned.indexOf(id), 1);
|
||||
// }
|
||||
// }
|
||||
|
||||
// localStorage.pinned = $scope.pinned;
|
||||
// }
|
||||
|
||||
// var timeout = setInterval(function ()
|
||||
// {
|
||||
// $scope.$apply();
|
||||
// }, 300);
|
||||
|
||||
// $scope.getNumber = function (num) {
|
||||
// return new Array(num);
|
||||
// }
|
||||
|
||||
// Socket listeners
|
||||
// ----------------
|
||||
|
||||
socket.on('open', function open() {
|
||||
socket.emit('ready');
|
||||
console.log('The connection has been opened.');
|
||||
})
|
||||
.on('end', function end() {
|
||||
console.log('Socket connection ended.')
|
||||
})
|
||||
.on('error', function error(err) {
|
||||
console.log(err);
|
||||
})
|
||||
.on('reconnecting', function reconnecting(opts) {
|
||||
console.log('We are scheduling a reconnect operation', opts);
|
||||
})
|
||||
.on('data', function incoming(data) {
|
||||
socketAction(data.action, data.data);
|
||||
});
|
||||
|
||||
socket.on('init', function(data)
|
||||
{
|
||||
_.each(data.nodes, function(node){
|
||||
Nodes.upsert(node.id, socketAction('init', node));
|
||||
|
||||
addToMap(node);
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('client-latency', function(data)
|
||||
{
|
||||
Blockchain.update('meta', {$set: {
|
||||
latency: data.latency
|
||||
}});
|
||||
})
|
||||
|
||||
function socketAction(action, data)
|
||||
{
|
||||
// console.log('Action: ', action);
|
||||
// console.log('Data: ', data);
|
||||
|
||||
switch(action)
|
||||
{
|
||||
case "init":
|
||||
var node = data;
|
||||
|
||||
// Init hashrate
|
||||
if( _.isUndefined(node.stats.hashrate) )
|
||||
node.stats.hashrate = 0;
|
||||
|
||||
// Init latency
|
||||
latencyFilter(node);
|
||||
|
||||
// Init history
|
||||
if( _.isUndefined(data.history) )
|
||||
{
|
||||
data.history = new Array(40);
|
||||
_.fill(data.history, -1);
|
||||
}
|
||||
|
||||
// Init or recover pin
|
||||
node.pinned = (Blockchain.findOne().pinned.indexOf(node.id) >= 0 ? true : false);
|
||||
|
||||
if( Nodes.find().count() > 0 )
|
||||
{
|
||||
toastr['success']("Got nodes list", "Got nodes!");
|
||||
|
||||
updateActiveNodes();
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
case "add":
|
||||
|
||||
if( addNewNode(data) )
|
||||
toastr['success']("New node "+ Nodes.findOne(data.id).info.name +" connected!", "New node!");
|
||||
else
|
||||
toastr['info']("Node "+ Nodes.findOne(data.id).info.name +" reconnected!", "Node is back!");
|
||||
|
||||
break;
|
||||
|
||||
// TODO: Remove when everybody updates api client to 0.0.12
|
||||
case "update":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( foundNode && !_.isUndefined(foundNode.stats) )
|
||||
{
|
||||
if( !_.isUndefined(foundNode.stats.latency) )
|
||||
data.stats.latency = foundNode.stats.latency;
|
||||
|
||||
if( _.isUndefined(data.stats.hashrate) )
|
||||
data.stats.hashrate = 0;
|
||||
|
||||
if( foundNode.stats.block.number < data.stats.block.number )
|
||||
{
|
||||
|
||||
var best = Nodes.findOne({},{sort: {'stats.block.number': -1}});
|
||||
|
||||
if(best) {
|
||||
if (data.block.number > best.stats.block.number) {
|
||||
data.block.arrived = _.now();
|
||||
} else {
|
||||
data.block.arrived = best.stats.block.arrived;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foundNode.history = data.history;
|
||||
}
|
||||
|
||||
foundNode.stats = data.stats;
|
||||
foundNode.stats.block = data.block; // necessary?
|
||||
|
||||
if( !_.isUndefined(data.stats.latency) && _.get(foundNode, 'stats.latency', 0) !== data.stats.latency )
|
||||
{
|
||||
foundNode.stats.latency = data.stats.latency;
|
||||
|
||||
latencyFilter(foundNode);
|
||||
}
|
||||
|
||||
Nodes.update(data.id, foundNode);
|
||||
|
||||
updateBestBlock();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "block":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
if( foundNode && foundNode.stats )
|
||||
{
|
||||
var set = {};
|
||||
|
||||
if( foundNode.stats.block.number < data.block.number )
|
||||
{
|
||||
var best = Nodes.findOne({},{sort: {'stats.block.number': -1}});
|
||||
|
||||
if(best) {
|
||||
if (data.block.number > best.stats.block.number) {
|
||||
data.block.arrived = _.now();
|
||||
} else {
|
||||
data.block.arrived = best.stats.block.arrived;
|
||||
}
|
||||
}
|
||||
|
||||
set.history = data.history;
|
||||
}
|
||||
|
||||
set['stats.block'] = data.block;
|
||||
set['stats.propagationAvg'] = data.propagationAvg;
|
||||
|
||||
Nodes.update('meta', {$set: set});
|
||||
|
||||
updateBestBlock();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "pending":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( !_.isUndefined(data.id) && foundNode )
|
||||
{
|
||||
|
||||
if( !_.isUndefined(foundNode) && !_.isUndefined(foundNode.stats.pending) && !_.isUndefined(data.pending) )
|
||||
Nodes.update(data.id, {$set: {
|
||||
'stats.pending': data.pending
|
||||
}});
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "stats":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( !_.isUndefined(data.id) && foundNode )
|
||||
{
|
||||
|
||||
if( !_.isUndefined(foundNode) && !_.isUndefined(foundNode.stats) )
|
||||
{
|
||||
Nodes.update(foundNode._id, {$set:{
|
||||
'stats.active': data.stats.active,
|
||||
'stats.mining': data.stats.mining,
|
||||
'stats.hashrate': data.stats.hashrate,
|
||||
'stats.peers': data.stats.peers,
|
||||
'stats.gasPrice': data.stats.gasPrice,
|
||||
'stats.uptime': data.stats.uptime
|
||||
}});
|
||||
|
||||
if( !_.isUndefined(data.stats.latency) && _.get(foundNode, 'stats.latency', 0) !== data.stats.latency )
|
||||
{
|
||||
Nodes.update(foundNode._id, {$set:{
|
||||
'stats.latency': data.stats.latency
|
||||
}});
|
||||
|
||||
latencyFilter(foundNode);
|
||||
}
|
||||
|
||||
updateActiveNodes();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "info":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( foundNode )
|
||||
{
|
||||
var set = {};
|
||||
|
||||
set.info = data.info;
|
||||
|
||||
if( _.isUndefined(foundNode.pinned) )
|
||||
set.pinned = false;
|
||||
|
||||
Nodes.update(data.id, {$set: set});
|
||||
|
||||
// Init latency
|
||||
latencyFilter(foundNode);
|
||||
|
||||
updateActiveNodes();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "blockPropagationChart":
|
||||
Blockchain.update('meta', {$set:{
|
||||
blockPropagationChart: data.histogram,
|
||||
blockPropagationAvg: data.avg
|
||||
}});
|
||||
|
||||
break;
|
||||
|
||||
case "uncleCount":
|
||||
Blockchain.update('meta', {$set:{
|
||||
uncleCount: data[0] + data[1],
|
||||
uncleCountChart: (function(){
|
||||
data.reverse();
|
||||
return data;
|
||||
})()
|
||||
}});
|
||||
|
||||
break;
|
||||
|
||||
case "charts":
|
||||
var meta = Blockchain.findOne('meta');
|
||||
|
||||
if( !_.isEqual(meta.avgBlockTime, data.avgBlocktime) )
|
||||
meta.avgBlockTime = data.avgBlocktime;
|
||||
|
||||
if( !_.isEqual(meta.avgHashrate, data.avgHashrate) )
|
||||
meta.avgHashrate = data.avgHashrate;
|
||||
|
||||
if( !_.isEqual(meta.lastBlocksTime, data.blocktime) && data.blocktime.length >= MAX_BINS )
|
||||
meta.lastBlocksTime = data.blocktime;
|
||||
|
||||
if( !_.isEqual(meta.difficultyChart, data.difficulty) && data.difficulty.length >= MAX_BINS )
|
||||
meta.difficultyChart = data.difficulty;
|
||||
|
||||
if( !_.isEqual(meta.blockPropagationChart, data.propagation.histogram) ) {
|
||||
meta.blockPropagationChart = data.propagation.histogram;
|
||||
meta.blockPropagationAvg = data.propagation.avg;
|
||||
}
|
||||
|
||||
data.uncleCount.reverse();
|
||||
|
||||
if( !_.isEqual(meta.uncleCountChart, data.uncleCount) && data.uncleCount.length >= MAX_BINS ) {
|
||||
meta.uncleCount = data.uncleCount[data.uncleCount.length-2] + data.uncleCount[data.uncleCount.length-1];
|
||||
meta.uncleCountChart = data.uncleCount;
|
||||
}
|
||||
|
||||
if( !_.isEqual(meta.transactionDensity, data.transactions) && data.transactions.length >= MAX_BINS )
|
||||
meta.transactionDensity = data.transactions;
|
||||
|
||||
if( !_.isEqual(meta.gasSpending, data.gasSpending) && data.gasSpending.length >= MAX_BINS )
|
||||
meta.gasSpending = data.gasSpending;
|
||||
|
||||
if( !_.isEqual(meta.miners, data.miners) ) {
|
||||
meta.miners = data.miners;
|
||||
getMinersNames(meta);
|
||||
}
|
||||
|
||||
// update
|
||||
delete meta._id;
|
||||
Blockchain.update('meta', {$set: meta});
|
||||
|
||||
break;
|
||||
|
||||
case "inactive":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( foundNode )
|
||||
{
|
||||
if( !_.isUndefined(data.stats) ) {
|
||||
Nodes.update(data.id, {$set: {
|
||||
stats: data.stats
|
||||
}});
|
||||
}
|
||||
|
||||
toastr['error']("Node "+ foundNode.info.name +" went away!", "Node connection was lost!");
|
||||
|
||||
updateActiveNodes();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "latency":
|
||||
if( !_.isUndefined(data.id) && !_.isUndefined(data.latency) )
|
||||
{
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( foundNode )
|
||||
{
|
||||
|
||||
if( !_.isUndefined(foundNode) && !_.isUndefined(foundNode.stats) && !_.isUndefined(foundNode.stats.latency) && foundNode.stats.latency !== data.latency )
|
||||
{
|
||||
Nodes.update(data.id, {$set: {
|
||||
'stats.latency': data.latency
|
||||
}});
|
||||
|
||||
latencyFilter(foundNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "client-ping":
|
||||
socket.emit('client-pong', {
|
||||
serverTime: data.serverTime,
|
||||
clientTime: _.now()
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// $scope.$apply();
|
||||
}
|
||||
|
||||
|
||||
function getMinersNames(meta)
|
||||
{
|
||||
if( meta.miners.length > 0 )
|
||||
{
|
||||
_.forIn(meta.miners, function (value, key)
|
||||
{
|
||||
if(value.name !== false)
|
||||
return;
|
||||
|
||||
if(value.miner === "0x0000000000000000000000000000000000000000")
|
||||
return;
|
||||
|
||||
if(miner = Nodes.findOne({'info.coinbase': value.miner}))
|
||||
var name = miner.info.name;
|
||||
|
||||
if( !_.isUndefined(name) ) {
|
||||
meta.miners[key].name = name;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
function addNewNode(data)
|
||||
{
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( _.isUndefined(data.history) )
|
||||
{
|
||||
data.history = new Array(40);
|
||||
_.fill(data.history, -1);
|
||||
}
|
||||
|
||||
|
||||
data.pinned = ( !_.isUndefined(foundNode.pinned) ? foundNode.pinned : false);
|
||||
|
||||
if( !_.isUndefined(foundNode.history) )
|
||||
{
|
||||
data.history = foundNode.history;
|
||||
}
|
||||
|
||||
// update node
|
||||
Nodes.upsert(data.id, {$set: data});
|
||||
|
||||
addToMap(data);
|
||||
|
||||
updateActiveNodes();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function addToMap(data) {
|
||||
// add to map
|
||||
var bestblock = Blockchain.findOne().bestBlock;
|
||||
|
||||
if(!Map.findOne(data.id) && data.geo != null)
|
||||
Map.insert({
|
||||
_id: data.id,
|
||||
radius: 3,
|
||||
latitude: data.geo.ll[0],
|
||||
longitude: data.geo.ll[1],
|
||||
nodeName: data.info.name,
|
||||
fillClass: mainClass(data.stats, bestblock),
|
||||
fillKey: mainClass(data.stats, bestblock).replace('text-', ''),
|
||||
});
|
||||
}
|
||||
|
||||
function updateActiveNodes()
|
||||
{
|
||||
updateBestBlock();
|
||||
|
||||
var nodesTotal = Nodes.find().count(),
|
||||
nodesActive = 0,
|
||||
upTimeTotal = 0;
|
||||
|
||||
// iterate over all nodes to get the correct data
|
||||
_.each(Nodes.find().fetch(), function(node){
|
||||
|
||||
if(node.stats) {
|
||||
if(node.stats.active)
|
||||
nodesActive++
|
||||
|
||||
upTimeTotal += node.stats.uptime;
|
||||
}
|
||||
});
|
||||
|
||||
Blockchain.update('meta', {$set: {
|
||||
|
||||
nodesTotal: nodesTotal,
|
||||
nodesActive: nodesActive,
|
||||
upTimeTotal: upTimeTotal / nodesTotal
|
||||
}});
|
||||
}
|
||||
|
||||
function updateBestBlock()
|
||||
{
|
||||
if( Nodes.find().count() )
|
||||
{
|
||||
// var chains = {};
|
||||
// var maxScore = 0;
|
||||
|
||||
// _($scope.nodes)
|
||||
// .map(function (item)
|
||||
// {
|
||||
// maxScore += (item.trusted ? 50 : 1);
|
||||
|
||||
// if( _.isUndefined(chains[item.stats.block.number]) )
|
||||
// chains[item.stats.block.number] = [];
|
||||
|
||||
// if( _.isUndefined(chains[item.stats.block.number][item.stats.block.fork]) )
|
||||
// chains[item.stats.block.number][item.stats.block.fork] = {
|
||||
// fork: item.stats.block.fork,
|
||||
// count: 0,
|
||||
// trusted: 0,
|
||||
// score: 0
|
||||
// };
|
||||
|
||||
// if(item.stats.block.trusted)
|
||||
// chains[item.stats.block.number][item.stats.block.fork].trusted++;
|
||||
// else
|
||||
// chains[item.stats.block.number][item.stats.block.fork].count++;
|
||||
|
||||
// chains[item.stats.block.number][item.stats.block.fork].score = chains[item.stats.block.number][item.stats.block.fork].trusted * 50 + chains[item.stats.block.number][item.stats.block.fork].count;
|
||||
// })
|
||||
// .value();
|
||||
|
||||
// $scope.maxScore = maxScore;
|
||||
// $scope.chains = _.reduce(chains, function (result, item, key)
|
||||
// {
|
||||
// result[key] = _.max(item, 'score');
|
||||
// return result;
|
||||
// }, {});
|
||||
|
||||
var bestBlock = Nodes.findOne({'stats.block.number': {$exists: true}},{sort: {'stats.block.number': -1}});
|
||||
if( bestBlock && bestBlock.stats.block.number !== Blockchain.findOne().bestBlock )
|
||||
{
|
||||
console.log('bestblock', bestBlock.stats.block.number);
|
||||
|
||||
Blockchain.update('meta', {$set: {
|
||||
bestBlock: bestBlock.stats.block.number,
|
||||
bestStats: bestBlock.stats,
|
||||
lastBlock: bestBlock.stats.block.arrived,
|
||||
lastDifficulty: bestBlock.stats.block.difficulty
|
||||
}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// function forkFilter(node)
|
||||
// {
|
||||
// if( _.isUndefined(node.readable) )
|
||||
// node.readable = {};
|
||||
|
||||
// node.readable.forkClass = 'hidden';
|
||||
// node.readable.forkMessage = '';
|
||||
|
||||
// return true;
|
||||
|
||||
// if( $scope.chains[node.stats.block.number].fork === node.stats.block.fork && $scope.chains[node.stats.block.number].score / $scope.maxScore >= 0.5 )
|
||||
// {
|
||||
// node.readable.forkClass = 'hidden';
|
||||
// node.readable.forkMessage = '';
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// if( $scope.chains[node.stats.block.number].fork !== node.stats.block.fork )
|
||||
// {
|
||||
// node.readable.forkClass = 'text-danger';
|
||||
// node.readable.forkMessage = 'Wrong chain.<br/>This chain is a fork.';
|
||||
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if( $scope.chains[node.stats.block.number].score / $scope.maxScore < 0.5)
|
||||
// {
|
||||
// node.readable.forkClass = 'text-warning';
|
||||
// node.readable.forkMessage = 'May not be main chain.<br/>Waiting for more confirmations.';
|
||||
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
function latencyFilter(node)
|
||||
{
|
||||
// var set = {};
|
||||
// if( _.isUndefined(node.readable) )
|
||||
// set['node.readable'] = {};
|
||||
|
||||
// if( _.isUndefined(node.stats) ) {
|
||||
// set['readable.latencyClass'] = 'text-danger';
|
||||
// set['readable.latency'] = 'offline';
|
||||
// }
|
||||
|
||||
// if (node.stats.active === false)
|
||||
// {
|
||||
// set['readable.latencyClass'] = 'text-danger';
|
||||
// set['readable.latency'] = 'offline';
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (node.stats.latency <= 100)
|
||||
// set['readable.latencyClass'] = 'text-success';
|
||||
|
||||
// if (node.stats.latency > 100 && node.stats.latency <= 1000)
|
||||
// set['readable.latencyClass'] = 'text-warning';
|
||||
|
||||
// if (node.stats.latency > 1000)
|
||||
// set['readable.latencyClass'] = 'text-danger';
|
||||
|
||||
// set['readable.latency'] = node.stats.latency + ' ms';
|
||||
// }
|
||||
|
||||
// // update node
|
||||
// Nodes.upsert(node.id, {$set: set});
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,24 @@
|
||||
(function(){mainClass = function(node, bestBlock)
|
||||
{
|
||||
|
||||
if(!node)
|
||||
return;
|
||||
|
||||
if( ! node.active)
|
||||
return 'text-gray';
|
||||
|
||||
if(node.peers === 0)
|
||||
return 'text-danger';
|
||||
|
||||
return peerClass(node.peers, node.active);
|
||||
}
|
||||
|
||||
peerClass = function(peers, active)
|
||||
{
|
||||
if( ! active)
|
||||
return 'text-gray';
|
||||
|
||||
return (peers <= 1 ? 'text-danger' : (peers > 1 && peers < 4 ? 'text-warning' : 'text-success'));
|
||||
}
|
||||
|
||||
})();
|
||||
14
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/bootstrap.min.js
vendored
Normal file
3
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/d3.tip.min.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
(function(){d3.tip=function(){function t(t){v=d(t),w=v.createSVGPoint(),document.body.appendChild(x)}function e(){return"n"}function n(){return[0,0]}function r(){return" "}function o(){var t=y();return{top:t.n.y-x.offsetHeight,left:t.n.x-x.offsetWidth/2}}function l(){var t=y();return{top:t.s.y,left:t.s.x-x.offsetWidth/2}}function s(){var t=y();return{top:t.e.y-x.offsetHeight/2,left:t.e.x}}function f(){var t=y();return{top:t.w.y-x.offsetHeight/2,left:t.w.x-x.offsetWidth}}function i(){var t=y();return{top:t.nw.y-x.offsetHeight,left:t.nw.x-x.offsetWidth}}function u(){var t=y();return{top:t.ne.y-x.offsetHeight,left:t.ne.x}}function a(){var t=y();return{top:t.sw.y,left:t.sw.x-x.offsetWidth}}function c(){var t=y();return{top:t.se.y,left:t.e.x}}function p(){var t=d3.select(document.createElement("div"));return t.style({position:"absolute",opacity:0,pointerEvents:"none",boxSizing:"border-box"}),t.node()}function d(t){return t=t.node(),"svg"==t.tagName.toLowerCase()?t:t.ownerSVGElement}function y(){var t=T||d3.event.target,e={},n=t.getScreenCTM(),r=t.getBBox(),o=r.width,l=r.height,s=r.x,f=r.y,i=document.documentElement.scrollTop||document.body.scrollTop,u=document.documentElement.scrollLeft||document.body.scrollLeft;return w.x=s+u,w.y=f+i,e.nw=w.matrixTransform(n),w.x+=o,e.ne=w.matrixTransform(n),w.y+=l,e.se=w.matrixTransform(n),w.x-=o,e.sw=w.matrixTransform(n),w.y-=l/2,e.w=w.matrixTransform(n),w.x+=o,e.e=w.matrixTransform(n),w.x-=o/2,w.y-=l/2,e.n=w.matrixTransform(n),w.y+=l,e.s=w.matrixTransform(n),e}var m=e,g=n,h=r,x=p(),v=null,w=null,T=null;t.show=function(){var e=Array.prototype.slice.call(arguments);e[e.length-1]instanceof SVGElement&&(T=e.pop());var n,r=h.apply(this,e),o=g.apply(this,e),l=m.apply(this,e),s=d3.select(x),f=0;for(s.html(r).style({opacity:1,"pointer-events":"all"});f--;)s.classed(E[f],!1);return n=b.get(l).apply(this),s.classed(l,!0).style({top:n.top+o[0]+"px",left:n.left+o[1]+"px"}),t},t.hide=function(){return nodel=d3.select(x),nodel.style({opacity:0,"pointer-events":"none"}),t},t.attr=function(e){if(arguments.length<2&&"string"==typeof e)return d3.select(x).attr(e);var n=Array.prototype.slice.call(arguments);return d3.selection.prototype.attr.apply(d3.select(x),n),t},t.style=function(e){if(arguments.length<2&&"string"==typeof e)return d3.select(x).style(e);var n=Array.prototype.slice.call(arguments);return d3.selection.prototype.style.apply(d3.select(x),n),t},t.direction=function(e){return arguments.length?(m=null==e?e:d3.functor(e),t):m},t.offset=function(e){return arguments.length?(g=null==e?e:d3.functor(e),t):g},t.html=function(e){return arguments.length?(h=null==e?e:d3.functor(e),t):h};var b=d3.map({n:o,s:l,e:s,w:f,nw:i,ne:u,sw:a,se:c}),E=b.keys();return t};
|
||||
|
||||
})();
|
||||
4
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/datamaps.min.js
vendored
Normal file
7
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/jquery.sparkline.min.js
vendored
Normal file
3
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/moment.en.min.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
(function(){!function(e){"function"==typeof define&&define.amd?define(["moment"],e):"object"==typeof exports?module.exports=e(require("../moment")):e(("undefined"!=typeof global?global:this).moment)}(function(e){return e.defineLocale("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few sec",m:"1 min",mm:"%d min",h:"1 h",hh:"%d h",d:"a day",dd:"%d days",M:"a month",MM:"%d mon",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10,d=1===~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th";return e+d},week:{dow:1,doy:4}})});
|
||||
|
||||
})();
|
||||
9
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/moment.min.js
vendored
Normal file
3
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/primus.min.js
vendored
Normal file
3
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/toastr.min.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
(function(){!function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return f({type:O.error,iconClass:g().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=g()),v=e("#"+t.containerId),v.length?v:(n&&(v=c(t)),v)}function i(e,t,n){return f({type:O.info,iconClass:g().iconClasses.info,message:e,optionsOverride:n,title:t})}function o(e){w=e}function s(e,t,n){return f({type:O.success,iconClass:g().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return f({type:O.warning,iconClass:g().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e){var t=g();v||n(t),l(e,t)||u(t)}function d(t){var i=g();return v||n(i),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function u(t){for(var n=v.children(),i=n.length-1;i>=0;i--)l(e(n[i]),t)}function l(t,n){return t&&0===e(":focus",t).length?(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0):!1}function c(t){return v=e("<div/>").attr("id",t.containerId).addClass(t.positionClass).attr("aria-live","polite").attr("role","alert"),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",target:"body",closeHtml:"<button>×</button>",newestOnTop:!0,preventDuplicates:!1,progressBar:!1}}function m(e){w&&w(e)}function f(t){function i(t){return!e(":focus",l).length||t?(clearTimeout(O.intervalId),l[r.hideMethod]({duration:r.hideDuration,easing:r.hideEasing,complete:function(){h(l),r.onHidden&&"hidden"!==b.state&&r.onHidden(),b.state="hidden",b.endTime=new Date,m(b)}})):void 0}function o(){(r.timeOut>0||r.extendedTimeOut>0)&&(u=setTimeout(i,r.extendedTimeOut),O.maxHideTime=parseFloat(r.extendedTimeOut),O.hideEta=(new Date).getTime()+O.maxHideTime)}function s(){clearTimeout(u),O.hideEta=0,l.stop(!0,!0)[r.showMethod]({duration:r.showDuration,easing:r.showEasing})}function a(){var e=(O.hideEta-(new Date).getTime())/O.maxHideTime*100;f.width(e+"%")}var r=g(),d=t.iconClass||r.iconClass;if(r.preventDuplicates){if(t.message===C)return;C=t.message}"undefined"!=typeof t.optionsOverride&&(r=e.extend(r,t.optionsOverride),d=t.optionsOverride.iconClass||d),T++,v=n(r,!0);var u=null,l=e("<div/>"),c=e("<div/>"),p=e("<div/>"),f=e("<div/>"),w=e(r.closeHtml),O={intervalId:null,hideEta:null,maxHideTime:null},b={toastId:T,state:"visible",startTime:new Date,options:r,map:t};return t.iconClass&&l.addClass(r.toastClass).addClass(d),t.title&&(c.append(t.title).addClass(r.titleClass),l.append(c)),t.message&&(p.append(t.message).addClass(r.messageClass),l.append(p)),r.closeButton&&(w.addClass("toast-close-button").attr("role","button"),l.prepend(w)),r.progressBar&&(f.addClass("toast-progress"),l.prepend(f)),l.hide(),r.newestOnTop?v.prepend(l):v.append(l),l[r.showMethod]({duration:r.showDuration,easing:r.showEasing,complete:r.onShown}),r.timeOut>0&&(u=setTimeout(i,r.timeOut),O.maxHideTime=parseFloat(r.timeOut),O.hideEta=(new Date).getTime()+O.maxHideTime,r.progressBar&&(O.intervalId=setInterval(a,10))),l.hover(s,o),!r.onclick&&r.tapToDismiss&&l.click(i),r.closeButton&&w&&w.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),i(!0)}),r.onclick&&l.click(function(){r.onclick(),i()}),m(b),r.debug&&console&&console.log(b),l}function g(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&v.remove())}var v,w,C,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:d,error:t,getContainer:n,info:i,options:{},subscribe:o,success:s,version:"2.1.0",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)});
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,38 @@
|
||||
(function(){(function() {
|
||||
$('body').on('mouseenter', '[data-toggle="tooltip"]', function( event ) {
|
||||
$(this).tooltip('show');
|
||||
}).on('mouseleave', '[data-toggle="tooltip"]', function( event ) {
|
||||
$(this).tooltip('hide');
|
||||
});
|
||||
|
||||
$.fn.sparkline.defaults.bar.height = 63;
|
||||
$.fn.sparkline.defaults.bar.barWidth = 6;
|
||||
$.fn.sparkline.defaults.bar.barSpacing = 1;
|
||||
$.fn.sparkline.defaults.bar.tooltipClassname = 'jqstooltip';
|
||||
$.fn.sparkline.defaults.bar.tooltipOffsetX = 0;
|
||||
$.fn.sparkline.defaults.bar.tooltipFormat = $.spformat('<div class="tooltip-arrow"></div><div class="tooltip-inner">{{prefix}}{{value}} {{suffix}}</div>');
|
||||
$.fn.sparkline.defaults.bar.colorMap = $.range_map({
|
||||
'0:6': '#10a0de',
|
||||
'6:13': '#7bcc3a',
|
||||
'13:20': '#FFD162',
|
||||
'20:30': '#ff8a00',
|
||||
'30:': '#F74B4B'
|
||||
});
|
||||
|
||||
moment.relativeTimeThreshold('s', 60);
|
||||
moment.relativeTimeThreshold('m', 60);
|
||||
moment.relativeTimeThreshold('h', 24);
|
||||
moment.relativeTimeThreshold('d', 28);
|
||||
moment.relativeTimeThreshold('M', 12);
|
||||
|
||||
})();
|
||||
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-63657296-1', 'auto');
|
||||
ga('send', 'pageview');
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,649 @@
|
||||
(function(){
|
||||
function blockTimeClass(diff)
|
||||
{
|
||||
if(diff <= 13)
|
||||
return 'text-success';
|
||||
|
||||
if(diff <= 20)
|
||||
return 'text-warning';
|
||||
|
||||
if(diff <= 30)
|
||||
return 'text-orange';
|
||||
|
||||
return 'text-danger'
|
||||
}
|
||||
|
||||
function timeClass(timestamp)
|
||||
{
|
||||
var diff = ((new Date()).getTime() - timestamp)/1000;
|
||||
|
||||
return blockTimeClass(diff);
|
||||
}
|
||||
|
||||
function compareVersions(v1, comparator, v2)
|
||||
{
|
||||
comparator = comparator == '=' ? '==' : comparator;
|
||||
|
||||
var v1parts = v1.split('.'), v2parts = v2.split('.');
|
||||
var maxLen = Math.max(v1parts.length, v2parts.length);
|
||||
var part1, part2;
|
||||
var cmp = 0;
|
||||
|
||||
for(var i = 0; i < maxLen && !cmp; i++)
|
||||
{
|
||||
part1 = parseInt(v1parts[i], 10) || 0;
|
||||
part2 = parseInt(v2parts[i], 10) || 0;
|
||||
if(part1 < part2)
|
||||
cmp = 1;
|
||||
if(part1 > part2)
|
||||
cmp = -1;
|
||||
}
|
||||
|
||||
return eval('0' + comparator + cmp);
|
||||
}
|
||||
|
||||
function mainClass(node, bestBlock)
|
||||
{
|
||||
|
||||
if(!node)
|
||||
return;
|
||||
|
||||
if( ! node.active)
|
||||
return 'text-gray';
|
||||
|
||||
if(node.peers === 0)
|
||||
return 'text-danger';
|
||||
|
||||
return peerClass(node.peers, node.active);
|
||||
}
|
||||
|
||||
function peerClass(peers, active)
|
||||
{
|
||||
if( ! active)
|
||||
return 'text-gray';
|
||||
|
||||
return (peers <= 1 ? 'text-danger' : (peers > 1 && peers < 4 ? 'text-warning' : 'text-success'));
|
||||
}
|
||||
|
||||
|
||||
function blockTimeClass(diff)
|
||||
{
|
||||
if(diff <= 13)
|
||||
return 'text-success';
|
||||
|
||||
if(diff <= 20)
|
||||
return 'text-warning';
|
||||
|
||||
if(diff <= 30)
|
||||
return 'text-orange';
|
||||
|
||||
return 'text-danger'
|
||||
}
|
||||
|
||||
|
||||
// global template helpers
|
||||
|
||||
Template.registerHelper('Blockchain', function(){
|
||||
return Blockchain.findOne('meta');
|
||||
});
|
||||
|
||||
Template.registerHelper('nodes', function(uptime) {
|
||||
return Nodes.find({},{sort: {'stats.block.number': -1, 'stats.active': -1}});
|
||||
});
|
||||
|
||||
Template.registerHelper('number', function(number){
|
||||
return numeral(number).format('0,0');
|
||||
});
|
||||
|
||||
Template.registerHelper('avgTimeClass', function(time){
|
||||
return blockTimeClass(time);
|
||||
});
|
||||
|
||||
Template.registerHelper('blockTimeFilter', function(timestamp){
|
||||
if(timestamp === 0)
|
||||
return '∞';
|
||||
|
||||
// var time = Math.floor((new Date()).getTime() / 1000);
|
||||
var time = (new Date()).getTime();
|
||||
var diff = Math.floor((time - timestamp)/1000);
|
||||
|
||||
if(diff < 60)
|
||||
return Math.round(diff) + ' s ago';
|
||||
|
||||
return moment.duration(Math.round(diff), 's').humanize() + ' ago';
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('timeClass', function(timestamp, active){
|
||||
if( _.isBoolean(active) && ! active)
|
||||
return 'text-gray';
|
||||
|
||||
return timeClass(timestamp);
|
||||
});
|
||||
|
||||
Template.registerHelper('avgTimeFilter', function(time){
|
||||
if(time < 60)
|
||||
return parseFloat(time).toFixed(2) + ' s';
|
||||
|
||||
return moment.duration(Math.round(time), 's').humanize();
|
||||
});
|
||||
|
||||
Template.registerHelper('networkHashrateFilter', function(hashes, isMining){
|
||||
if(hashes === null)
|
||||
hashes = 0;
|
||||
|
||||
var result = 0;
|
||||
var unit = 'K';
|
||||
|
||||
if(hashes !== 0 && hashes < 1000) {
|
||||
result = hashes;
|
||||
unit = '';
|
||||
}
|
||||
|
||||
if(hashes >= 1000 && hashes < Math.pow(1000, 2)) {
|
||||
result = hashes / 1000;
|
||||
unit = 'K';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 2) && hashes < Math.pow(1000, 3)) {
|
||||
result = hashes / Math.pow(1000, 2);
|
||||
unit = 'M';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 3) && hashes < Math.pow(1000, 4)) {
|
||||
result = hashes / Math.pow(1000, 3);
|
||||
unit = 'G';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 4) && hashes < Math.pow(1000, 5)) {
|
||||
result = hashes / Math.pow(1000, 4);
|
||||
unit = 'T';
|
||||
}
|
||||
|
||||
if( !isMining )
|
||||
return new Spacebars.SafeString(result.toFixed(1) + ' <span class="small-hash">' + unit + 'H/s</span>');
|
||||
|
||||
return new Spacebars.SafeString('? <span class="small-hash">' + unit + 'KH/s</span>');
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('nodesActiveClass', function(active, total) {
|
||||
var ratio = active/total;
|
||||
|
||||
if(ratio >= 0.9)
|
||||
return 'text-success';
|
||||
|
||||
if(ratio >= 0.75)
|
||||
return 'text-info';
|
||||
|
||||
if(ratio >= 0.5)
|
||||
return 'text-warning';
|
||||
|
||||
return 'text-danger';
|
||||
});
|
||||
|
||||
Template.registerHelper('gasPriceFilter', function(price) {
|
||||
if(typeof price === 'undefined')
|
||||
return "0 wei";
|
||||
|
||||
if(price.length < 4)
|
||||
return numeral(price).format('0,0') + " wei";
|
||||
|
||||
if(price.length < 7)
|
||||
return numeral(price/1000).format('0,0') + " kwei";
|
||||
|
||||
if(price.length < 10)
|
||||
return numeral(price/1000000).format('0,0') + " mwei";
|
||||
|
||||
if(price.length < 13)
|
||||
return numeral(price/1000000000).format('0,0') + " gwei";
|
||||
|
||||
if(price.length < 16)
|
||||
return numeral(price/1000000000000).format('0,0') + " szabo";
|
||||
|
||||
if(price.length < 19)
|
||||
return numeral(price.substr(0, price.length - 15)).format('0,0') + " finney";
|
||||
|
||||
return numeral(price.substr(0, price.length - 18)).format('0,0') + " ether";
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('upTimeFilter', function(uptime) {
|
||||
return Math.round(uptime) + '%';
|
||||
});
|
||||
|
||||
Template.registerHelper('propagationAvgTimeClass', function(propagationAvg, active) {
|
||||
if( ! active)
|
||||
return 'text-gray';
|
||||
|
||||
if(propagationAvg == 0)
|
||||
return 'text-info';
|
||||
|
||||
if(propagationAvg < 1000)
|
||||
return 'text-success';
|
||||
|
||||
if(propagationAvg < 3000)
|
||||
return 'text-warning';
|
||||
|
||||
if(propagationAvg < 7000)
|
||||
return 'text-orange';
|
||||
|
||||
return 'text-danger'
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('minerBlocksClass', function(blocks, prefix) {
|
||||
if(typeof prefix === 'undefined')
|
||||
prefix = 'bg-';
|
||||
if(blocks <= 6)
|
||||
return prefix + 'success';
|
||||
|
||||
if(blocks <= 12)
|
||||
return prefix + 'info';
|
||||
|
||||
if(blocks <= 18)
|
||||
return prefix + 'warning';
|
||||
|
||||
return prefix + 'danger';
|
||||
});
|
||||
|
||||
Template.registerHelper('latencyClass', function(active, latency) {
|
||||
if(active === false)
|
||||
return 'text-danger';
|
||||
|
||||
if(latency <= 100)
|
||||
return 'text-success';
|
||||
|
||||
if(latency <= 1000)
|
||||
return 'text-warning';
|
||||
|
||||
return 'text-danger'
|
||||
});
|
||||
|
||||
Template.registerHelper('upTimeClass', function(uptime, active) {
|
||||
if( active === false )
|
||||
return 'text-gray';
|
||||
|
||||
if(uptime >= 90)
|
||||
return 'text-success';
|
||||
|
||||
if(uptime >= 75)
|
||||
return 'text-warning';
|
||||
|
||||
return 'text-danger';
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('nodePinClass', function(pinned) {
|
||||
if(pinned)
|
||||
return 'icon-check-o';
|
||||
|
||||
return 'icon-loader';
|
||||
});
|
||||
|
||||
Template.registerHelper('mainClass', function(node, bestBlock) {
|
||||
return mainClass(node, bestBlock);
|
||||
});
|
||||
|
||||
Template.registerHelper('peerClass', function(peers, active) {
|
||||
return peerClass(peers, active);
|
||||
});
|
||||
|
||||
Template.registerHelper('miningClass', function(mining, active) {
|
||||
if(! active)
|
||||
return 'text-gray';
|
||||
|
||||
return (! mining ? 'text-danger' : 'text-success');
|
||||
});
|
||||
|
||||
Template.registerHelper('miningIconClass', function(mining) {
|
||||
return (! mining ? 'icon-cancel' : 'icon-check');
|
||||
});
|
||||
|
||||
Template.registerHelper('hashrateClass', function(mining, active) {
|
||||
if(! mining || ! active)
|
||||
return 'text-gray';
|
||||
|
||||
return 'text-success';
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('nodeClientClass', function(info, current) {
|
||||
if(typeof info === 'undefined' || typeof info.client === 'undefined' || typeof info.client === '')
|
||||
return 'text-danger';
|
||||
|
||||
if(compareVersions(info.client, '<', current))
|
||||
return 'text-danger';
|
||||
|
||||
return 'hidden';
|
||||
})
|
||||
|
||||
Template.registerHelper('consensusClass', function(nodes, bestBlock) {
|
||||
var status = 'success';
|
||||
var now = _.now();
|
||||
|
||||
for(var x = 0; x < nodes.length; x++)
|
||||
{
|
||||
if(nodes[x].stats.block.number === bestBlock.number && nodes[x].stats.block.hash !== bestBlock.hash)
|
||||
return 'danger';
|
||||
|
||||
if((bestBlock.number - nodes[x].stats.block.number) > 1 && (now - bestBlock.received) >= 20*1000)
|
||||
status = 'orange';
|
||||
|
||||
if((bestBlock.number - nodes[x].stats.block.number) === 1 && (now - bestBlock.received) >= 10*1000 && status !== 'orange')
|
||||
status = 'warning';
|
||||
}
|
||||
|
||||
return status;
|
||||
});
|
||||
|
||||
Template.registerHelper('consensusFilter', function(nodes, bestBlock) {
|
||||
var cnt = 0;
|
||||
|
||||
for(var x = 0; x < nodes.length; x++)
|
||||
{
|
||||
if(nodes[x].stats.block.number === bestBlock.number && nodes[x].stats.block.hash === bestBlock.hash)
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return cnt + '/' + nodes.length;
|
||||
});
|
||||
|
||||
Template.registerHelper('geoTooltip', function(node) {
|
||||
var tooltip = [];
|
||||
var string = '';
|
||||
|
||||
if(!node.info)
|
||||
return;
|
||||
|
||||
if(node.info.node !== '' && typeof node.info.node !== 'undefined') {
|
||||
var eth_version = node.info.node.split('/');
|
||||
|
||||
if(eth_version[1][0] !== 'v' && eth_version[1][2] !== '.')
|
||||
{
|
||||
eth_version.splice(1,1);
|
||||
}
|
||||
|
||||
string = "<b>" + node.info.node + "</b>";
|
||||
tooltip.push(string);
|
||||
|
||||
string = "Version: <b>" + (eth_version[1]) + "</b>";
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.net !== '') {
|
||||
string = "Network: <b>" + (typeof node.info.net !== 'undefined' ? node.info.net : '-') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.protocol !== '') {
|
||||
string = "Protocol: <b>" + (typeof node.info.protocol !== 'undefined' ? node.info.protocol : '-') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.port !== '') {
|
||||
string = "Port: <b>" + (typeof node.info.port !== 'undefined' ? node.info.port : '30303') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.api !== '') {
|
||||
string = "Web3: <b>" + node.info.api + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.client !== '') {
|
||||
string = "API: <b>" + (typeof node.info.client !== 'undefined' ? node.info.client : '<= 0.0.3') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.os !== '') {
|
||||
string = "OS: <b>" + (typeof node.info.os !== 'undefined' ? node.info.os + ' ' + node.info.os_v : '?') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.geo !== null)
|
||||
{
|
||||
string = "Location: <b>";
|
||||
|
||||
if(node.geo.city !== '')
|
||||
string += node.geo.city + ", ";
|
||||
string += node.geo.country + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.contact !== '') {
|
||||
string = "Contact: <b>" + (typeof node.info.contact !== 'undefined' ? node.info.contact : '-') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
return tooltip.join("<br>");
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('bubbleClass', function(node, bestBlock) {
|
||||
return mainClass(node, bestBlock).replace('text-', '');
|
||||
});
|
||||
|
||||
Template.registerHelper('minerNameFilter', function(address, name) {
|
||||
if(typeof name !== 'undefined' && name !== false && name.length > 0)
|
||||
return name;
|
||||
|
||||
return address.replace('0x', '');
|
||||
});
|
||||
|
||||
Template.registerHelper('blockPropagationFilter', function(ms, prefix) {
|
||||
if(!prefix)
|
||||
prefix = '+';
|
||||
|
||||
var result = 0;
|
||||
|
||||
if(ms < 1000) {
|
||||
return (ms === 0 ? "" : prefix) + ms + " ms";
|
||||
}
|
||||
|
||||
if(ms < 1000*60) {
|
||||
result = ms/1000;
|
||||
return prefix + result.toFixed(1) + " s";
|
||||
}
|
||||
|
||||
if(ms < 1000*60*60) {
|
||||
result = ms/1000/60;
|
||||
return prefix + Math.round(result) + " min";
|
||||
}
|
||||
|
||||
if(ms < 1000*60*60*24) {
|
||||
result = ms/1000/60/60;
|
||||
return prefix + Math.round(result) + " h";
|
||||
}
|
||||
|
||||
result = ms/1000/60/60/24;
|
||||
return prefix + Math.round(result) + " days";
|
||||
});
|
||||
|
||||
Template.registerHelper('blockPropagationAvgFilter', function(stats, bestBlock) {
|
||||
if(!stats)
|
||||
return;
|
||||
|
||||
var ms = stats.propagationAvg;
|
||||
|
||||
if(bestBlock - stats.block.number > 40)
|
||||
return "∞";
|
||||
//ms = _.now() - stats.block.received;
|
||||
|
||||
prefix = '';
|
||||
|
||||
var result = 0;
|
||||
|
||||
if(ms < 1000) {
|
||||
return (ms === 0 ? "" : prefix) + ms + " ms";
|
||||
}
|
||||
|
||||
if(ms < 1000*60) {
|
||||
result = ms/1000;
|
||||
return prefix + result.toFixed(1) + " s";
|
||||
}
|
||||
|
||||
if(ms < 1000*60*60) {
|
||||
result = ms/1000/60;
|
||||
return prefix + Math.round(result) + " min";
|
||||
}
|
||||
|
||||
if(ms < 1000*60*60*24) {
|
||||
result = ms/1000/60/60;
|
||||
return prefix + Math.round(result) + " h";
|
||||
}
|
||||
|
||||
result = ms/1000/60/60/24;
|
||||
return prefix + Math.round(result) + " days";
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('propagationTimeClass', function(stats, bestBlock) {
|
||||
if( ! stats.active)
|
||||
return 'text-gray';
|
||||
|
||||
if(stats.block.number < bestBlock)
|
||||
return 'text-gray';
|
||||
|
||||
if(stats.block.propagation == 0)
|
||||
return 'text-info';
|
||||
|
||||
if(stats.block.propagation < 1000)
|
||||
return 'text-success';
|
||||
|
||||
if(stats.block.propagation < 3000)
|
||||
return 'text-warning';
|
||||
|
||||
if(stats.block.propagation < 7000)
|
||||
return 'text-orange';
|
||||
|
||||
return 'text-danger'
|
||||
});
|
||||
|
||||
Template.registerHelper('propagationNodeAvgTimeClass', function(stats, bestBlock) {
|
||||
if(!stats)
|
||||
return;
|
||||
|
||||
if( ! stats.active)
|
||||
return 'text-gray';
|
||||
|
||||
if(stats.block.number < bestBlock)
|
||||
return 'text-gray';
|
||||
|
||||
|
||||
if(stats.propagationAvg == 0)
|
||||
return 'text-info';
|
||||
|
||||
if(stats.propagationAvg < 1000)
|
||||
return 'text-success';
|
||||
|
||||
if(stats.propagationAvg < 3000)
|
||||
return 'text-warning';
|
||||
|
||||
if(stats.propagationAvg < 7000)
|
||||
return 'text-orange';
|
||||
|
||||
return 'text-danger'
|
||||
});
|
||||
|
||||
Template.registerHelper('hashrateFilter', function(hashes, isMining) {
|
||||
var result = 0;
|
||||
var unit = 'K';
|
||||
|
||||
if( !isMining )
|
||||
return new Spacebars.SafeString('<i class="icon-cancel"></i>');
|
||||
|
||||
if(hashes !== 0 && hashes < 1000) {
|
||||
result = hashes;
|
||||
unit = '';
|
||||
}
|
||||
|
||||
if(hashes >= 1000 && hashes < Math.pow(1000, 2)) {
|
||||
result = hashes / 1000;
|
||||
unit = 'K';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 2) && hashes < Math.pow(1000, 3)) {
|
||||
result = hashes / Math.pow(1000, 2);
|
||||
unit = 'M';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 3) && hashes < Math.pow(1000, 4)) {
|
||||
result = hashes / Math.pow(1000, 3);
|
||||
unit = 'G';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 4) && hashes < Math.pow(1000, 5)) {
|
||||
result = hashes / Math.pow(1000, 4);
|
||||
unit = 'T';
|
||||
}
|
||||
|
||||
return new Spacebars.SafeString('<span class="small">' + numeral(result).format('0,0') + ' <span class="small-hash">' + unit + 'H/s</span></span>');
|
||||
});
|
||||
|
||||
Template.registerHelper('nodeVersion', function(version) {
|
||||
if(typeof version !== 'undefined')
|
||||
{
|
||||
var tmp = version.split('/');
|
||||
|
||||
tmp[0] = tmp[0].replace('Ethereum(++)', 'Eth');
|
||||
|
||||
if(tmp[0].indexOf('pyethapp') === 0)
|
||||
{
|
||||
tmp[0] = 'pyeth';
|
||||
}
|
||||
|
||||
if(tmp[1][0] !== 'v' && tmp[1][2] !== '.')
|
||||
{
|
||||
tmp.splice(1,1);
|
||||
}
|
||||
|
||||
if(tmp[2] === 'Release'){
|
||||
tmp.splice(2,1);
|
||||
}
|
||||
|
||||
if(tmp[2].indexOf('Linux') === 0)
|
||||
tmp[2] = 'linux';
|
||||
|
||||
if(tmp[2].indexOf('Darwin') === 0)
|
||||
tmp[2] = 'darwin';
|
||||
|
||||
return new Spacebars.SafeString(tmp.join('/'));
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
|
||||
Template.registerHelper('blockClass', function(current, best) {
|
||||
if(!current)
|
||||
return;
|
||||
|
||||
if( ! current.active)
|
||||
return 'text-gray';
|
||||
|
||||
return (best - current.block.number < 1 ? 'text-success' : (best - current.block.number === 1 ? 'text-warning' : (best - current.block.number > 1 && best - current.block.number < 4 ? 'text-orange' : 'text-danger')));
|
||||
});
|
||||
|
||||
Template.registerHelper('gasFilter', function(gas) {
|
||||
return (typeof gas !== 'undefined' ? parseInt(gas) : '?');
|
||||
});
|
||||
|
||||
Template.registerHelper('hashFilter', function(hash) {
|
||||
if(typeof hash === 'undefined')
|
||||
return "?";
|
||||
|
||||
if(hash.substr(0,2) === '0x')
|
||||
hash = hash.substr(2,64);
|
||||
|
||||
return hash.substr(0, 8) + '...' + hash.substr(56, 8);
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,14 @@
|
||||
(function(){
|
||||
Template.__checkName("error");
|
||||
Template["error"] = new Template("Template.error", (function() {
|
||||
var view = this;
|
||||
return [ HTML.H1(Blaze.View("lookup:message", function() {
|
||||
return Spacebars.mustache(view.lookup("message"));
|
||||
})), HTML.H2(Blaze.View("lookup:error.status", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("error"), "status"));
|
||||
})), HTML.PRE(Blaze.View("lookup:error.stack", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("error"), "stack"));
|
||||
})) ];
|
||||
}));
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,515 @@
|
||||
(function(){
|
||||
Template.__checkName("index");
|
||||
Template["index"] = new Template("Template.index", (function() {
|
||||
var view = this;
|
||||
return HTML.DIV({
|
||||
"class": "container-fluid",
|
||||
"ng-controller": "StatsCtrl"
|
||||
}, HTML.DIV({
|
||||
"class": "row"
|
||||
}, HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "bestblock", " ", "text-info" ]
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-block"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">best block</span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}))), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "uncleCount", " ", "text-info" ]
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-uncle"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">uncles \n<span class="small">(current / last 50)</span></span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:Blockchain.bestStats.block.uncles.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "bestStats", "block", "uncles", "length"));
|
||||
}), "/", Blaze.View("lookup:Blockchain.uncleCount", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "uncleCount"));
|
||||
}))), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info", " ", "blocktime", " ", Spacebars.mustache(view.lookup("timeClass"), view.lookup("lastBlock"), true) ];
|
||||
}
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-time"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">last block</span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:blockTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockTimeFilter"), Spacebars.dot(view.lookup("Blockchain"), "lastBlock"));
|
||||
})), "\n", ""), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info", " ", "avgblocktime", " ", Spacebars.mustache(view.lookup("avgTimeClass"), view.lookup("avgBlockTime")) ];
|
||||
}
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-gas"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">avg block time</span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:avgTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("avgTimeFilter"), Spacebars.dot(view.lookup("Blockchain"), "avgBlockTime"));
|
||||
}))), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "difficulty", " ", "text-orange" ]
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-hashrate"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">avg network hashrate</span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:networkHashrateFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("networkHashrateFilter"), Spacebars.dot(view.lookup("Blockchain"), "avgHashrate"), false);
|
||||
}))), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "difficulty", " ", "text-danger" ]
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-difficulty"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">difficulty</span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-hash"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("Blockchain"), "lastDifficulty"));
|
||||
})))), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.Raw('<div class="clearfix"></div>')), "\n", HTML.DIV({
|
||||
"class": "row"
|
||||
}, HTML.DIV({
|
||||
"class": [ "col-xs-8", " ", "stats-boxes" ],
|
||||
style: "padding-top: 0px;"
|
||||
}, HTML.DIV({
|
||||
"class": [ "row", " ", "second-row" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "box" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "active-nodes", " ", Spacebars.mustache(view.lookup("nodesActiveClass"), Spacebars.dot(view.lookup("Blockchain"), "nodesActive"), Spacebars.dot(view.lookup("Blockchain"), "nodesTotal")) ];
|
||||
}
|
||||
}, HTML.Raw('<i class="icon-node"></i>'), "\n", HTML.Raw('<span class="small-title">active nodes</span>'), "\n", HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:Blockchain.nodesActive", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "nodesActive"));
|
||||
}), "/", Blaze.View("lookup:Blockchain.nodesTotal", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "nodesTotal"));
|
||||
})))), "\n", "", "\n", "", "\n", "", "\n", "", "\n", "", "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "box" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "gasprice", " ", "text-info" ]
|
||||
}, HTML.Raw('<i class="icon-gasprice"></i>'), "\n", HTML.Raw('<span class="small-title">gas price</span>'), "\n", HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:gasPriceFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("gasPriceFilter"), Spacebars.dot(view.lookup("Blockchain"), "bestStats", "gasPrice", "toString"));
|
||||
})))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "box" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "page-latency", " ", Spacebars.mustache(view.lookup("latencyClass"), true, Spacebars.dot(view.lookup("Blockchain"), "latency")) ];
|
||||
}
|
||||
}, HTML.Raw('<i class="icon-clock"></i>'), "\n", HTML.Raw('<span class="small-title">page latency</span>'), "\n", HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:Blockchain.latency", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "latency"));
|
||||
}), " ms"))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "box" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "uptime", " ", Spacebars.mustache(view.lookup("upTimeClass"), view.lookup("upTimeTotal"), true) ];
|
||||
}
|
||||
}, HTML.Raw('<i class="icon-bulb"></i>'), "\n", HTML.Raw('<span class="small-title">uptime</span>'), "\n", HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:upTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeFilter"), Spacebars.dot(view.lookup("Blockchain"), "upTimeTotal"));
|
||||
}))))), "\n", HTML.DIV({
|
||||
"class": "row"
|
||||
}, HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info", " ", "chart", " ", Spacebars.mustache(view.lookup("avgTimeClass"), Spacebars.dot(view.lookup("Blockchain"), "avgBlockTime")) ];
|
||||
}
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">block time</span>'), "\n", "", "\n", HTML.getTag("sparkchart")({
|
||||
"class": [ "big-details", " ", "spark-blocktimes" ],
|
||||
data: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "lastBlocksTime", "join"));
|
||||
},
|
||||
tooltipsuffix: "s"
|
||||
}))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "chart", " ", "text-info" ]
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">difficulty</span>'), "\n", "", "\n", HTML.getTag("sparkchart")({
|
||||
"class": [ "big-details", " ", "spark-difficulty" ],
|
||||
data: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "difficultyChart", "join"));
|
||||
}
|
||||
}))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "xpull-right" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info", " ", "chart", " ", "xdouble-chart", " ", Spacebars.mustache(view.lookup("propagationAvgTimeClass"), Spacebars.dot(view.lookup("Blockchain"), "blockPropagationAvg"), true) ];
|
||||
}
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">block propagation</span>'), "\n", "", "\n", HTML.getTag("histogram")({
|
||||
"class": [ "big-details", " ", "d3-blockpropagation" ],
|
||||
data: "blockPropagationChart"
|
||||
}))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "pull-right" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "chart", " ", "double-chart" ]
|
||||
}, HTML.Raw('<span class="small-title">last blocks miners</span>'), "\n", HTML.DIV({
|
||||
"class": "blocks-holder",
|
||||
"ng-repeat": "miner in miners track by miner.miner",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "right",
|
||||
"data-original-title": function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "miner", "blocks"));
|
||||
}
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "block-count", " ", Spacebars.mustache(view.lookup("minerBlocksClass"), Spacebars.dot(view.lookup("Blockchain"), "miner", "blocks"), "text-") ];
|
||||
}
|
||||
}, Blaze.View("lookup:miner.blocks", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("miner"), "blocks"));
|
||||
})), "\n", "", "\n", HTML.DIV({
|
||||
"class": "small-title-miner"
|
||||
}, Blaze.View("lookup:miner.miner", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("miner"), "miner"));
|
||||
})), "\n", HTML.getTag("minerblock")({
|
||||
blocks: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "miner", "blocks"));
|
||||
}
|
||||
}), "\n", HTML.Raw('<div class="clearfix"></div>')))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "chart", " ", "text-info" ]
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">uncle count \n<span class="small">(25 blocks per bar)</span></span>'), "\n", "", "\n", HTML.getTag("sparkchart")({
|
||||
"class": [ "big-details", " ", "spark-uncles" ],
|
||||
data: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "uncleCountChart", "join"));
|
||||
}
|
||||
}))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "chart", " ", "text-info" ]
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">transactions</span>'), "\n", HTML.getTag("sparkchart")({
|
||||
"class": [ "big-details", " ", "spark-transactions" ],
|
||||
data: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "transactionDensity"));
|
||||
}
|
||||
}))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "chart", " ", "text-info" ]
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">gas spending</span>'), "\n", HTML.getTag("sparkchart")({
|
||||
"class": [ "big-details", " ", "spark-gasspending" ],
|
||||
data: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "gasSpending", "join"));
|
||||
}
|
||||
}))))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-4", " ", "stat-holder", " ", "map-holder" ]
|
||||
}, "", "\n", HTML.getTag("nodemap")({
|
||||
id: "mapHolder",
|
||||
data: "map"
|
||||
})), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-12", " ", "stats-boxes" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "row", " ", "second-row" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "col-xs-12", " ", "stat-holder", " ", "box" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "active-nodes", " ", "text-orange" ]
|
||||
}, HTML.Raw('<i class="icon-hashrate"></i>'), "\n", HTML.Raw('<span class="small-title">Block #1028201 hash</span>'), "\n", HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:Blockchain.frontierHash", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "frontierHash"));
|
||||
})))))), "\n", HTML.Raw('<div class="clearfix"></div>')), "\n", HTML.DIV({
|
||||
"class": "row",
|
||||
style: "padding-top: 10px"
|
||||
}, HTML.TABLE({
|
||||
"class": [ "table", " ", "table-striped" ]
|
||||
}, HTML.THEAD(HTML.TR({
|
||||
"class": "text-info"
|
||||
}, HTML.TH({
|
||||
"class": "th-nodecheck"
|
||||
}, HTML.I({
|
||||
"class": "icon-check-o",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Pin nodes to display first",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-nodename"
|
||||
}, HTML.I({
|
||||
"class": "icon-node",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node name",
|
||||
"ng-click": "orderTable(['info.name'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-nodetype"
|
||||
}, HTML.I({
|
||||
"class": "icon-laptop",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node type",
|
||||
"ng-click": "orderTable(['info.node'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-latency"
|
||||
}, HTML.I({
|
||||
"class": "icon-clock",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node latency",
|
||||
"ng-click": "orderTable(['stats.latency'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-mining",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Is mining",
|
||||
"ng-click": "orderTable(['-stats.hashrate'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-group",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Peers",
|
||||
"ng-click": "orderTable(['-stats.peers'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-network",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Pending transactions",
|
||||
"ng-click": "orderTable(['-stats.pending'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-block",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Last block",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-blockhash"
|
||||
}, HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-blockhash"
|
||||
}, HTML.I({
|
||||
"class": "icon-difficulty",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Total difficulty",
|
||||
"ng-click": "orderTable(['-stats.block.totalDifficulty'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-check-o",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Block transactions",
|
||||
"ng-click": "orderTable(['-stats.block.transactions.length'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-uncle",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Uncles",
|
||||
"ng-click": "orderTable(['-stats.block.uncles.length'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-blocktime"
|
||||
}, HTML.I({
|
||||
"class": "icon-time",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Last block time",
|
||||
"ng-click": "orderTable(['-stats.block.received'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-peerPropagationTime"
|
||||
}, HTML.I({
|
||||
"class": "icon-gas",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Propagation time",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-peerPropagationChart"
|
||||
}), "\n", HTML.TH({
|
||||
"class": "th-peerPropagationAvg"
|
||||
}, HTML.I({
|
||||
"class": "icon-gas",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Average propagation time",
|
||||
"ng-click": "orderTable(['stats.propagationAvg'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-bulb",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Up-time",
|
||||
"ng-click": "orderTable(['-stats.uptime'], false)"
|
||||
})))), "\n", HTML.TBODY(Blaze.Each(function() {
|
||||
return Spacebars.call(view.lookup("nodes"));
|
||||
}, function() {
|
||||
return HTML.TR({
|
||||
"ng-repeat": "node in nodes | orderBy:predicate track by node.id",
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("mainClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
},
|
||||
id: function() {
|
||||
return [ "node_", Spacebars.mustache(view.lookup("id")) ];
|
||||
}
|
||||
}, HTML.TD({
|
||||
"class": "td-nodecheck"
|
||||
}, HTML.I({
|
||||
"ng-click": "pinNode(id)",
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("nodePinClass"), view.lookup("pinned"));
|
||||
},
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "right",
|
||||
"data-original-title": function() {
|
||||
return [ "Click to ", Blaze.If(function() {
|
||||
return Spacebars.call(view.lookup("pinned"));
|
||||
}, function() {
|
||||
return "'un'";
|
||||
}, function() {
|
||||
return "''";
|
||||
}), "pin" ];
|
||||
}
|
||||
})), "\n", HTML.TD({
|
||||
"class": "nodeInfo",
|
||||
rel: function() {
|
||||
return Spacebars.mustache(view.lookup("id"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
"data-html": "true",
|
||||
"data-original-title": function() {
|
||||
return Spacebars.mustache(view.lookup("geoTooltip"), view.lookup("."));
|
||||
}
|
||||
}, Blaze.View("lookup:info.name", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("info"), "name"));
|
||||
})), "\n", HTML.SPAN({
|
||||
"class": "small"
|
||||
}, HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
}), "(", Blaze.View("lookup:info.ip", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("info"), "ip"));
|
||||
}), ")"), "\n", HTML.A({
|
||||
"class": function() {
|
||||
return [ "small", " ", Spacebars.mustache(view.lookup("nodeClientClass"), view.lookup("info"), Spacebars.dot(view.lookup("Blockchain"), "currentApiVersion")) ];
|
||||
},
|
||||
href: "https://github.com/ethereum/wiki/wiki/Network-Status#updating",
|
||||
target: "_blank",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
"data-html": "true",
|
||||
"data-original-title": "Netstats client needs update.<br>Click this icon for instructions."
|
||||
}, HTML.I({
|
||||
"class": "icon-warning-o"
|
||||
}))), "\n", HTML.TD(HTML.DIV({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:nodeVersion", function() {
|
||||
return Spacebars.mustache(view.lookup("nodeVersion"), Spacebars.dot(view.lookup("info"), "node"));
|
||||
}))), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "latencyClass"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:readable.latency", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "latency"));
|
||||
}))), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("hashrateClass"), Spacebars.dot(view.lookup("stats"), "mining"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:hashrateFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("hashrateFilter"), Spacebars.dot(view.lookup("stats"), "hashrate"), Spacebars.dot(view.lookup("stats"), "mining"));
|
||||
})), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("peerClass"), Spacebars.dot(view.lookup("stats"), "peers"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
},
|
||||
style: "padding-left: 11px;"
|
||||
}, Blaze.View("lookup:stats.peers", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "peers"));
|
||||
})), "\n", HTML.TD({
|
||||
style: "padding-left: 15px;"
|
||||
}, Blaze.View("lookup:stats.pending", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "pending"));
|
||||
})), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": function() {
|
||||
return Blaze.If(function() {
|
||||
return Spacebars.call(Spacebars.dot(view.lookup("readable"), "forkMessage"));
|
||||
}, function() {
|
||||
return [ " ", Blaze.View("lookup:readable.forkClass", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "forkClass"));
|
||||
}), " " ];
|
||||
}, function() {
|
||||
return " '' ";
|
||||
});
|
||||
}
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("stats"), "block", "number"));
|
||||
})), "\n", null), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:hashFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("hashFilter"), Spacebars.dot(view.lookup("stats"), "block", "hash"));
|
||||
}))), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("stats"), "block", "totalDifficulty"));
|
||||
}))), "\n", HTML.TD({
|
||||
style: "padding-left: 14px;"
|
||||
}, Blaze.View("lookup:stats.block.transactions.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "block", "transactions", "length"));
|
||||
})), "\n", HTML.TD({
|
||||
style: "padding-left: 14px;"
|
||||
}, Blaze.View("lookup:stats.block.uncles.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "block", "uncles", "length"));
|
||||
})), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("timeClass"), Spacebars.dot(view.lookup("stats"), "block", "received"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:blockTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockTimeFilter"), Spacebars.dot(view.lookup("stats"), "block", "received"));
|
||||
})), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("propagationTimeClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.DIV({
|
||||
"class": "propagationBox"
|
||||
}), "\n", HTML.SPAN(Blaze.View("lookup:blockPropagationFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockPropagationFilter"), Spacebars.dot(view.lookup("stats"), "block", "propagation"), false);
|
||||
}))), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return [ "peerPropagationChart", " ", Spacebars.mustache(view.lookup("id")) ];
|
||||
}
|
||||
}), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("propagationNodeAvgTimeClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, Blaze.View("lookup:blockPropagationAvgFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockPropagationAvgFilter"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
})), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeClass"), Spacebars.dot(view.lookup("stats"), "uptime"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:upTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeFilter"), Spacebars.dot(view.lookup("stats"), "uptime"));
|
||||
})));
|
||||
})))));
|
||||
}));
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,331 @@
|
||||
(function(){
|
||||
/**
|
||||
Update the spark chart
|
||||
|
||||
@method sparkChart
|
||||
@param {String} property the property name with the chart data
|
||||
@param {String} className the class name of the sparkchart element
|
||||
*/
|
||||
var sparkChart = function(template, property, className){
|
||||
var fields = {};
|
||||
fields[property] = 1;
|
||||
var meta = Blockchain.findOne('meta', fields);
|
||||
|
||||
var element = template.$('sparkchart.'+ className);
|
||||
element.html(meta[property].join(','));
|
||||
element.addClass("big-details");
|
||||
element.sparkline('html', {
|
||||
type: 'bar',
|
||||
tooltipSuffix: (element.attr('tooltipsuffix') || '')
|
||||
});
|
||||
};
|
||||
|
||||
Template['indexMeteor'].onRendered(function(){
|
||||
var template = this;
|
||||
|
||||
// map
|
||||
this.autorun(function(){
|
||||
var data = Map.find({}).fetch();
|
||||
var element = template.$('#mapHolder');
|
||||
var scope = {};
|
||||
|
||||
if(data.length === 0)
|
||||
return;
|
||||
|
||||
var bubbleConfig = {
|
||||
borderWidth: 0,
|
||||
highlightOnHover: false,
|
||||
popupOnHover: true,
|
||||
popupTemplate: function(geo, data) {
|
||||
return ['<div class="tooltip-arrow"></div>',
|
||||
'<div class="hoverinfo ' + data.fillClass + '">',
|
||||
'<div class="propagationBox"></div>',
|
||||
'<strong>',
|
||||
data.nodeName,
|
||||
'</strong>',
|
||||
'</div>'].join('');
|
||||
}
|
||||
};
|
||||
|
||||
element.empty();
|
||||
|
||||
var width = 628,
|
||||
height = 244;
|
||||
|
||||
var map = new Datamap({
|
||||
element: element[0],
|
||||
scope: 'world',
|
||||
width: width,
|
||||
height: 300,
|
||||
fills: {
|
||||
success: '#7BCC3A',
|
||||
info: '#10A0DE',
|
||||
warning: '#FFD162',
|
||||
orange: '#FF8A00',
|
||||
danger: '#F74B4B',
|
||||
defaultFill: '#282828'
|
||||
},
|
||||
geographyConfig: {
|
||||
borderWidth: 0,
|
||||
borderColor: '#000',
|
||||
highlightOnHover: false,
|
||||
popupOnHover: false
|
||||
},
|
||||
bubblesConfig: {
|
||||
borderWidth: 0,
|
||||
highlightOnHover: false,
|
||||
popupOnHover: true
|
||||
},
|
||||
done: function(datamap) {
|
||||
var ev;
|
||||
|
||||
var zoomListener = d3.behavior.zoom()
|
||||
.size([width, height])
|
||||
.scaleExtent([1, 3])
|
||||
.on("zoom", redraw)
|
||||
.on("zoomend", animadraw);
|
||||
|
||||
function redraw() {
|
||||
datamap.svg.select(".datamaps-subunits").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
|
||||
datamap.svg.select(".bubbles").selectAll("circle")
|
||||
.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")")
|
||||
.attr("r", 3/d3.event.scale);
|
||||
|
||||
ev = d3.event;
|
||||
}
|
||||
|
||||
zoomListener(datamap.svg);
|
||||
|
||||
function animadraw() {
|
||||
var x = Math.min(0, Math.max(ev.translate[0], (-1) * width * (ev.scale-1)));
|
||||
var y = Math.min(0, Math.max(ev.translate[1], (-1) * height * (ev.scale-1)));
|
||||
|
||||
datamap.svg.select(".datamaps-subunits")
|
||||
.transition()
|
||||
.delay(150)
|
||||
.duration(750)
|
||||
.attr("transform", "translate(" + x + "," + y + ")scale(" + ev.scale + ")");
|
||||
|
||||
datamap.svg.select(".bubbles").selectAll("circle")
|
||||
.transition()
|
||||
.delay(150)
|
||||
.duration(750)
|
||||
.attr("transform", "translate(" + x + "," + y + ")scale(" + ev.scale + ")")
|
||||
.attr("r", 3/ev.scale);
|
||||
|
||||
zoomListener.translate([x,y]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
map.bubbles(data, bubbleConfig);
|
||||
});
|
||||
|
||||
// block propagation times chart
|
||||
this.autorun(function(){
|
||||
var element = template.$('histogram.d3-blockpropagation');
|
||||
|
||||
var margin = {top: 0, right: 0, bottom: 0, left: 0};
|
||||
var width = 280 - margin.left - margin.right,
|
||||
height = 63 - margin.top - margin.bottom;
|
||||
|
||||
var TICKS = 40;
|
||||
|
||||
var x = d3.scale.linear()
|
||||
.domain([0, 10000])
|
||||
.rangeRound([0, width])
|
||||
.interpolate(d3.interpolateRound);
|
||||
|
||||
var y = d3.scale.linear()
|
||||
.range([height, 0])
|
||||
.interpolate(d3.interpolateRound);
|
||||
|
||||
var color = d3.scale.linear()
|
||||
.domain([1000, 3000, 7000, 10000])
|
||||
.range(["#7bcc3a", "#FFD162", "#ff8a00", "#F74B4B"]);
|
||||
|
||||
var xAxis = d3.svg.axis()
|
||||
.scale(x)
|
||||
.orient("bottom")
|
||||
.ticks(4, ",.1s")
|
||||
.tickFormat(function(t){ return t/1000 + "s"});
|
||||
|
||||
var yAxis = d3.svg.axis()
|
||||
.scale(y)
|
||||
.orient("left")
|
||||
.ticks(3)
|
||||
.tickFormat(d3.format("%"));
|
||||
|
||||
var line = d3.svg.line()
|
||||
.x(function(d) { return x(d.x + d.dx/2) - 1; })
|
||||
.y(function(d) { return y(d.y) - 2; })
|
||||
.interpolate('basis');
|
||||
|
||||
var tip = d3.tip()
|
||||
.attr('class', 'd3-tip')
|
||||
.offset([10, 0])
|
||||
.direction('s')
|
||||
.html(function(d) {
|
||||
return '<div class="tooltip-arrow"></div><div class="tooltip-inner"><b>' + (d.x/1000) + 's - ' + ((d.x + d.dx)/1000) + 's</b><div class="small">Percent: <b>' + Math.round(d.y * 100) + '%</b>' + '<br>Frequency: <b>' + d.frequency + '</b><br>Cumulative: <b>' + Math.round(d.cumpercent*100) + '%</b></div></div>';
|
||||
})
|
||||
|
||||
var data = Blockchain.findOne('meta', {fields: {blockPropagationChart: 1}}).blockPropagationChart;
|
||||
|
||||
if(data.length === 0)
|
||||
return;
|
||||
|
||||
// Adjust y axis
|
||||
y.domain([0, d3.max(data, function(d) { return d.y; })]);
|
||||
|
||||
// Delete previous histogram
|
||||
element.empty();
|
||||
|
||||
/* Start drawing */
|
||||
var svg = d3.select(".d3-blockpropagation").append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
|
||||
svg.call(tip);
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(xAxis)
|
||||
.selectAll("text")
|
||||
.attr("y", 6);
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "y axis")
|
||||
.attr("transform", "translate(" + width + ", 0)")
|
||||
.call(yAxis);
|
||||
|
||||
|
||||
var bar = svg.append("g")
|
||||
.attr("class", "bars")
|
||||
.selectAll("g")
|
||||
.data(data)
|
||||
.enter().append("g")
|
||||
.attr("transform", function(d) { return "translate(" + x(d.x) + ",0)"; })
|
||||
.on('mouseover', function(d) { tip.show(d, d3.select(this).select('.bar').node()); })
|
||||
.on('mouseout', tip.hide);
|
||||
|
||||
bar.insert("rect")
|
||||
.attr("class", "handle")
|
||||
.attr("y", 0)
|
||||
.attr("width", x(data[0].dx + data[0].x) - x(data[0].x))
|
||||
.attr("height", function(d) { return height; });
|
||||
|
||||
bar.insert("rect")
|
||||
.attr("class", "bar")
|
||||
.attr("y", function(d) { return y(d.y); })
|
||||
.attr("rx", 1)
|
||||
.attr("ry", 1)
|
||||
.attr("fill", function(d) { return color(d.x); })
|
||||
.attr("width", x(data[0].dx + data[0].x) - x(data[0].x) - 1)
|
||||
.attr("height", function(d) { return height - y(d.y) + 1; });
|
||||
|
||||
bar.insert("rect")
|
||||
.attr("class", "highlight")
|
||||
.attr("y", function(d) { return y(d.y); })
|
||||
.attr("fill", function(d) { return d3.rgb(color(d.x)).brighter(.7).toString(); })
|
||||
.attr("rx", 1)
|
||||
.attr("ry", 1)
|
||||
.attr("width", x(data[0].dx + data[0].x) - x(data[0].x) - 1)
|
||||
.attr("height", function(d) { return height - y(d.y) + 1; });
|
||||
|
||||
svg.append("path")
|
||||
.attr("class", "line")
|
||||
.attr("d", line(data));
|
||||
});
|
||||
|
||||
// blocktimes chart
|
||||
this.autorun(function(){
|
||||
sparkChart(template, 'lastBlocksTime', 'spark-blocktimes');
|
||||
});
|
||||
|
||||
// difficulty chart
|
||||
this.autorun(function(){
|
||||
sparkChart(template, 'difficultyChart', 'spark-difficulty');
|
||||
});
|
||||
|
||||
// uncles chart
|
||||
this.autorun(function(){
|
||||
sparkChart(template, 'uncleCountChart', 'spark-uncles');
|
||||
});
|
||||
|
||||
// transactions chart
|
||||
this.autorun(function(){
|
||||
sparkChart(template, 'transactionDensity', 'spark-transactions');
|
||||
});
|
||||
|
||||
// gasspending chart
|
||||
this.autorun(function(){
|
||||
sparkChart(template, 'gasSpending', 'spark-gasspending');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Template['indexMeteor'].helpers({
|
||||
'Blockchain': function(){
|
||||
return Blockchain.findOne('meta');
|
||||
},
|
||||
|
||||
'nodes': function(uptime) {
|
||||
return Nodes.find({stats: {$exists: true}},{limit: 10, sort: {'stats.block.number': -1, 'info.name': 1, 'stats.active': -1}});
|
||||
},
|
||||
|
||||
'blockTimeFilter': function() {
|
||||
var timestamp = this.lastBlock;
|
||||
|
||||
if(timestamp === 0)
|
||||
return '∞';
|
||||
|
||||
// var time = Math.floor((new Date()).getTime() / 1000);
|
||||
var time = (new Date()).getTime();
|
||||
var diff = Math.floor((time - timestamp)/1000);
|
||||
|
||||
if(diff < 60)
|
||||
return Math.round(diff) + ' s ago';
|
||||
|
||||
return moment.duration(Math.round(diff), 's').humanize() + ' ago';
|
||||
},
|
||||
|
||||
'avgTimeFilter': function() {
|
||||
var time = this.avgBlockTime;
|
||||
|
||||
if(time < 60)
|
||||
return parseFloat(time).toFixed(2) + ' s';
|
||||
|
||||
return moment.duration(Math.round(time), 's').humanize();
|
||||
},
|
||||
|
||||
'minerBlocks': function(){
|
||||
var array = [];
|
||||
|
||||
for (var i = 1; i <= this.blocks; i++) {
|
||||
array.push('');
|
||||
};
|
||||
|
||||
return array;
|
||||
},
|
||||
|
||||
'minerBlockClass': function (value) {
|
||||
if(value <= 6)
|
||||
return 'success';
|
||||
|
||||
if(value <= 12)
|
||||
return 'info';
|
||||
|
||||
if(value <= 18)
|
||||
return 'warning';
|
||||
|
||||
if(value <= 24)
|
||||
return 'orange';
|
||||
|
||||
return 'danger';
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,603 @@
|
||||
(function(){
|
||||
Template.__checkName("indexMeteor");
|
||||
Template["indexMeteor"] = new Template("Template.indexMeteor", (function() {
|
||||
var view = this;
|
||||
return [ Spacebars.With(function() {
|
||||
return Spacebars.call(view.lookup("Blockchain"));
|
||||
}, function() {
|
||||
return [ "\n ", HTML.DIV({
|
||||
"class": "container-fluid"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "row"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info bestblock text-info"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-block"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "best block"), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), view.lookup("bestBlock"));
|
||||
}))), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info uncleCount text-info"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-uncle"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "uncles", HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
}), HTML.SPAN({
|
||||
"class": "small"
|
||||
}, "(current / last 50)")), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:bestStats.block.uncles.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("bestStats"), "block", "uncles", "length"));
|
||||
}), "/", Blaze.View("lookup:uncleCount", function() {
|
||||
return Spacebars.mustache(view.lookup("uncleCount"));
|
||||
}))), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info blocktime ", Spacebars.mustache(view.lookup("timeClass"), view.lookup("lastBlock"), true) ];
|
||||
}
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-time"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "last block"), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:blockTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockTimeFilter"));
|
||||
})), "\n "), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info avgblocktime ", Spacebars.mustache(view.lookup("avgTimeClass"), view.lookup("avgBlockTime")) ];
|
||||
}
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-gas"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "avg block time"), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:avgTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("avgTimeFilter"));
|
||||
}))), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info difficulty text-orange"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-hashrate"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "avg network hashrate"), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:networkHashrateFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("networkHashrateFilter"), view.lookup("avgHashrate"), false);
|
||||
}))), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info difficulty text-danger"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-difficulty"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "difficulty"), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-hash"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), view.lookup("lastDifficulty"));
|
||||
})))), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n\n ", HTML.DIV({
|
||||
"class": "row"
|
||||
}, "\n ", HTML.DIV({
|
||||
style: "padding-top: 0px;",
|
||||
"class": "col-xs-8 stats-boxes"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "row second-row"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder box"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "active-nodes ", Spacebars.mustache(view.lookup("nodesActiveClass"), view.lookup("nodesActive"), view.lookup("nodesTotal")) ];
|
||||
}
|
||||
}, HTML.I({
|
||||
"class": "icon-node"
|
||||
}), HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "active nodes"), HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:nodesActive", function() {
|
||||
return Spacebars.mustache(view.lookup("nodesActive"));
|
||||
}), "/", Blaze.View("lookup:nodesTotal", function() {
|
||||
return Spacebars.mustache(view.lookup("nodesTotal"));
|
||||
}))), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder box"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "gasprice text-info"
|
||||
}, HTML.I({
|
||||
"class": "icon-gasprice"
|
||||
}), HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "gas price"), HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:gasPriceFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("gasPriceFilter"), Spacebars.dot(view.lookup("bestStats"), "gasPrice", "toString"));
|
||||
}))), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder box"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "page-latency ", Spacebars.mustache(view.lookup("latencyClass"), true, view.lookup("latency")) ];
|
||||
}
|
||||
}, HTML.I({
|
||||
"class": "icon-clock"
|
||||
}), HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "page latency"), HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:latency", function() {
|
||||
return Spacebars.mustache(view.lookup("latency"));
|
||||
}), " ms")), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder box"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "uptime ", Spacebars.mustache(view.lookup("upTimeClass"), view.lookup("upTimeTotal"), true) ];
|
||||
}
|
||||
}, HTML.I({
|
||||
"class": "icon-bulb"
|
||||
}), HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "uptime"), HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:upTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeFilter"), view.lookup("upTimeTotal"));
|
||||
}))), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "row"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info chart ", Spacebars.mustache(view.lookup("avgTimeClass"), view.lookup("avgBlockTime")) ];
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "block time"), "\n ", HTML.getTag("sparkchart")({
|
||||
tooltipsuffix: "s",
|
||||
"class": "big-details spark-blocktimes"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info chart text-info"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "difficulty"), "\n ", HTML.getTag("sparkchart")({
|
||||
"class": "big-details spark-difficulty"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder xpull-right"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info chart xdouble-chart ", Spacebars.mustache(view.lookup("propagationAvgTimeClass"), view.lookup("blockPropagationAvg"), true) ];
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "block propagation"), "\n ", HTML.getTag("histogram")({
|
||||
"class": "big-details d3-blockpropagation"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder pull-right"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info chart double-chart"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "last blocks miners"), "\n ", HTML.DIV({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "right",
|
||||
"data-original-title": function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("miner"), "blocks"));
|
||||
},
|
||||
"class": "blocks-holder"
|
||||
}, "\n ", Blaze.Each(function() {
|
||||
return Spacebars.call(view.lookup("miners"));
|
||||
}, function() {
|
||||
return [ "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "block-count ", Spacebars.mustache(view.lookup("minerBlocksClass"), view.lookup("blocks"), "text-") ];
|
||||
}
|
||||
}, Blaze.View("lookup:blocks", function() {
|
||||
return Spacebars.mustache(view.lookup("blocks"));
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "small-title-miner"
|
||||
}, Blaze.View("lookup:miner", function() {
|
||||
return Spacebars.mustache(view.lookup("miner"));
|
||||
})), "\n \n ", HTML.Comment(' <div class="block {{minerBlockClass ../blocks}}"></div> '), "\n \n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n " ];
|
||||
}), "\n "), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info chart text-info"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "uncle count", HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
}), HTML.SPAN({
|
||||
"class": "small"
|
||||
}, "(25 blocks per bar)")), "\n ", HTML.getTag("sparkchart")({
|
||||
"class": "big-details spark-uncles"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info chart text-info"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "transactions"), "\n ", HTML.getTag("sparkchart")({
|
||||
"class": "big-details spark-transactions"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info chart text-info"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "gas spending"), "\n ", HTML.getTag("sparkchart")({
|
||||
"class": "big-details spark-gasspending"
|
||||
}), "\n "), "\n "), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-4 stat-holder map-holder"
|
||||
}, "\n ", HTML.getTag("nodemap")({
|
||||
id: "mapHolder"
|
||||
}), "\n "), "\n\n ", HTML.DIV({
|
||||
"class": "col-xs-12 stats-boxes"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "row second-row"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "col-xs-12 stat-holder box"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "active-nodes text-orange"
|
||||
}, HTML.I({
|
||||
"class": "icon-hashrate"
|
||||
}), HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "Block #1028201 hash"), HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:frontierHash", function() {
|
||||
return Spacebars.mustache(view.lookup("frontierHash"));
|
||||
}))), "\n "), "\n "), "\n "), "\n\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n " ];
|
||||
}), "\n\n ", HTML.DIV({
|
||||
style: "padding-top: 10px",
|
||||
"class": "row"
|
||||
}, "\n ", HTML.TABLE({
|
||||
"class": "table table-striped"
|
||||
}, "\n ", HTML.THEAD("\n ", HTML.TR({
|
||||
"class": "text-info"
|
||||
}, "\n ", HTML.TH({
|
||||
"class": "th-nodecheck"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Pin nodes to display first",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)",
|
||||
"class": "icon-check-o"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-nodename"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node name",
|
||||
"ng-click": "orderTable(['info.name'], false)",
|
||||
"class": "icon-node"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-nodetype"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node type",
|
||||
"ng-click": "orderTable(['info.node'], false)",
|
||||
"class": "icon-laptop"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-latency"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node latency",
|
||||
"ng-click": "orderTable(['stats.latency'], false)",
|
||||
"class": "icon-clock"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Is mining",
|
||||
"ng-click": "orderTable(['-stats.hashrate'], false)",
|
||||
"class": "icon-mining"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Peers",
|
||||
"ng-click": "orderTable(['-stats.peers'], false)",
|
||||
"class": "icon-group"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Pending transactions",
|
||||
"ng-click": "orderTable(['-stats.pending'], false)",
|
||||
"class": "icon-network"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Last block",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)",
|
||||
"class": "icon-block"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-blockhash"
|
||||
}, HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-blockhash"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Total difficulty",
|
||||
"ng-click": "orderTable(['-stats.block.totalDifficulty'], false)",
|
||||
"class": "icon-difficulty"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Block transactions",
|
||||
"ng-click": "orderTable(['-stats.block.transactions.length'], false)",
|
||||
"class": "icon-check-o"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Uncles",
|
||||
"ng-click": "orderTable(['-stats.block.uncles.length'], false)",
|
||||
"class": "icon-uncle"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-blocktime"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Last block time",
|
||||
"ng-click": "orderTable(['-stats.block.received'], false)",
|
||||
"class": "icon-time"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-peerPropagationTime"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Propagation time",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)",
|
||||
"class": "icon-gas"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-peerPropagationChart"
|
||||
}), "\n ", HTML.TH({
|
||||
"class": "th-peerPropagationAvg"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Average propagation time",
|
||||
"ng-click": "orderTable(['stats.propagationAvg'], false)",
|
||||
"class": "icon-gas"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Up-time",
|
||||
"ng-click": "orderTable(['-stats.uptime'], false)",
|
||||
"class": "icon-bulb"
|
||||
})), "\n "), "\n "), "\n ", HTML.TBODY("\n ", Blaze.Each(function() {
|
||||
return Spacebars.call(view.lookup("nodes"));
|
||||
}, function() {
|
||||
return [ "\n ", HTML.TR({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("mainClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
},
|
||||
id: function() {
|
||||
return [ "node_", Spacebars.mustache(view.lookup("id")) ];
|
||||
}
|
||||
}, "\n ", HTML.TD({
|
||||
"class": "td-nodecheck"
|
||||
}, HTML.I({
|
||||
"ng-click": "pinNode(id)",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "right",
|
||||
"data-original-title": function() {
|
||||
return [ "Click to ", Blaze.If(function() {
|
||||
return Spacebars.call(view.lookup("pinned"));
|
||||
}, function() {
|
||||
return "'un'";
|
||||
}, function() {
|
||||
return "''";
|
||||
}), "pin" ];
|
||||
},
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("nodePinClass"), view.lookup("pinned"));
|
||||
}
|
||||
})), "\n ", HTML.TD({
|
||||
rel: function() {
|
||||
return Spacebars.mustache(view.lookup("id"));
|
||||
},
|
||||
"class": "nodeInfo"
|
||||
}, HTML.SPAN({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
"data-html": "true",
|
||||
"data-original-title": function() {
|
||||
return Spacebars.mustache(view.lookup("geoTooltip"), view.lookup("."));
|
||||
},
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:info.name", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("info"), "name"));
|
||||
})), HTML.SPAN({
|
||||
"class": "small"
|
||||
}, HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
}), "(", Blaze.View("lookup:info.ip", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("info"), "ip"));
|
||||
}), ")"), HTML.A({
|
||||
href: "https://github.com/ethereum/wiki/wiki/Network-Status#updating",
|
||||
target: "_blank",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
"data-html": "true",
|
||||
"data-original-title": [ "Netstats client needs update.", HTML.CharRef({
|
||||
html: "<",
|
||||
str: "<"
|
||||
}), "br", HTML.CharRef({
|
||||
html: ">",
|
||||
str: ">"
|
||||
}), "Click this icon for instructions." ],
|
||||
"class": function() {
|
||||
return [ "small ", Spacebars.mustache(view.lookup("nodeClientClass"), view.lookup("info"), Spacebars.dot(view.lookup("Blockchain"), "currentApiVersion")) ];
|
||||
}
|
||||
}, HTML.I({
|
||||
"class": "icon-warning-o"
|
||||
}))), "\n ", HTML.TD("\n ", HTML.DIV({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:nodeVersion", function() {
|
||||
return Spacebars.mustache(view.lookup("nodeVersion"), Spacebars.dot(view.lookup("info"), "node"));
|
||||
})), "\n "), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "latencyClass"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:readable.latency", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "latency"));
|
||||
}))), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("hashrateClass"), Spacebars.dot(view.lookup("stats"), "mining"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:hashrateFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("hashrateFilter"), Spacebars.dot(view.lookup("stats"), "hashrate"), Spacebars.dot(view.lookup("stats"), "mining"));
|
||||
})), "\n ", HTML.TD({
|
||||
style: "padding-left: 11px;",
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("peerClass"), Spacebars.dot(view.lookup("stats"), "peers"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:stats.peers", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "peers"));
|
||||
})), "\n ", HTML.TD({
|
||||
style: "padding-left: 15px;"
|
||||
}, Blaze.View("lookup:stats.pending", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "pending"));
|
||||
})), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": function() {
|
||||
return Blaze.If(function() {
|
||||
return Spacebars.call(Spacebars.dot(view.lookup("readable"), "forkMessage"));
|
||||
}, function() {
|
||||
return [ " ", Blaze.View("lookup:readable.forkClass", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "forkClass"));
|
||||
}), " " ];
|
||||
}, function() {
|
||||
return " '' ";
|
||||
});
|
||||
}
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("stats"), "block", "number"));
|
||||
})), "\n "), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:hashFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("hashFilter"), Spacebars.dot(view.lookup("stats"), "block", "hash"));
|
||||
}))), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("stats"), "block", "totalDifficulty"));
|
||||
}))), "\n ", HTML.TD({
|
||||
style: "padding-left: 14px;"
|
||||
}, Blaze.View("lookup:stats.block.transactions.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "block", "transactions", "length"));
|
||||
})), "\n ", HTML.TD({
|
||||
style: "padding-left: 14px;"
|
||||
}, Blaze.View("lookup:stats.block.uncles.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "block", "uncles", "length"));
|
||||
})), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("timeClass"), Spacebars.dot(view.lookup("stats"), "block", "received"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:blockTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockTimeFilter"), Spacebars.dot(view.lookup("stats"), "block", "received"));
|
||||
})), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("propagationTimeClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "propagationBox"
|
||||
}), HTML.SPAN(Blaze.View("lookup:blockPropagationFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockPropagationFilter"), Spacebars.dot(view.lookup("stats"), "block", "propagation"), false);
|
||||
})), "\n "), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return [ "peerPropagationChart ", Spacebars.mustache(view.lookup("id")) ];
|
||||
}
|
||||
}, "\n "), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("propagationNodeAvgTimeClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, Blaze.View("lookup:blockPropagationAvgFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockPropagationAvgFilter"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
})), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeClass"), Spacebars.dot(view.lookup("stats"), "uptime"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:upTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeFilter"), Spacebars.dot(view.lookup("stats"), "uptime"));
|
||||
})), "\n "), "\n " ];
|
||||
}), "\n "), "\n "), "\n ") ];
|
||||
}));
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,8 @@
|
||||
(function(){
|
||||
Template.body.addContent((function() {
|
||||
var view = this;
|
||||
return [ "\n ", Spacebars.include(view.lookupTemplate("indexMeteor")), "\n " ];
|
||||
}));
|
||||
Meteor.startup(Template.body.renderToDocument);
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Copyright (C) 2015 by original authors @ fontello.com</metadata>
|
||||
<defs>
|
||||
<font id="minimal-icons" horiz-adv-x="1000" >
|
||||
<font-face font-family="minimal-icons" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="1000" descent="0" />
|
||||
<missing-glyph horiz-adv-x="1000" />
|
||||
<glyph glyph-name="truck" unicode="" d="m734 179c-86 0-156 71-156 157s70 157 156 157 157-71 157-157-71-157-157-157z m0 282c-69 0-125-56-125-125s56-125 125-125 125 56 125 125-56 125-125 125z m-484-282c-87 0-157 71-157 157s70 157 157 157c86 0 156-71 156-157s-70-157-156-157z m0 282c-69 0-126-56-126-125s57-125 126-125c69 0 125 56 125 125s-56 125-125 125z m256-93h-83v31h65l19 31h56v-31h-38l-19-31z m441 31h-38v31h25l34 36v90h-109v155h-81l-77-178-28 12 84 198h243l0-290-53-54z m-56 188h77v124h-77v-124z m-325-110l-3 0-461 75c-14 1-25 11-27 24l-75 166v4c0 15 13 28 28 28l680 47c0 0 0 0 0 0 9 0 16-4 21-9v9h229v-32l-220 0-145-288c-2-14-13-24-27-24z m-460 106l457-74 140 280-669-46 72-160z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="database" unicode="" d="m500 984c-192 0-386-37-386-108h31c0 27 122 77 355 77 233 0 355-50 355-77v-31c0-25-125-72-355-72-233 0-355 46-355 72h-31c0-76 231-104 386-104 121 0 287 17 355 60v-191c0-33-138-79-355-79s-355 46-355 79v72h-31v-558c0-68 168-93 241-101 46-5 95-7 145-7 192 0 386 37 386 108v752c0 71-194 108-386 108z m355-860c0-27-122-77-355-77-49 0-97 2-142 7-147 15-213 50-213 70v185c63-44 210-66 355-66s292 22 355 66v-185z m0 234c0-34-138-84-355-84s-355 50-355 84v205c63-42 210-63 355-63s292 21 355 63v-205z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="mining" unicode="" d="m83 9c-8 0-16 3-22 9l-43 43c-12 12-12 31 0 43l350 351 22-22-350-351 43-42 524 525 22-22-525-525c-6-6-14-9-21-9z m739 727l-22 22 11 11-43 42-10-11-22 22 11 11c12 12 31 12 43 0l43-43c12-12 12-31 0-43l-11-11z m-140-171l0 0c-8 0-14 3-19 8l-90 90c-11 11-10 29 2 41l97 97c11 11 31 12 41 2l90-90c5-5 7-12 8-19 0-8-4-16-10-22l-97-97c-6-6-14-10-22-10z m-85 118l85-85 96 95-85 85-96-95z m339-520l-11 6-11 7 5 13c24 67-47 202-185 353l23 21c142-156 186-258 195-320 29 89-25 232-145 373l24 20c159-187 205-373 114-464l-9-9z m-394 571c-233 213-335 191-353 185-12-5-18 3-20 6l3 20c91 91 277 45 464-114l-20-24c-141 120-284 174-373 145 62-9 164-53 320-195l-21-23z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="check" unicode="" d="m393 85c-8 0-16 3-22 9l-354 355c-13 12-13 32 0 44l98 99 22-22-98-99 354-354 568 567-199 200-369-369-155 155-10-10-22 22 10 10c6 6 13 9 22 9 0 0 0 0 0 0 8 0 16-3 22-9l133-133 347 347c12 12 32 12 44 0l200-200c5-5 9-13 9-22 0-8-4-16-9-22l-569-568c-6-6-14-9-22-9z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="cancel" unicode="" d="m268 15c-8 0-16 3-22 9l-222 222c-12 12-12 32 0 44l211 210-211 210c-6 6-9 14-9 22s3 17 9 22l112 112 22-22-112-112 233-232-233-232 222-222 232 233 232-233 222 222-233 232 233 232-222 222-232-233-232 233-10-10-22 22 10 10c12 12 32 12 44 0l210-210 210 210c6 6 14 9 22 9 0 0 0 0 0 0 9 0 17-3 22-9l222-222c6-5 9-13 9-22 0-8-3-16-9-22l-210-210 210-210c12-12 12-32 0-44l-222-222c-12-12-32-12-44 0l-210 211-210-211c-6-6-14-9-22-9z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="loader" unicode="" d="m500 16c-267 0-484 217-484 484 0 103 32 202 92 285l25-19c-56-77-86-170-86-266 0-250 203-453 453-453 250 0 453 203 453 453s-203 453-453 453c-79 0-156-20-224-59l-16 27c73 41 156 63 240 63 267 0 484-217 484-484s-217-484-484-484z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="check-o" unicode="" d="m487 419l214 213 22-22-235-235-11 11-1-1-128 129 22 22 117-117z m477 222l-30-9c13-43 19-87 19-132 0-250-203-453-453-453s-453 203-453 453 203 453 453 453c50 0 99-8 146-24l10 30c-50 17-102 25-156 25-267 0-484-217-484-484s217-484 484-484 484 217 484 484c0 48-7 95-20 141z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="cancel-o" unicode="" d="m662 640l-140-140 140-140-22-22-140 140-140-140-22 22 140 140-140 140 22 22 140-140 140 140 22-22z m302 1l-30-9c13-43 19-87 19-132 0-250-203-453-453-453-250 0-453 203-453 453 0 250 203 453 453 453 50 0 99-8 146-24l10 30c-50 17-103 25-156 25-267 0-484-217-484-484 0-267 217-484 484-484 267 0 484 217 484 484 0 48-7 95-20 141z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="warning-o" unicode="" d="m984 500c0-267-217-484-484-484-267 0-484 217-484 484 0 103 32 202 92 285l25-19c-56-77-86-170-86-266 0-250 203-453 453-453s453 203 453 453-203 453-453 453c-79 0-156-20-224-59l-16 27c73 42 156 63 240 63 267 0 484-217 484-484z m-420 200l0 9c0 36-29 65-64 65-35 0-63-29-63-65 0-2 0-7-1-13l32 0c0 6 0 11 0 13 0 19 14 34 32 34 18 0 32-15 32-34l0-10c4-281-32-295-32-295 0 0-25 9-31 175l-31-1c6-181 35-205 62-205 6 0 15 2 24 10 29 30 42 133 40 317z m-64-378c35 0 64-29 64-64 0-35-29-64-64-64-35 0-63 29-63 64 0 35 28 64 63 64z m0-31c-18 0-32-15-32-33 0-18 14-33 32-33 18 0 32 15 32 33s-14 33-32 33z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="network" unicode="" d="m501 224c-63 0-124 23-172 64l19 22c43-36 97-56 153-56 124 0 227 97 235 221l29-2c-9-139-125-249-264-249z m-249 175c-11 29-16 60-16 91 0 147 119 266 265 266 104 0 199-62 242-158l-27-12c-38 85-122 140-215 140-130 0-236-106-236-236 0-28 5-55 14-81l-27-10z m-120-96c-51 0-86 12-97 38-22 52 61 123 135 174l17-24c-98-67-134-118-125-139 17-40 208-25 479 91 120 51 227 110 303 167 80 60 101 100 94 116-10 23-85 32-227-4l-7 29c86 21 235 48 261-13 16-38-19-89-104-152-77-58-187-118-308-170-152-65-318-113-421-113z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="block" unicode="" d="m1000 779l-16-5-484 140-484-140-16 5v-68h31v26l453-131v-483l-453 131v332h-31v-355l484-141v-9l16 5 16-5v9l484 141v548z m-928-21l428 124 428-124-428-124-428 124z m897-504l-453-131v483l453 131v-483z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="bulb" unicode="" d="m378 219c-12 22-4 37 1 45 4 6 4 7 1 14-27 47-59 84-89 120-36 42-69 81-90 131-12 28-18 56-21 87-1 14-2 28-3 41-1 10-1 20-1 29 0 11 1 24 3 38 18 128 120 231 255 257 22 2 43 3 65 3 22 0 44-1 64-3v0l3 0c150-29 258-153 258-295 0-37-7-85-20-140-23-68-59-110-98-154-28-33-58-67-84-114-4-7-4-8 0-14 5-8 13-22 2-45l-28 15c4 7 3 8-1 14-5 9-13 23-1 45 28 50 59 85 89 119 38 44 71 82 91 143 12 50 19 97 19 131 0 127-97 238-232 264l0 0c-40 4-83 4-123 0-120-23-212-116-228-230-2-13-3-24-3-34 0-8 1-17 1-27 1-14 2-27 3-41 2-27 9-52 19-77 19-45 51-83 84-123 32-36 64-75 93-125 12-22 4-36-1-44-3-7-4-8 0-15l-28-15z m68-203c-25 0-49 7-55 44l30 5c4-18 9-20 47-17 19 2 45 2 64 0 38-3 43-1 46 17l31-5c-8-49-48-46-79-43-20 2-41 2-60 0-7 0-16-1-24-1z m-68 111h242v-31h-242v31z m0 62h242v-31h-242v31z m184 154h-32c0 55 4 103 12 143-16 3-30 8-43 16-12-7-25-13-40-15 7-40 11-87 11-142h-31c0 62-5 107-12 141-50 5-97 35-97 90 0 24 18 43 41 43 13 0 44-6 68-63 5-11 10-24 13-39 8 1 16 4 22 7-15 18-24 41-24 65 0 36 21 62 50 62 29 0 51-26 51-61 0-24-10-48-26-66 7-4 15-6 24-7 3 14 8 27 13 39 25 58 56 64 68 64 23 0 40-18 40-42 0-55-46-86-96-92-7-34-12-80-12-143z m-191 245c-7 0-10-6-10-12 0-32 27-51 58-57-2 10-6 18-8 25-14 32-30 44-40 44z m259 1c-9 0-25-12-39-45-3-7-6-15-9-25 31 7 56 27 56 59 0 2 0 11-8 11z m-130 31c-13 0-19-16-19-31 0-18 7-34 19-47 12 13 19 30 19 48 0 15-6 30-19 30z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="node" unicode="" d="m228 516h529v-31h-529v31z m-30-138h589c26 0 46 21 46 46h-31c0-8-7-15-15-15h-589c-8 0-15 7-15 15v409c0 8 7 14 15 14h589c8 0 15-6 15-14v-197h31v197c0 25-20 46-46 46h-589c-26 0-46-21-46-46v-409c0-25 20-46 46-46z m318-30h-31v-74h-61v-153h152v153h-60v74z m29-195h-90v89h90v-89z m-514 60h363v-31h-363v31z m575 0h363v-31h-363v31z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="laptop" unicode="" d="m893 396c-1 16-9 30-22 39 6 8 9 18 9 29v400c0 29-22 52-49 52h-659c-27 0-49-23-49-52v-38h31v38c0 11 8 21 18 21h659c10 0 18-10 18-21v-400c0-11-8-21-18-21h-659c-10 0-18 10-18 21v244h-31v-244c0-10 3-19 7-27-14-8-24-23-25-41l-89-259v-3c0-27 22-50 49-50h870c27 0 49 23 49 50v3l-91 259z m42-281h-870c-9 0-17 8-18 17l89 259v2c0 11 8 19 18 19h18 659 13c10 0 18-8 18-19v-2l91-259c-1-9-9-17-18-17z m-193 269h-489c-20 0-36-15-38-35l-41-134-1-4c0-21 17-38 38-38h574c20 0 37 17 37 38l-43 138c-2 20-18 35-37 35z m31-119h-39l-9 28h32v22l16-50z m-469 28h48l-7-28h-50l9 28z m-42-28h-40l9 28h40l-9-28z m342 59h-49v29h42l7-29z m25 29h43l9-29h-45l-7 29z m5-147h-271l7 28h257l7-28z m-168 59v28h58v-28h-58z m-32 0h-57l7 28h50v-28z m121 0v28h57l7-28h-64z m-31 59h-58v29h58v-29z m-90 0h-42l7 29h35v-29z m-74 0h-45l9 29h43l-7-29z m-23-90l-7-30h-55l10 30h52z m322 0h53l9-30h-55l-7 30z m-8 31l0 0-7 28h48l9-28h-50z m97 81l7-22h-41l-9 29h37c3 0 6-3 6-7z m-501 0c0 4 2 7 6 7h38l-9-29h-42l6 18 1 4z m-42-137l8 25h39l-10-30h-31c-3 0-5 2-6 5z m580-5h-31l-10 30h39l8-25c-1-3-3-5-6-5z m38 415v193c0 25-20 46-45 46h-550c-25 0-46-21-46-46v-296c0-25 21-45 46-45h550c25 0 45 20 45 45v29h-31v-29c0-8-7-14-14-14h-550c-8 0-14 6-14 14v296c0 8 6 14 14 14h550c7 0 14-6 14-14v-193l31 0 0 0z m-405 72l-124-107 20-23 109 93 135-55 152 124-20 24-137-112-135 56z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="time" unicode="" d="m823 968h-646v-30h52c-14-76-42-354 266-452 300-96 257-367 244-425h-479c-6 33-23 137 19 236l-28 12c-43-103-30-206-22-248h-52v-30h646v30h-54c14 75 45 355-265 454-297 94-257 363-244 423h479c12-57 50-305-206-409l12-28c264 108 238 364 225 437h53v30z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="clock" unicode="" d="m501 484h-307v31h291v161h32v-180l-6-12-10 0z m483 16c0 267-217 484-484 484-39 0-78-4-116-14l8-30c35 9 71 13 108 13 250 0 453-203 453-453s-203-453-453-453-453 203-453 453c0 53 9 106 27 155l-29 11c-20-53-29-109-29-166 0-267 217-484 484-484 267 0 484 217 484 484z m-53 401c-2 21-12 40-28 54-17 14-37 21-58 19-21-1-40-11-54-27l24-20c8 10 19 15 32 16 13 1 25-3 36-12 10-8 16-20 17-33 1-12-2-24-10-34l23-20c14 16 20 36 18 57z m-415 31h-31v-61h31v61z m0-806h-31v-61h31v61z m418 388h-61v-31h61v31z m-806 0h-61v-31h61v31z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="group" unicode="" d="m500 429c-58 0-105 48-105 106 0 59 47 107 105 107 58 0 106-48 106-107 0-58-48-106-106-106z m0 181c-40 0-74-33-74-75s34-75 74-75c41 0 74 34 74 75s-33 75-74 75z m243-356h-31c0 63-97 115-211 115-115 0-212-52-212-115h-31c0 82 107 147 243 147 136 0 242-65 242-147z m-544 327c-50 0-91 41-91 90 0 50 41 91 91 91 50 0 91-41 91-91 0-49-41-90-91-90z m0 149c-33 0-60-26-60-59 0-32 27-59 60-59 33 0 60 27 60 59 0 33-27 59-60 59z m181-309h-32c0 57-63 99-150 99-88 0-151-42-151-99h-31c0 75 76 130 182 130 105 0 182-55 182-130z m422 158c-50 0-90 41-90 91 0 50 40 91 90 91s91-41 91-91c0-50-41-91-91-91z m0 151c-32 0-59-27-59-60 0-33 27-59 59-59s60 26 60 59c0 33-27 60-60 60z m182-309h-31c0 58-63 100-150 100-88 0-151-42-151-100h-31c0 76 76 131 182 131 105 0 181-55 181-131z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="gas" unicode="" d="m500 16c-267 0-484 217-484 484 0 103 32 202 93 285l25-19c-57-77-86-169-86-266 0-250 203-453 452-453 250 0 452 203 452 453 0 250-202 453-452 453-79 0-156-20-224-59l-15 27c72 41 155 63 239 63 267 0 484-217 484-484 0-267-217-484-484-484z m280 453l-13 28 66 28c-6 179-153 322-333 322-183 0-333-149-333-332h-31c0 201 163 364 364 364 201 0 364-163 364-364v-10l-84-36z m-280-270v31c25 0 45 20 45 44 0 44-24 259-45 309-21-50-45-265-45-309h-31c0 18 7 102 18 181 21 154 40 167 58 167 19 0 37-13 58-167 11-79 18-163 18-181 0-41-34-75-76-75z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="difficulty" unicode="" d="m498 21c-9 0-17 3-23 9l-450 450c-12 13-12 33 0 45l140 140c-23 6-43 17-60 34-24 24-38 57-38 92s14 67 38 92c25 25 57 38 92 38s68-13 92-38c25-25 39-58 38-93l-31 0c0 27-10 52-29 71-19 19-43 29-70 29-26 0-51-11-70-29-18-19-29-44-29-70 0-26 11-51 29-70 19-19 45-30 71-29l39 0-190-189 450-451 452 450-140 141c-6-23-17-43-34-60-25-24-57-38-92-38s-67 14-92 38c-25 25-38 57-38 92 0 35 13 68 38 92 17 17 37 29 60 34l-153 152-30-29-22 22 29 29c13 13 33 13 46 0l201-201-38 0c-27 1-52-10-71-29-19-19-29-43-29-70s10-51 29-70c19-18 44-29 70-29s51 11 70 29c19 19 29 44 29 71l-1 39 190-190c6-6 9-14 9-22s-3-17-9-23l-450-450c-6-6-15-9-23-9z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="uncle" unicode="" d="m659 0c-125 0-228 102-228 228 0 41 11 81 32 116l-75 75c-28-17-60-25-92-25-101 0-182 81-182 182s81 182 182 182v-31c-84 0-151-68-151-151s68-151 151-151c30 0 60 9 85 27l11 7 111-111-7-11c-22-32-33-70-33-109 0-109 88-197 196-197s196 88 196 197-88 196-196 196c-46 0-90-16-125-45l-11-9-110 110 7 10c17 26 27 55 27 86 0 27-8 53-22 77l-6 10 128 129 11-6c15-9 31-13 48-13 54 0 98 44 98 98s-44 98-98 98c-16 0-32-4-46-11-32-18-52-51-52-87 0-17 5-34 13-48l6-11-117-117-22 22 100 101c-7 17-11 35-11 53 0 48 26 92 69 114 18 10 39 15 60 15 71 0 129-58 129-129 0-71-58-129-129-129-18 0-36 4-53 11l-95-95c13-26 20-54 20-82 0-33-9-64-25-92l72-72c39 28 86 43 134 43 125 0 228-102 228-227s-103-228-228-228z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="hashrate" unicode="" d="m367 39c-163 37-286 115-340 215-31 57-35 117-13 175l7 20 17-13c80-62 99-64 103-63 4 8-2 42-7 70-8 49-19 110-10 170 17 110 96 175 235 195l24 3-7-23c-15-52-8-91 19-109 31-21 85-11 127 23 67 53 85 142 48 239l-15 38 36-19c271-138 195-309 158-391-7-17-16-37-15-43 3-5 32-40 69-37 39 2 78 46 113 126l12 30 16-28c63-115 73-229 30-331-49-114-161-203-307-242l-8 30c137 37 241 119 286 225 36 84 31 178-14 274-37-74-80-113-128-115-54-3-92 45-97 54-9 16 1 37 15 69 35 81 94 213-110 333 24-95-1-182-69-236-54-43-121-54-164-25-21 14-51 47-37 120-111-21-172-75-186-164-8-55 2-114 10-161 7-44 12-73 2-91-4-8-11-13-20-14-17-4-43 5-111 55-10-43-4-87 19-129 48-91 167-165 319-200l-7-30z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="gasprice" unicode="" d="m430 1c-8 0-16 3-22 9l-398 398c-12 12-12 32 0 44l345 345 22-22-345-345 398-398 494 494c3 17 11 90 18 161 8 75 17 160 25 222l-58 58c-62-8-146-17-221-24-71-8-145-16-162-19l-8-9-23 22 12 12c6 6 7 7 178 25 77 8 165 17 228 25l8 1 79-79-1-8c-8-63-17-151-26-229-17-170-18-171-24-177l-497-497c-6-6-14-9-22-9z m420 771c-21 0-41 8-55 23-15 14-23 34-23 55 0 21 8 40 23 55s34 23 55 23c21 0 40-8 55-23l-22-22c-18 18-49 18-66 0-9-9-14-21-14-33 0-13 5-24 14-33 17-18 48-18 66 0l22-22c-15-15-34-23-55-23z m-430-565l-22 22 177 177c-73-16-121 29-121 30l21 22-10-11 10 11c4-3 80-72 188 36l0 0 23-22-266-265z" horiz-adv-x="1000" />
|
||||
</font>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 574 B |
|
After Width: | Height: | Size: 574 B |
|
After Width: | Height: | Size: 442 KiB |
|
After Width: | Height: | Size: 722 KiB |
|
After Width: | Height: | Size: 881 KiB |
|
After Width: | Height: | Size: 1.1 MiB |