UNPKG

foxy-proxy

Version:

A Proof of Capacity proxy which supports solo and pool mining upstreams.

145 lines (128 loc) 4.93 kB
const chalk = require('chalk'); const logUpdate = require('log-update'); const moment = require('moment'); const Table = require('cli-table3'); const eventBus = require('./services/event-bus'); const store = require('./services/store'); const version = require('./version'); const Capacity = require('../shared/capacity'); const outputUtil = require('./output-util'); class Dashboard { static getTimeElapsedSinceLastBlock(blockStart) { const duration = moment.duration(moment().diff(moment(blockStart))); return `${duration.hours().toString().padStart(2, '0')}:${duration.minutes().toString().padStart(2, '0')}:${duration.seconds().toString().padStart(2, '0')}`; } static getBestDeadlineString(bestDL) { if (bestDL === null) { return 'N/A'; } const duration = moment.duration(parseInt(bestDL, 10), 'seconds'); if (duration.months() > 0) { return `${duration.months()}m ${duration.days()}d ${duration.hours().toString().padStart(2, '0')}:${duration.minutes().toString().padStart(2, '0')}:${duration.seconds().toString().padStart(2, '0')}`; } else if (duration.days() > 0) { return `${duration.days()}d ${duration.hours().toString().padStart(2, '0')}:${duration.minutes().toString().padStart(2, '0')}:${duration.seconds().toString().padStart(2, '0')}`; } return `${duration.hours().toString().padStart(2, '0')}:${duration.minutes().toString().padStart(2, '0')}:${duration.seconds().toString().padStart(2, '0')}`; }; constructor() { this.maxLogLines = 12; this.lastLogLines= []; this.proxyStats = []; eventBus.subscribe('log/info', (msg) => { this.lastLogLines.push(`${moment().format('YYYY-MM-DD HH:mm:ss.SSS')} [INFO] | ${msg}`); if (this.lastLogLines.length > this.maxLogLines) { this.lastLogLines = this.lastLogLines.slice(this.maxLogLines * -1); } }); eventBus.subscribe('log/debug', (msg) => { this.lastLogLines.push(chalk.grey(`${moment().format('YYYY-MM-DD HH:mm:ss.SSS')} [DEBUG] | ${msg}`)); if (this.lastLogLines.length > this.maxLogLines) { this.lastLogLines = this.lastLogLines.slice(this.maxLogLines * -1); } }); eventBus.subscribe('log/error', (msg) => { this.lastLogLines.push(chalk.red(`${moment().format('YYYY-MM-DD HH:mm:ss.SSS')} [ERROR] | ${msg}`)); if (this.lastLogLines.length > this.maxLogLines) { this.lastLogLines = this.lastLogLines.slice(this.maxLogLines * -1); } }); eventBus.subscribe('stats/proxy', this.onNewProxyStats.bind(this)); eventBus.subscribe('stats/current-round', this.onNewUpstreamStats.bind(this)); eventBus.subscribe('stats/historical', this.onNewUpstreamStats.bind(this)); } async initStats() { this.proxyStats = await Promise.all(store.getProxies().map((proxy) => proxy.getStats())); } onNewProxyStats(proxyName, proxyStats) { const stats = this.proxyStats; if (!stats) { return; } const proxy = stats.find(proxy => proxy.name === proxyName); if (!proxy) { return; } Object.keys(proxyStats).forEach(key => { proxy[key] = proxyStats[key]; }); } onNewUpstreamStats(fullUpstreamName, upstreamStats) { const stats = this.proxyStats; if (!stats) { return; } const upstream = stats .map(proxy => proxy.upstreamStats) .reduce((acc, curr) => acc.concat(curr), []) .find(upstream => upstream.fullName === fullUpstreamName); if (!upstream) { return; } Object.keys(upstreamStats).forEach(key => { upstream[key] = upstreamStats[key]; }); } buildTable() { const table = new Table({ head: ['Proxy', 'Upstream', 'Block #', 'NetDiff', 'Elapsed', 'Best DL', 'EC', 'Plot size'], style: { head: ['cyan'], }, }); this.proxyStats.map(proxy => { return proxy.upstreamStats.map(upstream => { table.push([ outputUtil.getName(proxy), outputUtil.getName(upstream), upstream.blockNumber, upstream.netDiff ? `${Capacity.fromTiB(upstream.netDiff).toString(2)}` : 'N/A', Dashboard.getTimeElapsedSinceLastBlock(upstream.roundStart), Dashboard.getBestDeadlineString(upstream.bestDL), upstream.estimatedCapacityInTB ? Capacity.fromTiB(upstream.estimatedCapacityInTB).toString() : 'N/A', proxy.totalCapacity ? (new Capacity(proxy.totalCapacity)).toString() : 'N/A', ]); }); }); return table.toString(); } buildLogs() { return this.lastLogLines.join('\n'); } render() { logUpdate([ chalk.bold.magenta(`Foxy-Proxy ${version}`), this.buildTable(), '', 'Last log lines:', this.buildLogs(), ].join('\n')); } start() { this.render(); this.timer = setInterval(this.render.bind(this), 1000); } stop() { clearInterval(this.timer); } } module.exports = Dashboard;