add meteor frontend app

This commit is contained in:
Fabian Vogelsteller
2015-08-14 19:22:53 +02:00
parent b9cd95bedc
commit f53e5559f8
233 changed files with 115140 additions and 0 deletions

View File

@@ -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"
};
})();

View File

@@ -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});
}
})();

View File

@@ -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'));
}
})();

File diff suppressed because one or more lines are too long

View 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};
})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View 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}})});
})();

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View 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>&times;</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)});
})();

View File

@@ -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');
})();

View File

@@ -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);
});
})();

View File

@@ -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"));
})) ];
}));
})();

View File

@@ -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&nbsp;\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&nbsp;\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: "&nbsp;",
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: "&nbsp;",
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"));
})));
})))));
}));
})();

View File

@@ -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';
}
});
})();

View File

@@ -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: "&nbsp;",
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: "&nbsp;",
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: "&nbsp;",
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: "&nbsp;",
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: "&lt;",
str: "<"
}), "br", HTML.CharRef({
html: "&gt;",
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 ") ];
}));
})();

View File

@@ -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);
})();

View File

@@ -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="&#xe800;" 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="&#xe801;" 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="&#xe802;" 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="&#xe803;" 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="&#xe804;" 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="&#xe805;" 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="&#xe806;" 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="&#xe807;" 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="&#xe808;" 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="&#xe809;" 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="&#xe80a;" 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="&#xe80b;" 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="&#xe80c;" 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="&#xe80d;" 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="&#xe80e;" 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="&#xe80f;" 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="&#xe810;" 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="&#xe811;" 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="&#xe812;" 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="&#xe813;" 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="&#xe814;" 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="&#xe815;" 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB