Browse Source

Merge pull request #22 from webworker01/validateworker

Validateworker updates, code formatting, heapdump memory profiling
pull/1/head
Web Worker 5 years ago
committed by GitHub
parent
commit
6e234dedf7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      libs/paymentProcessor.js
  2. 661
      libs/stats.js
  3. 322
      website/default/static/miner_stats.js
  4. 13
      website/piratepool.io/index.html
  5. 16
      website/piratepool.io/pages/getting_started.html
  6. 26
      website/piratepool.io/pages/home.html
  7. 8
      website/piratepool.io/pages/miner_stats.html
  8. 24
      website/piratepool.io/pages/payments.html
  9. 8
      website/piratepool.io/pages/stats.html
  10. 14
      website/piratepool.io/pages/workers.html
  11. 7
      website/piratepool.io/static/payments.js
  12. 6
      website/piratepool.io/static/stats.js
  13. 67
      website/piratepool.io/static/style.css
  14. 22
      website/piratepool.io/static/workers.js

5
libs/paymentProcessor.js

@ -603,7 +603,10 @@ function SetupForPool(logger, poolOptions, setupFinished) {
let minerAddressPrefix = address.substring(0,2);
let checkPrefix = (poolOptions.minerPrefix || false);
if (privateChain && poolZAddressPrefix == 'zs' && minerAddressLength == 78 && minerAddressPrefix == 'zs') {
if (typeof poolOptions.rewardsDisabled !== 'undefined' && poolOptions.rewardsDisabled.includes(address)) {
logger.warning(logSystem, logComponent, 'Rewards disabled for this adddress: ' + address + ', convert to address ' + (poolOptions.invalidAddress || poolOptions.address));
return (poolOptions.invalidAddress || poolOptions.address);
} else if (privateChain && poolZAddressPrefix == 'zs' && minerAddressLength == 78 && minerAddressPrefix == 'zs') {
//validate as sapling
return address;
} else if (privateChain && poolZAddressPrefix == 'zc' && minerAddressLength == 95 && minerAddressPrefix == 'zc') {

661
libs/stats.js

@ -25,31 +25,31 @@ function rediscreateClient(port, host, pass) {
* @returns {Array} array of items in [[key,value],[key,value],...] format.
*/
function sortProperties(obj, sortedBy, isNumericSort, reverse) {
sortedBy = sortedBy || 1; // by default first key
isNumericSort = isNumericSort || false; // by default text sort
reverse = reverse || false; // by default no reverse
var reversed = (reverse) ? -1 : 1;
var sortable = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
sortable.push([key, obj[key]]);
}
}
if (isNumericSort)
sortable.sort(function (a, b) {
return reversed * (a[1][sortedBy] - b[1][sortedBy]);
});
else
sortable.sort(function (a, b) {
var x = a[1][sortedBy].toLowerCase(),
y = b[1][sortedBy].toLowerCase();
return x < y ? reversed * -1 : x > y ? reversed : 0;
});
return sortable; // array in format [ [ key1, val1 ], [ key2, val2 ], ... ]
sortedBy = sortedBy || 1; // by default first key
isNumericSort = isNumericSort || false; // by default text sort
reverse = reverse || false; // by default no reverse
var reversed = (reverse) ? -1 : 1;
var sortable = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
sortable.push([key, obj[key]]);
}
}
if (isNumericSort)
sortable.sort(function (a, b) {
return reversed * (a[1][sortedBy] - b[1][sortedBy]);
});
else
sortable.sort(function (a, b) {
var x = a[1][sortedBy].toLowerCase(),
y = b[1][sortedBy].toLowerCase();
return x < y ? reversed * -1 : x > y ? reversed : 0;
});
return sortable; // array in format [ [ key1, val1 ], [ key2, val2 ], ... ]
}
module.exports = function(logger, portalConfig, poolConfigs){
var _this = this;
@ -101,19 +101,29 @@ module.exports = function(logger, portalConfig, poolConfigs){
async.each(_this.stats.pools, function(pool, pcb) {
if (_this.stats.pools[pool.name].pending && _this.stats.pools[pool.name].pending.blocks)
for (var i=0; i<_this.stats.pools[pool.name].pending.blocks.length; i++)
allBlocks[pool.name+"-"+_this.stats.pools[pool.name].pending.blocks[i].split(':')[2]] = _this.stats.pools[pool.name].pending.blocks[i];
for (var i=0; i<_this.stats.pools[pool.name].pending.blocks.length; i++) {
let blockoutput = _this.stats.pools[pool.name].pending.blocks[i].split(':');
blockoutput[3] = pool.name + '-miner';
blockoutput = blockoutput.join(':');
allBlocks[pool.name+"-"+_this.stats.pools[pool.name].pending.blocks[i].split(':')[2]] = blockoutput;
}
if (_this.stats.pools[pool.name].confirmed && _this.stats.pools[pool.name].confirmed.blocks)
for (var i=0; i<_this.stats.pools[pool.name].confirmed.blocks.length; i++)
allBlocks[pool.name+"-"+_this.stats.pools[pool.name].confirmed.blocks[i].split(':')[2]] = _this.stats.pools[pool.name].confirmed.blocks[i];
for (var i=0; i<_this.stats.pools[pool.name].confirmed.blocks.length; i++) {
let blockoutput = _this.stats.pools[pool.name].confirmed.blocks[i].split(':');
blockoutput[3] = pool.name + '-miner';
blockoutput = blockoutput.join(':');
allBlocks[pool.name+"-"+_this.stats.pools[pool.name].confirmed.blocks[i].split(':')[2]] = blockoutput;
}
pcb();
}, function(err) {
cback(allBlocks);
cback(allBlocks);
});
};
function gatherStatHistory(){
var retentionTime = (((Date.now() / 1000) - portalConfig.website.stats.historicalRetention) | 0).toString();
redisStats.zrangebyscore(['statHistory', retentionTime, '+inf'], function(err, replies){
@ -133,34 +143,34 @@ module.exports = function(logger, portalConfig, poolConfigs){
});
}
function getWorkerStats(address) {
address = address.split(".")[0];
if (address.length > 0 && address.startsWith('t')) {
for (var h in statHistory) {
for(var pool in statHistory[h].pools) {
statHistory[h].pools[pool].workers.sort(sortWorkersByHashrate);
for(var w in statHistory[h].pools[pool].workers){
if (w.startsWith(address)) {
if (history[w] == null) {
history[w] = [];
}
if (workers[w] == null && stats.pools[pool].workers[w] != null) {
workers[w] = stats.pools[pool].workers[w];
}
if (statHistory[h].pools[pool].workers[w].hashrate) {
history[w].push({time: statHistory[h].time, hashrate:statHistory[h].pools[pool].workers[w].hashrate});
}
}
}
}
}
return JSON.stringify({"workers": workers, "history": history});
}
return null;
}
function getWorkerStats(address) {
address = address.split(".")[0];
if (address.length > 0 && address.startsWith('t')) {
for (var h in statHistory) {
for(var pool in statHistory[h].pools) {
statHistory[h].pools[pool].workers.sort(sortWorkersByHashrate);
for(var w in statHistory[h].pools[pool].workers){
if (w.startsWith(address)) {
if (history[w] == null) {
history[w] = [];
}
if (workers[w] == null && stats.pools[pool].workers[w] != null) {
workers[w] = stats.pools[pool].workers[w];
}
if (statHistory[h].pools[pool].workers[w].hashrate) {
history[w].push({time: statHistory[h].time, hashrate:statHistory[h].pools[pool].workers[w].hashrate});
}
}
}
}
}
return JSON.stringify({"workers": workers, "history": history});
}
return null;
}
function addStatPoolHistory(stats){
var data = {
time: stats.time,
@ -175,10 +185,10 @@ module.exports = function(logger, portalConfig, poolConfigs){
}
_this.statPoolHistory.push(data);
}
var magnitude = 100000000;
var coinPrecision = magnitude.toString().length - 1;
function roundTo(n, digits) {
if (digits === undefined) {
digits = 0;
@ -192,7 +202,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
var satoshisToCoins = function(satoshis){
return roundTo((satoshis / magnitude), coinPrecision);
};
var coinsToSatoshies = function(coins){
return Math.round(coins * magnitude);
};
@ -200,7 +210,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
function coinsRound(number) {
return roundTo(number, coinPrecision);
}
function readableSeconds(t) {
var seconds = Math.round(t);
var minutes = Math.floor(seconds/60);
@ -219,7 +229,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
_this.stats.coins = redisClients[0].coins;
cback();
};
this.getPayout = function(address, cback){
async.waterfall([
function(callback){
@ -231,38 +241,38 @@ module.exports = function(logger, portalConfig, poolConfigs){
cback(coinsRound(total).toFixed(8));
});
};
this.getTotalSharesByAddress = function(address, cback) {
var a = address.split(".")[0];
this.getTotalSharesByAddress = function(address, cback) {
var a = address.split(".")[0];
var client = redisClients[0].client,
coins = redisClients[0].coins,
shares = [];
var pindex = parseInt(0);
var totalShares = parseFloat(0);
async.each(_this.stats.pools, function(pool, pcb) {
var totalShares = parseFloat(0);
async.each(_this.stats.pools, function(pool, pcb) {
pindex++;
var coin = String(_this.stats.pools[pool.name].name);
client.hscan(coin + ':shares:roundCurrent', 0, "match", a+"*", "count", 1000, function(error, result) {
var coin = String(_this.stats.pools[pool.name].name);
client.hscan(coin + ':shares:roundCurrent', 0, "match", a+"*", "count", 1000, function(error, result) {
if (error) {
pcb(error);
return;
}
var workerName="";
var shares = 0;
for (var i in result[1]) {
if (Math.abs(i % 2) != 1) {
workerName = String(result[1][i]);
} else {
shares += parseFloat(result[1][i]);
}
}
var workerName="";
var shares = 0;
for (var i in result[1]) {
if (Math.abs(i % 2) != 1) {
workerName = String(result[1][i]);
} else {
shares += parseFloat(result[1][i]);
}
}
if (shares>0) {
totalShares = shares;
}
pcb();
});
}, function(err) {
});
}, function(err) {
if (err) {
cback(0);
return;
@ -271,37 +281,37 @@ module.exports = function(logger, portalConfig, poolConfigs){
cback(totalShares);
return;
}
});
};
});
};
this.getBalanceByAddress = function(address, cback){
var a = address.split(".")[0];
var a = address.split(".")[0];
var client = redisClients[0].client,
coins = redisClients[0].coins,
balances = [];
var totalHeld = parseFloat(0);
var totalPaid = parseFloat(0);
var totalHeld = parseFloat(0);
var totalPaid = parseFloat(0);
var totalImmature = parseFloat(0);
async.each(_this.stats.pools, function(pool, pcb) {
var coin = String(_this.stats.pools[pool.name].name);
// get all immature balances from address
client.hscan(coin + ':immature', 0, "match", a+"*", "count", 10000, function(error, pends) {
async.each(_this.stats.pools, function(pool, pcb) {
var coin = String(_this.stats.pools[pool.name].name);
// get all immature balances from address
client.hscan(coin + ':immature', 0, "match", a+"*", "count", 10000, function(error, pends) {
// get all balances from address
client.hscan(coin + ':balances', 0, "match", a+"*", "count", 10000, function(error, bals) {
// get all payouts from address
client.hscan(coin + ':payouts', 0, "match", a+"*", "count", 10000, function(error, pays) {
var workerName = "";
var balAmount = 0;
var paidAmount = 0;
var pendingAmount = 0;
var workers = {};
for (var i in pays[1]) {
if (Math.abs(i % 2) != 1) {
workerName = String(pays[1][i]);
@ -335,7 +345,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
totalImmature += pendingAmount;
}
}
for (var w in workers) {
balances.push({
worker:String(w),
@ -344,23 +354,23 @@ module.exports = function(logger, portalConfig, poolConfigs){
immature:workers[w].immature
});
}
pcb();
});
});
});
}, function(err) {
if (err) {
callback("There was an error getting balances");
return;
}
_this.stats.balances = balances;
_this.stats.address = address;
cback({totalHeld:coinsRound(totalHeld), totalPaid:coinsRound(totalPaid), totalImmature:satoshisToCoins(totalImmature), balances});
});
};
}, function(err) {
if (err) {
callback("There was an error getting balances");
return;
}
_this.stats.balances = balances;
_this.stats.address = address;
cback({totalHeld:coinsRound(totalHeld), totalPaid:coinsRound(totalPaid), totalImmature:satoshisToCoins(totalImmature), balances});
});
};
this.getGlobalStats = function(callback){
@ -379,9 +389,9 @@ module.exports = function(logger, portalConfig, poolConfigs){
['scard', ':blocksPending'],
['scard', ':blocksConfirmed'],
['scard', ':blocksKicked'],
['smembers', ':blocksPending'],
['smembers', ':blocksConfirmed'],
['hgetall', ':shares:roundCurrent'],
['smembers', ':blocksPending'],
['smembers', ':blocksConfirmed'],
['hgetall', ':shares:roundCurrent'],
['hgetall', ':blocksPendingConfirms'],
['zrange', ':payments', -100, -1],
['hgetall', ':shares:timesCurrent']
@ -411,6 +421,39 @@ module.exports = function(logger, portalConfig, poolConfigs){
marketStats = replies[i + 2] ? (JSON.parse(replies[i + 2].coinmarketcap)[0] || 0) : 0;
}
}
//anonymize currentRoundShares
let currentRoundSharesIndex = 0;
for (var worker in replies[i + 8]) {
Object.defineProperty(replies[i+8], 'worker' + currentRoundSharesIndex, Object.getOwnPropertyDescriptor(replies[i+8], worker));
delete replies[i+8][worker];
currentRoundSharesIndex++;
}
//anonymize currentRoundTimes
let currentRoundTimesIndex = 0;
for (var worker in replies[i + 11]) {
Object.defineProperty(replies[i+11], 'worker' + currentRoundTimesIndex, Object.getOwnPropertyDescriptor(replies[i+11], worker));
delete replies[i+11][worker];
currentRoundTimesIndex++;
}
//anonymize confirmed blocks
for (var b=0; b < replies[i + 7].length; b++) {
let blockoutput = replies[i + 7][b].split(':');
blockoutput[3] = coinName + '-miner';
blockoutput = blockoutput.join(':');
replies[i + 7][b] = blockoutput;
}
//anonymize pending blocks
for (var b=0; b < replies[i + 6].length; b++) {
let blockoutput = replies[i + 6][b].split(':');
blockoutput[3] = coinName + '-miner';
blockoutput = blockoutput.join(':');
replies[i + 6][b] = blockoutput;
}
var coinStats = {
name: coinName,
symbol: poolConfigs[coinName].coin.symbol.toUpperCase(),
@ -421,11 +464,11 @@ module.exports = function(logger, portalConfig, poolConfigs){
validBlocks: replies[i + 2] ? (replies[i + 2].validBlocks || 0) : 0,
invalidShares: replies[i + 2] ? (replies[i + 2].invalidShares || 0) : 0,
totalPaid: replies[i + 2] ? (replies[i + 2].totalPaid || 0) : 0,
networkBlocks: replies[i + 2] ? (replies[i + 2].networkBlocks || 0) : 0,
networkSols: replies[i + 2] ? (replies[i + 2].networkSols || 0) : 0,
networkSolsString: getReadableNetworkHashRateString(replies[i + 2] ? (replies[i + 2].networkSols || 0) : 0),
networkDiff: replies[i + 2] ? (replies[i + 2].networkDiff || 0) : 0,
networkConnections: replies[i + 2] ? (replies[i + 2].networkConnections || 0) : 0,
networkBlocks: replies[i + 2] ? (replies[i + 2].networkBlocks || 0) : 0,
networkSols: replies[i + 2] ? (replies[i + 2].networkSols || 0) : 0,
networkSolsString: getReadableNetworkHashRateString(replies[i + 2] ? (replies[i + 2].networkSols || 0) : 0),
networkDiff: replies[i + 2] ? (replies[i + 2].networkDiff || 0) : 0,
networkConnections: replies[i + 2] ? (replies[i + 2].networkConnections || 0) : 0,
networkVersion: replies[i + 2] ? (replies[i + 2].networkSubVersion || 0) : 0,
networkProtocolVersion: replies[i + 2] ? (replies[i + 2].networkProtocolVersion || 0) : 0
},
@ -437,16 +480,16 @@ module.exports = function(logger, portalConfig, poolConfigs){
orphaned: replies[i + 5]
},
/* show all pending blocks */
pending: {
blocks: replies[i + 6].sort(sortBlocks),
pending: {
blocks: replies[i + 6].sort(sortBlocks),
confirms: (replies[i + 9] || {})
},
},
/* show last 50 found blocks */
confirmed: {
blocks: replies[i + 7].sort(sortBlocks).slice(0,50)
},
confirmed: {
blocks: replies[i + 7].sort(sortBlocks).slice(0,50)
},
payments: [],
currentRoundShares: (replies[i + 8] || {}),
currentRoundShares: (replies[i + 8] || {}),
currentRoundTimes: (replies[i + 11] || {}),
maxRoundTime: 0,
shareCount: 0,
@ -459,7 +502,31 @@ module.exports = function(logger, portalConfig, poolConfigs){
} catch(e) {
jsonObj = null;
}
if (jsonObj !== null) {
if (jsonObj !== null) {
//Anonymize paid amounts
let paymentIndex = 0;
for (var payment in jsonObj.amounts) {
Object.defineProperty(jsonObj.amounts, 'miner' + paymentIndex, Object.getOwnPropertyDescriptor(jsonObj.amounts, payment));
delete jsonObj.amounts[payment];
paymentIndex++;
}
//Anonymize balances
let balanceIndex = 0;
for (var balance in jsonObj.balances) {
Object.defineProperty(jsonObj.balances, 'miner' + balanceIndex, Object.getOwnPropertyDescriptor(jsonObj.balances, balance));
delete jsonObj.balances[balance];
balanceIndex++;
}
//Anonymize work
let workIndex = 0;
for (var work in jsonObj.work) {
Object.defineProperty(jsonObj.work, 'miner' + workIndex, Object.getOwnPropertyDescriptor(jsonObj.work, work));
delete jsonObj.work[work];
workIndex++;
}
coinStats.payments.push(jsonObj);
}
}
@ -491,103 +558,120 @@ module.exports = function(logger, portalConfig, poolConfigs){
Object.keys(allCoinStats).forEach(function(coin){
var coinStats = allCoinStats[coin];
coinStats.workers = {};
coinStats.miners = {};
coinStats.miners = {};
coinStats.shares = 0;
coinStats.hashrates.forEach(function(ins){
var parts = ins.split(':');
var workerShares = parseFloat(parts[0]);
var miner = parts[1].split('.')[0];
var miner = parts[1].split('.')[0];
var worker = parts[1];
var diff = Math.round(parts[0] * 8192);
var diff = Math.round(parts[0] * 8192);
if (workerShares > 0) {
coinStats.shares += workerShares;
// build worker stats
// build worker stats
if (worker in coinStats.workers) {
coinStats.workers[worker].shares += workerShares;
coinStats.workers[worker].diff = diff;
coinStats.workers[worker].diff = diff;
} else {
coinStats.workers[worker] = {
name: worker,
diff: diff,
name: worker,
diff: diff,
shares: workerShares,
invalidshares: 0,
currRoundShares: 0,
currRoundShares: 0,
currRoundTime: 0,
hashrate: null,
hashrate: null,
hashrateString: null,
luckDays: null,
luckHours: null,
paid: 0,
balance: 0
luckDays: null,
luckHours: null,
paid: 0,
balance: 0
};
}
// build miner stats
if (miner in coinStats.miners) {
coinStats.miners[miner].shares += workerShares;
} else {
coinStats.miners[miner] = {
name: miner,
shares: workerShares,
invalidshares: 0,
currRoundShares: 0,
}
// build miner stats
if (miner in coinStats.miners) {
coinStats.miners[miner].shares += workerShares;
} else {
coinStats.miners[miner] = {
name: miner,
shares: workerShares,
invalidshares: 0,
currRoundShares: 0,
currRoundTime: 0,
hashrate: null,
hashrateString: null,
luckDays: null,
luckHours: null
};
}
}
else {
// build worker stats
hashrate: null,
hashrateString: null,
luckDays: null,
luckHours: null
};
}
} else {
// build worker stats
if (worker in coinStats.workers) {
coinStats.workers[worker].invalidshares -= workerShares; // workerShares is negative number!
coinStats.workers[worker].diff = diff;
coinStats.workers[worker].diff = diff;
} else {
coinStats.workers[worker] = {
name: worker,
diff: diff,
name: worker,
diff: diff,
shares: 0,
invalidshares: -workerShares,
currRoundShares: 0,
invalidshares: -workerShares,
currRoundShares: 0,
currRoundTime: 0,
hashrate: null,
hashrate: null,
hashrateString: null,
luckDays: null,
luckHours: null,
paid: 0,
balance: 0
luckDays: null,
luckHours: null,
paid: 0,
balance: 0
};
}
// build miner stats
if (miner in coinStats.miners) {
coinStats.miners[miner].invalidshares -= workerShares; // workerShares is negative number!
} else {
coinStats.miners[miner] = {
name: miner,
shares: 0,
invalidshares: -workerShares,
currRoundShares: 0,
}
// build miner stats
if (miner in coinStats.miners) {
coinStats.miners[miner].invalidshares -= workerShares; // workerShares is negative number!
} else {
coinStats.miners[miner] = {
name: miner,
shares: 0,
invalidshares: -workerShares,
currRoundShares: 0,
currRoundTime: 0,
hashrate: null,
hashrateString: null,
luckDays: null,
luckHours: null
};
}
hashrate: null,
hashrateString: null,
luckDays: null,
luckHours: null
};
}
}
});
//anonymize miners
let minerindex = 0;
for (var miner in coinStats.miners) {
Object.defineProperty(coinStats.miners, 'miner' + minerindex, Object.getOwnPropertyDescriptor(coinStats.miners, miner));
coinStats.miners['miner' + minerindex].name = 'miner' + minerindex;
delete coinStats.miners[miner];
minerindex++;
}
//anonymize workers
let workerindex = 0;
for (var worker in coinStats.workers) {
Object.defineProperty(coinStats.workers, 'worker' + workerindex, Object.getOwnPropertyDescriptor(coinStats.workers, worker));
coinStats.workers['worker' + workerindex].name = 'worker' + workerindex;
delete coinStats.workers[worker];
workerindex++;
}
var shareMultiplier = Math.pow(2, 32) / algos[coinStats.algorithm].multiplier;
coinStats.hashrate = shareMultiplier * coinStats.shares / portalConfig.website.stats.hashrateWindow;
coinStats.hashrateString = _this.getReadableHashRateString(coinStats.hashrate);
var _blocktime = 160;
var _networkHashRate = parseFloat(coinStats.poolStats.networkSols) * 1.2;
var _myHashRate = (coinStats.hashrate / 1000000) * 2;
coinStats.luckDays = ((_networkHashRate / _myHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3);
coinStats.luckHours = ((_networkHashRate / _myHashRate * _blocktime) / (60 * 60)).toFixed(3);
coinStats.minerCount = Object.keys(coinStats.miners).length;
var _networkHashRate = parseFloat(coinStats.poolStats.networkSols) * 1.2;
var _myHashRate = (coinStats.hashrate / 1000000) * 2;
coinStats.luckDays = ((_networkHashRate / _myHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3);
coinStats.luckHours = ((_networkHashRate / _myHashRate * _blocktime) / (60 * 60)).toFixed(3);
coinStats.minerCount = Object.keys(coinStats.miners).length;
coinStats.workerCount = Object.keys(coinStats.workers).length;
portalStats.global.workers += coinStats.workerCount;
@ -627,29 +711,29 @@ module.exports = function(logger, portalConfig, poolConfigs){
coinStats.shareCount = _shareTotal;
coinStats.maxRoundTime = _maxTimeShare;
coinStats.maxRoundTimeString = readableSeconds(_maxTimeShare);
for (var worker in coinStats.workers) {
var _workerRate = shareMultiplier * coinStats.workers[worker].shares / portalConfig.website.stats.hashrateWindow;
var _wHashRate = (_workerRate / 1000000) * 2;
coinStats.workers[worker].luckDays = ((_networkHashRate / _wHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3);
coinStats.workers[worker].luckHours = ((_networkHashRate / _wHashRate * _blocktime) / (60 * 60)).toFixed(3);
coinStats.workers[worker].hashrate = _workerRate;
coinStats.workers[worker].hashrateString = _this.getReadableHashRateString(_workerRate);
var miner = worker.split('.')[0];
if (miner in coinStats.miners) {
coinStats.workers[worker].currRoundTime = coinStats.miners[miner].currRoundTime;
}
var _workerRate = shareMultiplier * coinStats.workers[worker].shares / portalConfig.website.stats.hashrateWindow;
var _wHashRate = (_workerRate / 1000000) * 2;
coinStats.workers[worker].luckDays = ((_networkHashRate / _wHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3);
coinStats.workers[worker].luckHours = ((_networkHashRate / _wHashRate * _blocktime) / (60 * 60)).toFixed(3);
coinStats.workers[worker].hashrate = _workerRate;
coinStats.workers[worker].hashrateString = _this.getReadableHashRateString(_workerRate);
var miner = worker.split('.')[0];
if (miner in coinStats.miners) {
coinStats.workers[worker].currRoundTime = coinStats.miners[miner].currRoundTime;
}
}
for (var miner in coinStats.miners) {
var _workerRate = shareMultiplier * coinStats.miners[miner].shares / portalConfig.website.stats.hashrateWindow;
var _wHashRate = (_workerRate / 1000000) * 2;
coinStats.miners[miner].luckDays = ((_networkHashRate / _wHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3);
coinStats.miners[miner].luckHours = ((_networkHashRate / _wHashRate * _blocktime) / (60 * 60)).toFixed(3);
coinStats.miners[miner].hashrate = _workerRate;
coinStats.miners[miner].hashrateString = _this.getReadableHashRateString(_workerRate);
for (var miner in coinStats.miners) {
var _workerRate = shareMultiplier * coinStats.miners[miner].shares / portalConfig.website.stats.hashrateWindow;
var _wHashRate = (_workerRate / 1000000) * 2;
coinStats.miners[miner].luckDays = ((_networkHashRate / _wHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3);
coinStats.miners[miner].luckHours = ((_networkHashRate / _wHashRate * _blocktime) / (60 * 60)).toFixed(3);
coinStats.miners[miner].hashrate = _workerRate;
coinStats.miners[miner].hashrateString = _this.getReadableHashRateString(_workerRate);
}
// sort workers by name
// sort workers by name
coinStats.workers = sortWorkersByName(coinStats.workers);
coinStats.miners = sortMinersByHashrate(coinStats.miners);
@ -666,7 +750,7 @@ module.exports = function(logger, portalConfig, poolConfigs){
portalStats.pools = sortPoolsByHashrate(portalStats.pools);
_this.stats = portalStats;
// save historical hashrate, not entire stats!
var saveStats = JSON.parse(JSON.stringify(portalStats));
Object.keys(saveStats.pools).forEach(function(pool){
@ -679,9 +763,9 @@ module.exports = function(logger, portalConfig, poolConfigs){
});
_this.statsString = JSON.stringify(saveStats);
_this.statHistory.push(saveStats);
addStatPoolHistory(portalStats);
addStatPoolHistory(portalStats);
var retentionTime = (((Date.now() / 1000) - portalConfig.website.stats.historicalRetention) | 0);
for (var i = 0; i < _this.statHistory.length; i++){
@ -701,42 +785,43 @@ module.exports = function(logger, portalConfig, poolConfigs){
if (err)
logger.error(logSystem, 'Historics', 'Error adding stats to historics ' + JSON.stringify(err));
});
callback();
});
};
function sortPoolsByName(objects) {
var newObject = {};
var sortedArray = sortProperties(objects, 'name', false, false);
for (var i = 0; i < sortedArray.length; i++) {
var key = sortedArray[i][0];
var value = sortedArray[i][1];
newObject[key] = value;
}
return newObject;
var newObject = {};
var sortedArray = sortProperties(objects, 'name', false, false);
for (var i = 0; i < sortedArray.length; i++) {
var key = sortedArray[i][0];
var value = sortedArray[i][1];
newObject[key] = value;
}
return newObject;
}
function sortPoolsByHashrate(objects) {
var newObject = {};
var sortedArray = sortProperties(objects, 'hashrate', true, true);
for (var i = 0; i < sortedArray.length; i++) {
var key = sortedArray[i][0];
var value = sortedArray[i][1];
newObject[key] = value;
}
return newObject;
var newObject = {};
var sortedArray = sortProperties(objects, 'hashrate', true, true);
for (var i = 0; i < sortedArray.length; i++) {
var key = sortedArray[i][0];
var value = sortedArray[i][1];
newObject[key] = value;
}
return newObject;
}
function sortPoolsByShares(objects) {
var newObject = {};
var sortedArray = sortProperties(objects, 'shareSort', true, true);
for (var i = 0; i < sortedArray.length; i++) {
var key = sortedArray[i][0];
var value = sortedArray[i][1];
newObject[key] = value;
}
return newObject;
var newObject = {};
var sortedArray = sortProperties(objects, 'shareSort', true, true);
for (var i = 0; i < sortedArray.length; i++) {
var key = sortedArray[i][0];
var value = sortedArray[i][1];
newObject[key] = value;
}
return newObject;
}
function sortBlocks(a, b) {
@ -746,56 +831,56 @@ module.exports = function(logger, portalConfig, poolConfigs){
if (as < bs) return 1;
return 0;
}
function sortWorkersByName(objects) {
var newObject = {};
var sortedArray = sortProperties(objects, 'name', false, false);
for (var i = 0; i < sortedArray.length; i++) {
var key = sortedArray[i][0];
var value = sortedArray[i][1];
newObject[key] = value;
}
return newObject;
}
function sortMinersByHashrate(objects) {
var newObject = {};
var sortedArray = sortProperties(objects, 'hashrate', true, true);
for (var i = 0; i < sortedArray.length; i++) {
var key = sortedArray[i][0];
var value = sortedArray[i][1];
newObject[key] = value;
}
return newObject;
}
function sortWorkersByHashrate(a, b) {
if (a.hashrate === b.hashrate) {
return 0;
}
else {
return (a.hashrate < b.hashrate) ? -1 : 1;
}
}
function sortWorkersByName(objects) {
var newObject = {};
var sortedArray = sortProperties(objects, 'name', false, false);
for (var i = 0; i < sortedArray.length; i++) {
var key = sortedArray[i][0];
var value = sortedArray[i][1];
newObject[key] = value;
}
return newObject;
}
function sortMinersByHashrate(objects) {
var newObject = {};
var sortedArray = sortProperties(objects, 'hashrate', true, true);
for (var i = 0; i < sortedArray.length; i++) {
var key = sortedArray[i][0];
var value = sortedArray[i][1];
newObject[key] = value;
}
return newObject;
}
function sortWorkersByHashrate(a, b) {
if (a.hashrate === b.hashrate) {
return 0;
}
else {
return (a.hashrate < b.hashrate) ? -1 : 1;
}
}
this.getReadableHashRateString = function(hashrate){
hashrate = (hashrate * 2);
if (hashrate < 1000000) {
return (Math.round(hashrate / 1000) / 1000 ).toFixed(2)+' Sol/s';
}
hashrate = (hashrate * 2);
if (hashrate < 1000000) {
return (Math.round(hashrate / 1000) / 1000 ).toFixed(2)+' Sol/s';
}
var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ];
var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1);
hashrate = (hashrate/1000) / Math.pow(1000, i + 1);
return hashrate.toFixed(2) + byteUnits[i];
};
function getReadableNetworkHashRateString(hashrate) {
hashrate = (hashrate * 1000000);
if (hashrate < 1000000)
return '0 Sol';
var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ];
var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1);
hashrate = (hashrate/1000) / Math.pow(1000, i + 1);
return hashrate.toFixed(2) + byteUnits[i];
}
function getReadableNetworkHashRateString(hashrate) {
hashrate = (hashrate * 1000000);
if (hashrate < 1000000)
return '0 Sol';
var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ];
var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1);
hashrate = (hashrate/1000) / Math.pow(1000, i + 1);
return hashrate.toFixed(2) + byteUnits[i];
}
};

322
website/default/static/miner_stats.js

@ -10,14 +10,14 @@ var totalPaid;
var totalShares;
function getReadableHashRateString(hashrate){
hashrate = (hashrate * 2);
if (hashrate < 1000000) {
return (Math.round(hashrate / 1000) / 1000 ).toFixed(2)+' Sol/s';
}
var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ];
var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1);
hashrate = (hashrate/1000) / Math.pow(1000, i + 1);
return hashrate.toFixed(2) + byteUnits[i];
hashrate = (hashrate * 2);
if (hashrate < 1000000) {
return (Math.round(hashrate / 1000) / 1000 ).toFixed(2)+' Sol/s';
}
var byteUnits = [ ' Sol/s', ' KSol/s', ' MSol/s', ' GSol/s', ' TSol/s', ' PSol/s' ];
var i = Math.floor((Math.log(hashrate/1000) / Math.log(1000)) - 1);
hashrate = (hashrate/1000) / Math.pow(1000, i + 1);
return hashrate.toFixed(2) + byteUnits[i];
}
function timeOfDayFormat(timestamp){
@ -27,95 +27,95 @@ function timeOfDayFormat(timestamp){
}
function getWorkerNameFromAddress(w) {
var worker = w;
if (w.split(".").length > 1) {
worker = w.split(".")[1];
if (worker == null || worker.length < 1) {
worker = "noname";
}
} else {
worker = "noname";
}
return worker;
var worker = w;
if (w.split(".").length > 1) {
worker = w.split(".")[1];
if (worker == null || worker.length < 1) {
worker = "noname";
}
} else {
worker = "noname";
}
return worker;
}
function buildChartData(){
var workers = {};
for (var w in statData.history) {
var worker = getWorkerNameFromAddress(w);
var a = workers[worker] = (workers[worker] || {
hashrate: []
});
for (var wh in statData.history[w]) {
a.hashrate.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]);
}
if (a.hashrate.length > workerHistoryMax) {
workerHistoryMax = a.hashrate.length;
}
}
var i=0;
for (var w in statData.history) {
var worker = getWorkerNameFromAddress(w);
var a = workers[worker] = (workers[worker] || {
hashrate: []
});
for (var wh in statData.history[w]) {
a.hashrate.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]);
}
if (a.hashrate.length > workerHistoryMax) {
workerHistoryMax = a.hashrate.length;
}
}
var i=0;
workerHashrateData = [];
for (var worker in workers){
workerHashrateData.push({
key: worker,
disabled: (i > Math.min((_workerCount-1), 3)),
disabled: (i > Math.min((_workerCount-1), 3)),
values: workers[worker].hashrate
});
i++;
i++;
}
}
function updateChartData(){
var workers = {};
for (var w in statData.history) {
var worker = getWorkerNameFromAddress(w);
// get a reference to lastest workerhistory
for (var wh in statData.history[w]) { }
//var wh = statData.history[w][statData.history[w].length - 1];
var foundWorker = false;
for (var i = 0; i < workerHashrateData.length; i++) {
if (workerHashrateData[i].key === worker) {
foundWorker = true;
if (workerHashrateData[i].values.length >= workerHistoryMax) {
workerHashrateData[i].values.shift();
}
workerHashrateData[i].values.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]);
break;
}
}
if (!foundWorker) {
var hashrate = [];
hashrate.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]);
workerHashrateData.push({
key: worker,
values: hashrate
});
rebuildWorkerDisplay();
return true;
}
}
triggerChartUpdates();
return false;
for (var w in statData.history) {
var worker = getWorkerNameFromAddress(w);
// get a reference to lastest workerhistory
for (var wh in statData.history[w]) { }
//var wh = statData.history[w][statData.history[w].length - 1];
var foundWorker = false;
for (var i = 0; i < workerHashrateData.length; i++) {
if (workerHashrateData[i].key === worker) {
foundWorker = true;
if (workerHashrateData[i].values.length >= workerHistoryMax) {
workerHashrateData[i].values.shift();
}
workerHashrateData[i].values.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]);
break;
}
}
if (!foundWorker) {
var hashrate = [];
hashrate.push([statData.history[w][wh].time * 1000, statData.history[w][wh].hashrate]);
workerHashrateData.push({
key: worker,
values: hashrate
});
rebuildWorkerDisplay();
return true;
}
}
triggerChartUpdates();
return false;
}
function calculateAverageHashrate(worker) {
var count = 0;
var total = 1;
var avg = 0;
for (var i = 0; i < workerHashrateData.length; i++) {
count = 0;
for (var ii = 0; ii < workerHashrateData[i].values.length; ii++) {
if (worker == null || workerHashrateData[i].key === worker) {
count++;
avg += parseFloat(workerHashrateData[i].values[ii][1]);
}
}
if (count > total)
total = count;
}
avg = avg / total;
return avg;
var count = 0;
var total = 1;
var avg = 0;
for (var i = 0; i < workerHashrateData.length; i++) {
count = 0;
for (var ii = 0; ii < workerHashrateData[i].values.length; ii++) {
if (worker == null || workerHashrateData[i].key === worker) {
count++;
avg += parseFloat(workerHashrateData[i].values[ii][1]);
}
}
if (count > total)
total = count;
}
avg = avg / total;
return avg;
}
function triggerChartUpdates(){
@ -141,67 +141,67 @@ function displayCharts() {
}
function updateStats() {
totalHash = statData.totalHash;
totalPaid = statData.paid;
totalBal = statData.balance;
totalImmature = statData.immature;
totalShares = statData.totalShares;
// do some calculations
var _blocktime = 250;
var _networkHashRate = parseFloat(statData.networkSols) * 1.2;
var _myHashRate = (totalHash / 1000000) * 2;
var luckDays = ((_networkHashRate / _myHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3);
// update miner stats
$("#statsHashrate").text(getReadableHashRateString(totalHash));
$("#statsHashrateAvg").text(getReadableHashRateString(calculateAverageHashrate(null)));
$("#statsLuckDays").text(luckDays);
$("#statsTotalImmature").text(totalImmature);
$("#statsTotalBal").text(totalBal);
$("#statsTotalPaid").text(totalPaid);
$("#statsTotalShares").text(totalShares.toFixed(2));
totalHash = statData.totalHash;
totalPaid = statData.paid;
totalBal = statData.balance;
totalImmature = statData.immature;
totalShares = statData.totalShares;
// do some calculations
var _blocktime = 250;
var _networkHashRate = parseFloat(statData.networkSols) * 1.2;
var _myHashRate = (totalHash / 1000000) * 2;
var luckDays = ((_networkHashRate / _myHashRate * _blocktime) / (24 * 60 * 60)).toFixed(3);
// update miner stats
$("#statsHashrate").text(getReadableHashRateString(totalHash));
$("#statsHashrateAvg").text(getReadableHashRateString(calculateAverageHashrate(null)));
$("#statsLuckDays").text(luckDays);
$("#statsTotalImmature").text(totalImmature);
$("#statsTotalBal").text(totalBal);
$("#statsTotalPaid").text(totalPaid);
$("#statsTotalShares").text(totalShares.toFixed(2));
}
function updateWorkerStats() {
// update worker stats
var i=0;
for (var w in statData.workers) { i++;
var htmlSafeWorkerName = w.split('.').join('_').replace(/[^\w\s]/gi, '');
var saneWorkerName = getWorkerNameFromAddress(w);
$("#statsHashrate"+htmlSafeWorkerName).text(getReadableHashRateString(statData.workers[w].hashrate));
$("#statsHashrateAvg"+htmlSafeWorkerName).text(getReadableHashRateString(calculateAverageHashrate(saneWorkerName)));
$("#statsLuckDays"+htmlSafeWorkerName).text(statData.workers[w].luckDays);
$("#statsPaid"+htmlSafeWorkerName).text(statData.workers[w].paid);
$("#statsBalance"+htmlSafeWorkerName).text(statData.workers[w].balance);
$("#statsShares"+htmlSafeWorkerName).text(Math.round(statData.workers[w].currRoundShares * 100) / 100);
$("#statsDiff"+htmlSafeWorkerName).text(statData.workers[w].diff);
}
// update worker stats
var i=0;
for (var w in statData.workers) { i++;
var htmlSafeWorkerName = w.split('.').join('_').replace(/[^\w\s]/gi, '');
var saneWorkerName = getWorkerNameFromAddress(w);
$("#statsHashrate"+htmlSafeWorkerName).text(getReadableHashRateString(statData.workers[w].hashrate));
$("#statsHashrateAvg"+htmlSafeWorkerName).text(getReadableHashRateString(calculateAverageHashrate(saneWorkerName)));
$("#statsLuckDays"+htmlSafeWorkerName).text(statData.workers[w].luckDays);
$("#statsPaid"+htmlSafeWorkerName).text(statData.workers[w].paid);
$("#statsBalance"+htmlSafeWorkerName).text(statData.workers[w].balance);
$("#statsShares"+htmlSafeWorkerName).text(Math.round(statData.workers[w].currRoundShares * 100) / 100);
$("#statsDiff"+htmlSafeWorkerName).text(statData.workers[w].diff);
}
}
function addWorkerToDisplay(name, htmlSafeName, workerObj) {
var htmlToAdd = "";
htmlToAdd = '<div class="boxStats" id="boxStatsLeft" style="float:left; margin: 9px; min-width: 260px;"><div class="boxStatsList">';
if (htmlSafeName.indexOf("_") >= 0) {
htmlToAdd+= '<div class="boxLowerHeader">'+htmlSafeName.substr(htmlSafeName.indexOf("_")+1,htmlSafeName.length)+'</div>';
} else {
htmlToAdd+= '<div class="boxLowerHeader">noname</div>';
}
htmlToAdd+='<div><i class="fa fa-tachometer"></i> <span id="statsHashrate'+htmlSafeName+'">'+getReadableHashRateString(workerObj.hashrate)+'</span> (Now)</div>';
htmlToAdd+='<div><i class="fa fa-tachometer"></i> <span id="statsHashrateAvg'+htmlSafeName+'">'+getReadableHashRateString(calculateAverageHashrate(name))+'</span> (Avg)</div>';
htmlToAdd+='<div><i class="fa fa-shield"></i> <small>Diff:</small> <span id="statsDiff'+htmlSafeName+'">'+workerObj.diff+'</span></div>';
htmlToAdd+='<div><i class="fa fa-cog"></i> <small>Shares:</small> <span id="statsShares'+htmlSafeName+'">'+(Math.round(workerObj.currRoundShares * 100) / 100)+'</span></div>';
htmlToAdd+='<div><i class="fa fa-gavel"></i> <small>Luck <span id="statsLuckDays'+htmlSafeName+'">'+workerObj.luckDays+'</span> Days</small></div>';
htmlToAdd+='<div><i class="fa fa-money"></i> <small>Bal: <span id="statsBalance'+htmlSafeName+'">'+workerObj.balance+'</span></small></div>';
htmlToAdd+='<div><i class="fa fa-money"></i> <small>Paid: <span id="statsPaid'+htmlSafeName+'">'+workerObj.paid+'</span></small></div>';
htmlToAdd+='</div></div></div>';
$("#boxesWorkers").html($("#boxesWorkers").html()+htmlToAdd);
var htmlToAdd = "";
htmlToAdd = '<div class="boxStats" id="boxStatsLeft" style="float:left; margin: 9px; min-width: 260px;"><div class="boxStatsList">';
if (htmlSafeName.indexOf("_") >= 0) {
htmlToAdd+= '<div class="boxLowerHeader">'+htmlSafeName.substr(htmlSafeName.indexOf("_")+1,htmlSafeName.length)+'</div>';
} else {
htmlToAdd+= '<div class="boxLowerHeader">noname</div>';
}
htmlToAdd+='<div><i class="fa fa-tachometer"></i> <span id="statsHashrate'+htmlSafeName+'">'+getReadableHashRateString(workerObj.hashrate)+'</span> (Now)</div>';
htmlToAdd+='<div><i class="fa fa-tachometer"></i> <span id="statsHashrateAvg'+htmlSafeName+'">'+getReadableHashRateString(calculateAverageHashrate(name))+'</span> (Avg)</div>';
htmlToAdd+='<div><i class="fa fa-shield"></i> <small>Diff:</small> <span id="statsDiff'+htmlSafeName+'">'+workerObj.diff+'</span></div>';
htmlToAdd+='<div><i class="fa fa-cog"></i> <small>Shares:</small> <span id="statsShares'+htmlSafeName+'">'+(Math.round(workerObj.currRoundShares * 100) / 100)+'</span></div>';
htmlToAdd+='<div><i class="fa fa-gavel"></i> <small>Luck <span id="statsLuckDays'+htmlSafeName+'">'+workerObj.luckDays+'</span> Days</small></div>';
htmlToAdd+='<div><i class="fa fa-money"></i> <small>Bal: <span id="statsBalance'+htmlSafeName+'">'+workerObj.balance+'</span></small></div>';
htmlToAdd+='<div><i class="fa fa-money"></i> <small>Paid: <span id="statsPaid'+htmlSafeName+'">'+workerObj.paid+'</span></small></div>';
htmlToAdd+='</div></div></div>';
$("#boxesWorkers").html($("#boxesWorkers").html()+htmlToAdd);
}
function rebuildWorkerDisplay() {
$("#boxesWorkers").html("");
var i=0;
for (var w in statData.workers) { i++;
var htmlSafeWorkerName = w.split('.').join('_').replace(/[^\w\s]/gi, '');
var saneWorkerName = getWorkerNameFromAddress(w);
addWorkerToDisplay(saneWorkerName, htmlSafeWorkerName, statData.workers[w]);
}
$("#boxesWorkers").html("");
var i=0;
for (var w in statData.workers) { i++;
var htmlSafeWorkerName = w.split('.').join('_').replace(/[^\w\s]/gi, '');
var saneWorkerName = getWorkerNameFromAddress(w);
addWorkerToDisplay(saneWorkerName, htmlSafeWorkerName, statData.workers[w]);
}
}
// resize chart on window resize
@ -210,37 +210,37 @@ nv.utils.windowResize(triggerChartUpdates);
// grab initial stats
$.getJSON('/api/worker_stats?'+_miner, function(data){
statData = data;
for (var w in statData.workers) { _workerCount++; }
buildChartData();
displayCharts();
rebuildWorkerDisplay();
for (var w in statData.workers) { _workerCount++; }
buildChartData();
displayCharts();
rebuildWorkerDisplay();
updateStats();
});
// live stat updates
statsSource.addEventListener('message', function(e){
// TODO, create miner_live_stats...
// miner_live_stats will return the same josn except without the worker history
// FOR NOW, use this to grab updated stats
$.getJSON('/api/worker_stats?'+_miner, function(data){
statData = data;
// check for missing workers
var wc = 0;
var rebuilt = false;
// update worker stats
for (var w in statData.workers) { wc++; }
// TODO, this isn't 100% fool proof!
if (_workerCount != wc) {
if (_workerCount > wc) {
rebuildWorkerDisplay();
rebuilt = true;
}
_workerCount = wc;
}
rebuilt = (rebuilt || updateChartData());
updateStats();
if (!rebuilt) {
updateWorkerStats();
}
});
// TODO, create miner_live_stats...
// miner_live_stats will return the same josn except without the worker history
// FOR NOW, use this to grab updated stats
$.getJSON('/api/worker_stats?'+_miner, function(data){
statData = data;
// check for missing workers
var wc = 0;
var rebuilt = false;
// update worker stats
for (var w in statData.workers) { wc++; }
// TODO, this isn't 100% fool proof!
if (_workerCount != wc) {
if (_workerCount > wc) {
rebuildWorkerDisplay();
rebuilt = true;
}
_workerCount = wc;
}
rebuilt = (rebuilt || updateChartData());
updateStats();
if (!rebuilt) {
updateWorkerStats();
}
});
});

13
website/piratepool.io/index.html

@ -7,7 +7,7 @@
<title>piratepool.io - mining pool for PirateChain (ARRR) - the most private and anonymous mineable cryptocurrency - Pirate</title>
<meta name="description" content="The first and largest mining pool for PirateChain (ARRR). Low fees with some proceeds donated to development and marketing efforts. The most private and anonymous cryptocurrency in existence is mineable here on the Equihash algorithm by CPU, GPU, ASIC, NiceHash. - Pirate">
<meta name="description" content="The first and largest mining pool for PirateChain (ARRR). Low fees with 66% of proceeds donated to development and marketing efforts. The most private and anonymous cryptocurrency in existence is mineable here on the Equihash algorithm by CPU, GPU, ASIC, NiceHash. - Pirate">
<meta name="keywords" content="PirateChain,Pirate,ARRR,mining,pool,equihash,komodo,dpow,privacy,private,freedom">
<meta name="robots" content="index, follow">
@ -15,20 +15,21 @@
<meta property="og:type" content="website">
<meta property="og:title" content="PiratePool.io - mining pool for PirateChain (ARRR) - the most private mineable cryptocurrency - Pirate">
<meta property="og:site_name" content="PiratePool.io - mining pool for PirateChain (ARRR)">
<meta property="og:description" content="The first and largest mining pool for PirateChain (ARRR). Low fees with some proceeds donated to development and marketing efforts. The most private and anonymous cryptocurrency in existence is mineable here on the Equihash algorithm by CPU, GPU, ASIC, NiceHash. - Pirate">
<meta property="og:description" content="The first and largest mining pool for PirateChain (ARRR). Low fees with 66% of proceeds donated to development and marketing efforts. The most private and anonymous cryptocurrency in existence is mineable here on the Equihash algorithm by CPU, GPU, ASIC, NiceHash. - Pirate">
<meta property="og:url" content="https://piratepool.io">
<meta property="og:image" content="https://piratepool.io/static/pirate128.png">
<meta property="og:image:secure_url" content="https://piratepool.io/static/pirate128.png">
<meta property="og:image:width" content="128">
<meta property="og:image:height" content="128">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:description" content="The first and largest mining pool for PirateChain (ARRR). Low fees with some proceeds donated to development and marketing efforts. The most private and anonymous cryptocurrency in existence is mineable here on the Equihash algorithm by CPU, GPU, ASIC, NiceHash. - Pirate">
<meta name="twitter:description" content="The first and largest mining pool for PirateChain (ARRR). Low fees with 66% of proceeds donated to development and marketing efforts. The most private and anonymous cryptocurrency in existence is mineable here on the Equihash algorithm by CPU, GPU, ASIC, NiceHash. - Pirate">
<meta name="twitter:title" content="PiratePool.io - mining pool for PirateChain (ARRR) - the most private mineable cryptocurrency - Pirate">
<meta name="twitter:site" content="@webworker01">
<meta name="twitter:image" content="https://piratepool.io/static/pirate128.png">
<meta name="twitter:creator" content="@webworker01">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Bai+Jamjuree|Roboto" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Bai+Jamjuree|Roboto" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous" />
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/1.0.0/base-min.css" integrity="sha256-XsW+lsCsaHybdLLnHWsTuwb9A2NuD2hVVlsxtiipTZQ=" crossorigin="anonymous" />
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/pure/1.0.0/pure-min.css" integrity="sha256-Q0zCrUs2IfXWYx0uMKJfG93CvF6oVII21waYsAV4/8Q=" crossorigin="anonymous" />
@ -93,9 +94,9 @@
{{=it.page}}
</main>
<footer>
No warranties matey! If ye be 'aving any troubles, invoke yarrr right t' parlay at <a href="https://discord.gg/rZCXtCC" target="_blank" rel="noopener noreferrer" class="highlight">#pirate</a>
No warranties matey! If ye be 'aving any troubles, invoke yarrr right t' parlay at <!-- <a href="https://discord.gg/rZCXtCC" target="_blank" rel="noopener noreferrer" class="highlight">#pirate</a> --> <a href="https://discord.gg/ASMfX7B" target="_blank" rel="nofollow noreferrer noopener" class="highlight">#piratepool</a>
<br>
&lt;3 <a href="https://webworker.sh" alt="webworker01" target="_blank" rel="noopener noreferrer">🐸</a> &middot; Built with <a href="https://github.com/webworker01/knomp" target="_blank" rel="noopener noreferrer" class="highlight">knomp</a>
&lt;3 <a href="https://webworker.sh" alt="webworker01" target="_blank" rel="noopener noreferrer">🕷️</a> &middot; Built with <a href="https://github.com/webworker01/knomp" target="_blank" rel="noopener noreferrer" class="highlight">knomp</a>
</footer>
</body>
</html>

16
website/piratepool.io/pages/getting_started.html

@ -110,20 +110,20 @@
</code>
<code>
<h3 class="coinInfoHeader">Optiminer</h3>
optiminer-zcash -s {{=it.portalConfig.website.stratumHost}}:{{= Object.keys(it.poolsConfigs[Object.keys(it.poolsConfigs)[0]].ports)[0] }} -u zs1nrn7h684wq4429pz8a20r49dmmhd3ey07u38f8m2n9du33ashd0xcnls3lfz0spdvn26z3r4jrv<span class="highlight">.myrigname</span> -p x
optiminer-zcash -s {{=it.portalConfig.website.stratumHost}}:{{= Object.keys(it.poolsConfigs[Object.keys(it.poolsConfigs)[0]].ports)[0] }} -u zs1nrn7h684wq4429pz8a20r49dmmhd3ey07u38f8m2n9du33ashd0xcnls3lfz0spdvn26z3r4jrv<span class="highlight">.myrigname</span> -p x
</code>
{{ } }}
</div>
<h1 class="menuHeader" id="payments">Payments</h1>
<div class="gettingStartedContent">
<p>Payouts are currently scheduled once every 4 hours with a minimum payout of 42 ARRR.</p>
<p>Payouts are currently scheduled once every 4 hours with a minimum payout of 21 ARRR.</p>
<p>There is a limit of ~200 recipients that can be included in a single payout, so the pool payouts are monitored and the min payout adjusted accordingly to ensure a constant flow of payments.</p>
<p>If payments stop going out, do not worry! Funds are safu! Blocks can still be found and will be credited to your worker! Please check the <a href="https://discord.gg/rZCXtCC">#pools-and-operators channel in discord</a> to see if it's already being worked on.</p>
<p>If payments stop going out, do not worry! Funds are safu! Blocks can still be found and will be credited to your worker! Please check <!-- the <a href="https://discord.gg/rZCXtCC">#pools-and-operators channel in discord</a>--><a href="https://discord.gg/ASMfX7B" target="_blank" rel="nofollow noreferrer noopener" class="highlight">#piratepool in discord</a> to see if it's already being worked on.</p>
<p>Pending blocks have not yet been scanned by the payment processor. After being scanned, blocks will need to receive both <a href="https://komodoplatform.com/security-delayed-proof-of-work-dpow/" target="_blank" rel="noopener noreferrer">dPoW notarization</a> and 10 confirmations before being actually paid out.</p>
<p>On your worker stats page, <em class="highlight">pending</em> balance is the remaining estimated amount to be paid for blocks that
were scanned but not yet eligible for payout either because of
<a href="https://komodoplatform.com/new-feature-to-verify-dpow-notarizations/" target="_blank" rel="noopener noreferrer">dPoW</a> or min confirmations.
<p>On your worker stats page, <em class="highlight">pending</em> balance is the remaining estimated amount to be paid for blocks that
were scanned but not yet eligible for payout either because of
<a href="https://komodoplatform.com/new-feature-to-verify-dpow-notarizations/" target="_blank" rel="noopener noreferrer">dPoW</a> or min confirmations.
<em class="highlight">Balance</em> includes blocks that were scanned and already paid out but you have not yet met the min payout.<em class="highlight">*</em></p>
<p><em class="highlight">*Please note these 2 stats will only update when the payment processor runs which is currently every 4 hours.</em></p>
<p>Payments that show up on the payments page initially are in the process of constructing the z transaction. Once the transaction actually broadcasts to the network, the blocks paid out will become hyperlinked to the explorer and then should arrive in your wallet in the next block or two.</p>
@ -131,7 +131,7 @@
<h1 class="menuHeader" id="createWallet">Generate Wallet and Address</h1>
<div class="gettingStartedContent">
<p><a href="https://pirate.black/wallets/" target="_blank" rel="noopener noreferrer">The Agama GUI Wallet for PIRATE</a> is available. For Agama support please visit <a href="https://discord.gg/qReShun">#newpirates on Discord</a></p>
<p><a href="https://medium.com/piratechain/pirateocean-wallet-guide-1cb80f70364c" target="_blank" rel="noopener noreferrer">The PirateOceanQT for PIRATE</a> is available. For wallet support please visit <a href="https://discord.gg/qReShun">#newpirates on Discord</a></p>
<h4>CLI Wallet:</h4>
<ol>
@ -172,7 +172,7 @@
<li><a href="https://www.bminer.me/releases/" target="_blank" rel="noopener noreferrer">Bminer Lite</a></li>
<li><a href="https://bitcointalk.org/index.php?topic=1670733.0" target="_blank" rel="noopener noreferrer">Claymore's ZCash/BTG AMD GPU Miner</a></li>
<li><a href="https://github.com/Optiminer/OptiminerZcash" target="_blank" rel="noopener noreferrer">Optiminer AMD</a></li>
</ul>
</div>

26
website/piratepool.io/pages/home.html

@ -2,8 +2,11 @@
<div>
<div class="alertbar">
<!-- Stop mining to exchange addresses&#8230; -->
300K+ ARRR donated to Onboarding/Dev and Marketing funds, made possible via KMD notary node income.<br>
Thank you for all who voted me into KMD notary node for 2019 in SH! ❤ 🐸</div>
<!-- 300K+ ARRR donated to Onboarding/Dev and Marketing funds, made possible via KMD notary node income.<br>
Thank you for all who voted me into KMD notary node for 2019 in SH! ❤ 🐸-->
<!-- New piratepool.io discord support and discussion channel created! <a href="https://discord.gg/ASMfX7B" target="_blank" rel="nofollow noreferrer noopener" class="highlight">join #piratepool</a> 🐸 -->
Payout strategy changed to PPLNT with 1 hour payout frequency! Join <a href="https://discord.gg/ASMfX7B" target="_blank" rel="nofollow noreferrer noopener" class="highlight">#piratepool</a> for support and discussion! 🐸
</div>
<div class="pure-g boxWelcome">
<div class="pure-u-1-3 pure-responsive-disable" style="display:flex; justify-content:center; align-items:center;">
<img src="/static/pirate128.png" style="width:128px; -webkit-filter: drop-shadow(-1px -1px 0 #000); filter: drop-shadow(-1px -1px 0 #000);" alt="piratepool.io - knomp" />
@ -11,8 +14,15 @@
<div class="pure-u-2-3 pure-responsive-disable">
<h1 style="font-size: 2em; text-align:left; font-weight:900; color:#BB9645; margin:5px 0 10px;" class="textshadow">piratepool.io</h1>
<h2 style="color:#FFF; font-weight:900; font-size:1.5em; margin:0 0 10px;">Mining Pool For PirateChain (ARRR)</h2>
<p>
Donating 66% of the pool fee to the PirateChain project!<br>
<em>33% to PIRATE dev and <a href="https://dexstats.info/onboarding.php" target="_blank" rel="noopener noreferrer">onboarding</a> <a href="https://explorer.pirate.black/address/RAzq6y7dsUKgfuzNjpzyGiuFzvrwuDheQw" target="_blank" rel="noopener noreferrer">fund</a>
<br />
33% to <a href="https://explorer.pirate.black/address/RD5PhyAUhapsvj5ps2cCHozsXZfQSvDdrZ" target="_blank" rel="noopener noreferrer">PIRATE Marketing</a>!</em>
</p>
<table style="width: 100%; margin: 15px auto; text-align: left;">
<tr><td style="width:50%;">Algorithm: </td><td>Equihash</td></tr>
<tr><td>Payout Strategy: </td><td>PPLNT</td></tr>
<tr><td>Payout Frequency: </td><td>{{=it.poolsConfigs['arrr'].paymentProcessing.paymentInterval/60/60}} Hours</td></tr>
<tr><td>Min Payout: </td><td>{{=it.poolsConfigs['arrr'].paymentProcessing.minimumPayment}} ARRR</td></tr>
<tr><td>Pool Fee: </td><td>1%</td></tr>
@ -36,19 +46,15 @@
</div>
<div style="max-width:640px; margin:10px auto; padding: 10px 10px 0;">
<p>
<em>1/3rd of the pool fee is donated to the PIRATE <a href="https://dexstats.info/onboarding.php" target="_blank" rel="noopener noreferrer">onboarding</a> <a href="https://explorer.pirate.black/address/RAzq6y7dsUKgfuzNjpzyGiuFzvrwuDheQw" target="_blank" rel="noopener noreferrer">fund</a> and <br />
1/3rd is donated to <a href="https://explorer.pirate.black/address/RD5PhyAUhapsvj5ps2cCHozsXZfQSvDdrZ" target="_blank" rel="noopener noreferrer">PIRATE Marketing</a>!</em>
</p>
<p>
<span style="font-weight:900;">Sprout stratum has been retired! <a href="https://piratepool.io/static/sproutfinal.txt" target="_blank" style=" text-decoration:underline; text-decoration-color:#BB9645">Final Sprout Payouts Report</a></span>
<a href="https://medium.com/piratechain/pirateocean-wallet-guide-1cb80f70364c" target="_blank" rel="noopener noreferrer">Download the latest PirateOcean wallet</a> and create a sapling address (<span class="highlight">starts with zs1</span>) and connect to the new stratum ports labeled as <strong><em>arrr</em></strong> on <a href="/getting_started" class="hot-swapper">Getting Started</a>.
</p>
<p>
<a href="https://github.com/KomodoPlatform/Agama/releases" target="_blank" rel="noopener noreferrer">Download the latest Agama wallet</a> and create a sapling address (<span class="highlight">starts with zs1</span>) and connect to the new stratum ports labeled as <strong><em>arrr</em></strong> on <a href="/getting_started" class="hot-swapper">Getting Started</a>.
{{ /* <span style="font-weight:900;">Sprout stratum has been retired! <a href="https://piratepool.io/static/sproutfinal.txt" target="_blank" style=" text-decoration:underline; text-decoration-color:#BB9645">Final Sprout Payouts Report</a></span> */ }}
</p>
<p>
<!-- <p>
You need to migrate sprout funds in your own zc wallet address by <span class="highlight">2019-02-01</span>. A quick guide on how to migrate can be <a href="https://github.com/PirateNetwork/docs/wiki/How-to-Migrate-Pirate-(ARRR)-from-sprout-address-to-sapling-address" target="_blank" rel="noopener noreferrer">found here</a>.
You could also try <a href="https://dexstats.info/pirateswap.php" target="_blank" rel="noopener noreferrer">this service to swap your coins</a>.
</p>
</p> -->
</div>
<div class="pure-g boxStats">

8
website/piratepool.io/pages/miner_stats.html

@ -1,5 +1,11 @@
{{ function middleEllipsis(x) { return x.length > 40 ? x.substring(0, 20) + '...' + x.substring(x.length-20, x.length): x; } }}
{{ function checkCompromised(m) { var compromised = ['zs10jprfefpt2ra88u2ml96nzh3dmlqqqfeha5l7g0x0s0d2awme0eqfyt4w7r7pee0na8tcz6ezzj', 'zs12urwtysy5rkqzy3xgaxeu9g3ezf4fr0wfq44xrnf48uq6ug8qfxp059lms06khekppquvzadxyf', 'zs16sk9n6lyc8ulzkrf5xc72cr07hkyjvvj2emeqjel7xmn90qaf9mj2m8vt34yw45l7syqxlmfe5v', 'zs16xlsu48grwgsr29c9ztcn8jl0s47rtyucv3dw0n2e6y00w0wtt3d4ukqk4sq4sycrdhtxxg7g3k', 'zs19whs7s29a2kn5d4s8mpdad0m4setz86sq64kpv0t2v263mrqvuducp6nlmlwvynltam9zm9mr0p', 'zs1au66ft2gyu8ylgkw70vy4we2ktzum52esl94875w44mu8cmw2dcwfc29kahgmvfwcagwy39ctee', 'zs1c83zjak7ealmn92hejmqmjc7h3ysvglc9n95z79dhajth4fmhmrnv5zxdkufzg6l489y6hwf694', 'zs1d9myt9rpvu6grsl3ntg9wv0dfuj4vhp4rr0m3f940tt6fpxy8adpx4uzs7hgtclqtqe4wq2sjr8', 'zs1df3t2wpdmsjmzd7pwet67grfgr900fg6hjy97hl9vv0tkf7w5eye2zur6xhhzhfxdceu740g04g', 'zs1g342mavfn70xf5pycn8xwu2zsc4vq3fe8zzg99dfkdsdr39rqszvnuzxdp238d3uaqg96mmrclq', 'zs1gp9egrus6zrjqmea23nae7pzpxdy9jt3w65j8netsrcctl3g9e0lrag4tgvctw3r7rhryj4f4ua', 'zs1jttxxfwurarqw3cmkf94ygfs8skh7xxjf83wuh4awq6zjcee9p804p6aurmxv5q02f2uxc3qm93', 'zs1kqaakh9tw8uj039e9hzkh0444rw533uh8r5http8mfjuakmglqyqrjvd2ertnk8j9jlvvnzne9r', 'zs1lpp9qdtj9tkqjfj64wkcprvp2kflpu8cxz8fgclx80uuu4ajsmslkxkx0fh49cpw2yyhxwk0yzg', 'zs1pd047rvjf6es3ypx6vnl7vgnngmt3mkegn4vjtymfy26rxzp97mpjw5y2gkmyljmk99qs2wa4c0', 'zs1qsr5r8fp9scdz4wt08h4uxnlmefl0dmukuzxzs3f8wx6tk6ged399c9taphhx0asagryjkqgya7', 'zs1r4kfr08dm5yx60yg535dzhnpg8m8s4dl8ap42exkwm6699prpw9zu8sgj6xjd5efmrnj6p4u0an', 'zs1sfj20kyt95sfvll20lraw5q22q2aagw2r3pcdgtlaw4epc9sdwymxzdsge8c84f707ytqpjlnx4', 'zs1stzrmj7rfwr8g0hcsgs7aln0vxwcss6h7qfvzkyf9f6vuupeq6eqhrx7kwa0kmm5dawf7f9j8hr', 'zs1u7sy6prj270ucxwcwh9sh7vr33lnlgs6a95nt4hzgwxwvtcesu240px90822mffc0epf2kjlrjq', 'zs1ued52v4gv83yrguw4gpp4j85mtz9euedmwlszqmldl99cgefz8tz4y60ttjgm4avpqegyhnesns', 'zs1uhnyckurr2x4e8ak6ffqes4ggth8n2vxlzyksd8ufv9zltdhggdnxcx4q2jfn8tuea3f7w4yevs', 'zs1v569xvf7klgw8ylgf0dvtd92dtmu669xcqv05qvxud78nt4zwwcjdz046ghq7lvs4r0d227sgrv', 'zs1xl7l6sn0r5nsa6cex87yp3z7j2mj9jgf32dng6qqp7ym66s8wkx9lykmd896uq62e5xlq2mkaqq', 'zs1yxspuhm7fd5ffrjlmxtsyuryaj983paurt794rg87ln98ekdsugexl7kfvjw97ejhv66ytd3454', 'zs1yyeyhf856aag8vxlq4mkhjs8qjrlxfzz67s4jgjazpedrqfj62tr4zkp3tsj6cgc3hggq4t5raf', 'zs1z4aqxzy2krpvu45mfqes74a20yjmeuxlj0s4x89zr932panatzsfh8wf90qulh5683cgg9q0u2v']; return compromised.indexOf(m) > -1; } }}
<div id="pageMiner">
{{ if (checkCompromised(it.stats.address)) { }}
<div class="alertbar">
Your wallet address was possibly comporomised! Please visit <a href="https://discord.gg/ASMfX7B" target="_blank" rel="noopener noreferrer">discord</a> for more details!
</div>
{{ } }}
<div id="topCharts">
<div class="chartWrapper">
<div class="chartLabel">
@ -25,4 +31,4 @@
var _workerCount = 0;
document.querySelector('main').appendChild(document.createElement('script')).src = '/static/miner_stats.js';
</script>
</div>
</div>

24
website/piratepool.io/pages/payments.html

@ -1,11 +1,11 @@
{{
function readableDate(a){
return new Date(parseInt(a)).toISOString().substring(0, 16).replace('T', ' ') + ' UTC';
{{
function readableDate(a){
return new Date(parseInt(a)).toISOString().substring(0, 16).replace('T', ' ') + ' UTC';
}
function bigNumber(x){
return (x > 1000000000000) ? (x / 1000000000000).toFixed(1) + 'T' : (x > 1000000000) ? (x / 1000000000).toFixed(1) + 'B' : (x > 1000000) ? (x / 1000000).toFixed(1) + 'M' : (x > 1000) ? (x / 1000).toFixed(1) + 'K' : x.toFixed(1);
function bigNumber(x){
return (x > 1000000000000) ? (x / 1000000000000).toFixed(1) + 'T' : (x > 1000000000) ? (x / 1000000000).toFixed(1) + 'B' : (x > 1000000) ? (x / 1000000).toFixed(1) + 'M' : (x > 1000) ? (x / 1000).toFixed(1) + 'K' : x.toFixed(1);
}
function timeTil(x){
function timeTil(x){
return (x < 0) ? 'Now' : (x > 86400) ? (x/86400).toFixed(1) + ' Days' : (x > 3600) ? (x/3600).toFixed(1) + ' Hours' : (x > 60) ? (x / 60).toFixed(1) + ' Minutes' : x + ' Seconds';
}
function timeTilNumbers(timestamp) {
@ -13,7 +13,11 @@ function timeTilNumbers(timestamp) {
}
}}
<div id="pagePayments">
<div class="alertbar">Payout frequency has been changed to 4 hours because miners have been mining to exchange addresses&#8230;</div>
<div class="alertbar">
<!-- Payout frequency has been changed to 4 hours because miners have been mining to exchange addresses&#8230;-->
<!-- Block Reward Halving occured at block <a href="https://explorer.pirate.black/block/00000000004332fdca73719414e6e595c5f9f909bf39df5ff68f56b008b29790" target="_blank" rel="nofollow noreferrer noopener">388,885</a>!! Join <a href="https://discord.gg/ASMfX7B" target="_blank" rel="nofollow noreferrer noopener" class="highlight">#piratepool</a> for support and discussion! 🐸 -->
Payout strategy changed to PPLNT with 1 hour payout frequency! Join <a href="https://discord.gg/ASMfX7B" target="_blank" rel="nofollow noreferrer noopener" class="highlight">#piratepool</a> for support and discussion! 🐸
</div>
{{ for(var pool in it.stats.pools) { }}
<div class="poolLabel">
{{=it.stats.pools[pool].name}} Payments<span class="responsivehide"> &#160;&#160;</span><br class="responsiveonly" />
@ -37,7 +41,7 @@ function timeTilNumbers(timestamp) {
<tbody>
{{ for(var p in it.stats.pools[pool].payments) { }}
<tr id="payment{{=pool}}{{=it.stats.pools[pool].payments[p].time}}">
<td class="paymentblocks" title="Blocks:{{=it.stats.pools[pool].payments[p].blocks.length}} {{=it.stats.pools[pool].payments[p].opid}}">
<td class="paymentblocks{{if (it.stats.pools[pool].payments[p].blocks.length > 9) { }} paymentblocksexpand{{ } }}" title="Blocks:{{=it.stats.pools[pool].payments[p].blocks.length}} {{=it.stats.pools[pool].payments[p].opid}}">
<span class="responsiveTableLabel"><i class="fas fa-link fa-fw"></i></span> <span>Blocks: [{{=it.stats.pools[pool].payments[p].blocks.length}}] </span>
{{if (String(it.stats.pools[pool].name) == "KMD") { }}
<a href="https://kmdexplorer.io/tx/{{=it.stats.pools[pool].payments[p].txid}}" target="_blank" rel="noopener noreferrer">{{=it.stats.pools[pool].payments[p].blocks}}</a>
@ -57,8 +61,8 @@ function timeTilNumbers(timestamp) {
</tbody>
</table>
{{ } }}
<script>
document.querySelector('main').appendChild(document.createElement('script')).src = '/static/payments.js';
</script>
</div>
</div>

8
website/piratepool.io/pages/stats.html

@ -3,6 +3,10 @@
{{ function bigNumber(x){ return (x > 1000000000000) ? (x / 1000000000000).toFixed(1) + 'T' : (x > 1000000000) ? (x / 1000000000).toFixed(1) + 'B' : (x > 1000000) ? (x / 1000000).toFixed(1) + 'M' : (x > 1000) ? (x / 1000).toFixed(1) + 'K' : x.toFixed(1); } }}
{{ function middleEllipsis(x) { return x.length > 40 ? x.substring(0, 15) + '...' + x.substring(x.length-15, x.length): x; } }}
<div id="pageStats">
<div class="alertbar">
<!-- New piratepool.io discord support and discussion channel created! <a href="https://discord.gg/ASMfX7B" target="_blank" rel="nofollow noreferrer noopener" class="highlight">join #piratepool</a> 🐸 -->
Payout strategy changed to PPLNT with 1 hour payout frequency! Join <a href="https://discord.gg/ASMfX7B" target="_blank" rel="nofollow noreferrer noopener" class="highlight">#piratepool</a> for support and discussion! 🐸
</div>
<div id="topCharts">
<div class="chartWrapper">
<h1 class="chartLabel">Pool Hashrate</h1>
@ -35,7 +39,7 @@
<li><i class="fas fa-link fa-fw" aria-hidden="true"></i> Block Height: <span id="statsNetworkBlocks{{=pool}}">{{=it.stats.pools[pool].poolStats.networkBlocks}}</span></li>
<li><i class="fas fa-tachometer-alt fa-fw"></i> Network Hash/s: <span id="statsNetworkSols{{=pool}}">{{=it.stats.pools[pool].poolStats.networkSolsString}}</span></li>
<li><i class="fas fa-unlock-alt fa-fw" aria-hidden="true"></i> Difficulty: <span id="statsNetworkDiff{{=pool}}">{{=bigNumber(it.stats.pools[pool].poolStats.networkDiff)}}</span></li>
<li><i class="fas fa-coins fa-fw"></i> Total Supply: <span id="statsNetworkCoins{{=pool}}">{{=(it.stats.pools[pool].poolStats.networkBlocks*256).toLocaleString('en')}}</span></li>
<li><i class="fas fa-coins fa-fw"></i> Total Supply: <span id="statsNetworkCoins{{=pool}}">{{=(99554304+(it.stats.pools[pool].poolStats.networkBlocks-388884)*128).toLocaleString('en')}}</span></li>
<li><i class="fas fa-users fa-fw"></i> Node Connections: <span id="statsNetworkConnections{{=pool}}">{{=it.stats.pools[pool].poolStats.networkConnections}}</span></li>
</ul>
</div>
@ -79,7 +83,6 @@
<span class="countLabel">Pending</span>
{{ } }}
</div>
<div><i class="fas fa-crown fa-fw"></i> <small>Mined By:</small> <a href="/workers/{{=block[3].split('.')[0]}}" class="minerAddress" title="{{=block[3]}}">{{=middleEllipsis(block[3])}}</a></div>
</div>
{{ } }}
@ -95,7 +98,6 @@
{{ } }}
<span class="countLabel">Paid</span>
</div>
<div><i class="fas fa-crown fa-fw"></i> <small>Mined By:</small> <a href="/workers/{{=block[3].split('.')[0]}}" class="minerAddress" title="{{=block[3]}}">{{=middleEllipsis(block[3])}}</a></div>
</div>
{{ } }}
</div>

14
website/piratepool.io/pages/workers.html

@ -6,7 +6,7 @@
<div id="workers{{=pool}}">
<div class="poolLabel">
<span style="float:right;">
<small>Miner Lookup:
<small>Miner Lookup:
<input type="text" class="form-control input-lg" onkeypress="return searchKeyPress(event);" />
<span class="input-group-btn">
<button class="btn btn-default btn-lg" type="button">Lookup</button>
@ -24,22 +24,24 @@
<table class="pure-table poolMinerTable">
<thead>
<tr>
<th>Address</th>
<th>Miner</th>
<th>Shares</th>
<th>Efficiency</th>
<th>Hashrate</th>
</tr>
</thead>
<tbody>
{{ var minerindex = 0; }}
{{ for(var worker in it.stats.pools[pool].miners) { }}
{{ minerindex++; }}
{{var workerstat = it.stats.pools[pool].miners[worker];}}
<tr id="worker{{=worker}}" data-hashrate="{{=workerstat.hashrate}}">
<td><span class="responsiveTableLabel"><i class="far fa-address-card fa-fw"></i> Address: </span><a href="/workers/{{=worker.split('.')[0]}}" title="{{=worker}}">{{=middleEllipsis(worker)}}</a></td>
<tr id="worker{{=minerindex}}" data-hashrate="{{=workerstat.hashrate}}">
<td><span class="responsiveTableLabel"><i class="far fa-address-card fa-fw"></i></span>Miner #{{=minerindex}}</td>
<td><span class="responsiveTableLabel"><i class="fas fa-cog fa-fw"></i> Shares: </span><span>{{=bigNumber(workerstat.currRoundShares)}}</span></td>
<td><span class="responsiveTableLabel"><i class="fas fa-bullseye fa-fw"></i> Efficiency: </span><span>{{? workerstat.shares > 0}} {{=Math.floor(10000 * workerstat.shares / (workerstat.shares + workerstat.invalidshares)) / 100}}% {{??}} 0% {{?}}</span></td>
<td><span class="responsiveTableLabel"><i class="fas fa-tachometer-alt fa-fw"></i> Hashrate: </span><span>{{=workerstat.hashrateString}}</span></td>
</tr>
{{ } }}
{{ } }}
</tbody>
</table>
</div>
@ -48,4 +50,4 @@
<script>
document.querySelector('main').appendChild(document.createElement('script')).src = '/static/workers.js';
</script>
</div>
</div>

7
website/piratepool.io/static/payments.js

@ -49,12 +49,11 @@ $(function() {
console.log('Added new payment!');
}
} else {
//Update existing (txid) for private chains
//Update existing (txid) for private chains
if (typeof paymentstat.txid !== 'undefined' && (String(stats.pools[pool].name).startsWith("pirate") || String(stats.pools[pool].name).startsWith("arrr")) ) {
var explorer = 'https://explorer.pirate.black/tx/';
var paymentblock = document.querySelector('#payment' + pool + paymentstat.time + ' .paymentblocks a');
paymentblock.setAttribute('href', explorer + paymentstat.txid);
paymentblock.setAttribute('href', explorerURL + 'tx/' + paymentstat.txid);
paymentblock.setAttribute('target', '_blank');
paymentblock.setAttribute('rel', 'noopener noreferrer');
}
@ -81,4 +80,4 @@ $(function() {
}
}
});
});
});

6
website/piratepool.io/static/stats.js

@ -58,7 +58,7 @@ $(function() {
insertPendingBlock.setAttribute('title', 'Waiting for payment processor to review');
insertPendingBlock.style.opacity = 0;
insertPendingBlock.style.transition = 'opacity 1s ease-in';
insertPendingBlock.innerHTML = '<div><i class="fas fa-link fa-fw"></i> <small>Block:</small> <a href="' + explorerURL + 'block/' + checkblock[0] + '" target="_blank" rel="noopener noreferrer">' + checkblock[2] + '</a><span style="padding-left: 10px;"><small>' + readableDate(checkblock[4]) + '</small></span><span class="countLabel">Pending</span></div><div><i class="fas fa-crown fa-fw"></i> <small>Mined By:</small> <a href="/workers/' + checkblock[3].split('.')[0] + '" class="minerAddress" title="' + checkblock[3] + '">' + middleEllipsis(checkblock[3]) + '</a></div>';
insertPendingBlock.innerHTML = '<div><i class="fas fa-link fa-fw"></i> <small>Block:</small> <a href="' + explorerURL + 'block/' + checkblock[0] + '" target="_blank" rel="noopener noreferrer">' + checkblock[2] + '</a><span style="padding-left: 10px;"><small>' + readableDate(checkblock[4]) + '</small></span><span class="countLabel">Pending</span></div>';
if (parseInt(checkblock[2]) > prevHeight) {
poolFoundList.insertBefore(insertPendingBlock, poolFoundList.firstChild);
@ -85,7 +85,7 @@ $(function() {
insertPendingBlock.id = 'blocksFoundPaid' + checkblock[0];
insertPendingBlock.setAttribute('class', 'blocksFoundPaid');
insertPendingBlock.setAttribute('title', 'Payment sent, please check payments page');
insertPendingBlock.innerHTML = '<div><i class="fas fa-link fa-fw"></i> <small>Block:</small> <a href="' + explorerURL + 'block/' + checkblock[0] + '" target="_blank" rel="noopener noreferrer">' + checkblock[2] + '</a><span style="padding-left: 10px;"><small>' + readableDate(checkblock[4]) + '</small></span><span class="countLabel">Pending</span></div><div><i class="fas fa-crown fa-fw"></i> <small>Mined By:</small> <a href="/workers/' + checkblock[3].split('.')[0] + '" class="minerAddress" title="' + checkblock[3] + '">' + middleEllipsis(checkblock[3]) + '</a></div>';
insertPendingBlock.innerHTML = '<div><i class="fas fa-link fa-fw"></i> <small>Block:</small> <a href="' + explorerURL + 'block/' + checkblock[0] + '" target="_blank" rel="noopener noreferrer">' + checkblock[2] + '</a><span style="padding-left: 10px;"><small>' + readableDate(checkblock[4]) + '</small></span><span class="countLabel">Pending</span></div>';
poolFoundList.insertBefore(insertPendingBlock, document.querySelectorAll('.blocksFoundList .blocksFoundPaid')[0]);
}
@ -146,4 +146,4 @@ function displayCharts(){
function triggerChartUpdates(){
poolHashrateChart.update();
}
}

67
website/piratepool.io/static/style.css

@ -13,7 +13,7 @@
}
html, body, button, input, select, textarea,
.pure-g [class *= "pure-u"] {
.pure-g [class *= "pure-u"] {
font-family: 'Roboto', sans-serif;
line-height: 1.4em;
}
@ -99,8 +99,8 @@ footer a {
}
.highlight {
color:var(--gold);
font-weight:900;
color:var(--gold);
font-weight:900;
}
.muted {
@ -117,11 +117,11 @@ br.responsiveonly {
}
.alertbar {
color:var(--gold);
color:var(--gold);
font-weight:900;
text-shadow: -3px -3px 0px #000;
text-align:center;
padding:10px 0;
padding:10px 0;
background-color:var(--dark-blue);
}
@ -134,7 +134,7 @@ header .pure-menu {
}
header .home-menu,
header .home-menu .pure-menu-list,
header .home-menu .pure-menu-list,
header .home-menu .pure-menu-list li {
display: flex;
align-items: center;
@ -151,7 +151,7 @@ header .home-menu a {
transition:background-color 0.33s ease-out, color 0.33s ease-out;
}
header .home-menu a:hover,
header .home-menu a:hover,
header .home-menu .pure-menu-selected a {
color: #FFF!important;
background-color: var(--gold);
@ -162,7 +162,7 @@ header .home-menu li a i {
margin-right:5px;
}
.pure-menu.pure-menu-open,
.pure-menu.pure-menu-open,
.pure-menu.pure-menu-horizontal li .pure-menu-children {
border:none;
}
@ -208,7 +208,7 @@ header .home-menu li a i {
background-color: var(--dark-blue);
color: white;
max-width:640px;
margin:15px auto 10px auto;
margin:15px auto 10px auto;
padding:5px 10px 10px;
box-shadow: -1px -1px 0 #000;
}
@ -265,7 +265,7 @@ header .home-menu li a i {
}
.blocksFoundList .countLabel {
float:right;
float:right;
font-size:0.8em;
line-height:1em;
}
@ -298,7 +298,7 @@ header .home-menu li a i {
}
.blocksFoundHeader > div:nth-child(2) {
font-size:0.8em;
font-size:0.8em;
text-align:right;
}
@ -349,6 +349,11 @@ header .home-menu li a i {
}
.paymentblocks .fade {
display:none;
}
.paymentblocksexpand .fade {
display:block;
z-index: 10;
background-image: linear-gradient(to bottom, rgba(20, 20, 20, 0), rgba(20, 20, 20, 1) 90%);
width: 95%;
@ -370,11 +375,11 @@ header .home-menu li a i {
transition: max-height 0.2s ease-out 0.33s;
}
.paymentblocks a:hover {
.paymentblocksexpand a:hover {
max-height: 1000px;
}
.paymentblocks a:hover + .fade {
.paymentblocksexpand a:hover + .fade {
opacity:0;
}
@ -444,9 +449,9 @@ header .home-menu li a i {
.nv-group.nv-series-0,
.nv-series:first-of-type .nv-legend-symbol {
stroke-opacity: 1;
fill-opacity: 0.5;
fill: var(--gold)!important;
stroke-opacity: 1;
fill-opacity: 0.5;
fill: var(--gold)!important;
stroke: var(--gold)!important;
}
@ -468,32 +473,32 @@ header .home-menu li a i {
font-size: 1em;
line-height: 1em;
}
.home-menu li a i {
margin-right:0;
}
.pure-table {
.pure-table {
border-top: 1px solid var(--grey);
}
table, thead, tbody, th, td, tr {
display: block;
table, thead, tbody, th, td, tr {
display: block;
}
thead tr {
thead tr {
display:none;
visiblity:hidden;
}
tr {
tr {
border-bottom: 1px solid var(--grey);
}
td {
td {
border: none;
position: relative;
}
.pure-table td {
@ -508,11 +513,11 @@ header .home-menu li a i {
br.responsiveonly {
display:initial;
}
.responsivehide {
display:none;
}
.boxWelcome h1,
.boxWelcome h2 {
text-align:center!important;
@ -525,7 +530,7 @@ header .home-menu li a i {
.blocksFoundHeader > div {
text-align:center!important;
}
.blocksFoundList > div {
flex: 1;
}
@ -534,17 +539,17 @@ header .home-menu li a i {
display:inline-block;
visibility:visible;
}
.pure-responsive-disable,
.flex-responsive-disable {
width: 100%;
}
.paymentblocks a {
display:inline;
}
.paymentblocks .fade {
display:none;
}
}
}

22
website/piratepool.io/static/workers.js

@ -12,32 +12,34 @@ $(function() {
for (var f = 0; f < poolKeys.length; f++) {
var pool = poolKeys[f];
var sharesTotal = 0;
var minerIndex = 0;
for (var addr in stats.pools[pool].miners) {
minerIndex++;
var workerstat = stats.pools[pool].miners[addr];
sharesTotal += parseFloat(workerstat.shares);
var existingRow = document.querySelector('#workers' + pool + ' #worker' + addr);
var existingRow = document.querySelector('#workers' + pool + ' #worker' + minerIndex);
var minerEfficiency = ( workerstat.shares > 0 ) ? Math.floor(10000 * workerstat.shares / (workerstat.shares + workerstat.invalidshares)) / 100 : 0;
if (existingRow == null) {
//Add new
var insertMinerTr = document.createElement('tr');
insertMinerTr.id = 'worker' + addr;
insertMinerTr.id = 'worker' + minerIndex;
insertMinerTr.setAttribute('data-hashrate', workerstat.hashrate);
insertMinerTr.innerHTML = '<td><span class="responsiveTableLabel"><i class="far fa-address-card fa-fw"></i> Address: </span><a href="/workers/' + addr + '" title="' + addr + '">'+ middleEllipsis(addr, 20) + '</a></td>';
insertMinerTr.innerHTML = '<td><span class="responsiveTableLabel"><i class="far fa-address-card fa-fw"></i></span>Miner #'+ minerIndex +'</td>';
insertMinerTr.innerHTML += '<td><span class="responsiveTableLabel"><i class="fas fa-cog fa-fw"></i> Shares: </span><span>' + bigNumber(workerstat.shares) + '</span></td>';
insertMinerTr.innerHTML += '<td><span class="responsiveTableLabel"><i class="fas fa-bullseye fa-fw"></i> Efficiency: </span><span> ' + minerEfficiency + '%</span></td>';
insertMinerTr.innerHTML += '<td><span class="responsiveTableLabel"><i class="fas fa-tachometer-alt fa-fw"></i> Hashrate: </span><span>' + workerstat.hashrateString + '</span></td>';
document.querySelector('#workers' + pool + ' .poolMinerTable tbody').appendChild(insertMinerTr);
console.log('Added new miner! [' + addr + ']');
console.log('Added new miner! [' + minerIndex + ']');
} else {
//Update existing
document.querySelector('#workers' + pool + ' #worker' + addr + ' td:nth-child(2) span:nth-child(2)').innerHTML = bigNumber(workerstat.shares);
document.querySelector('#workers' + pool + ' #worker' + addr + ' td:nth-child(3) span:nth-child(2)').innerHTML = minerEfficiency + '%';
document.querySelector('#workers' + pool + ' #worker' + addr + ' td:nth-child(4) span:nth-child(2)').innerHTML = workerstat.hashrateString;
document.querySelector('#workers' + pool + ' #worker' + addr).setAttribute('data-hashrate', workerstat.hashrate);
document.querySelector('#workers' + pool + ' #worker' + minerIndex + ' td:nth-child(2) span:nth-child(2)').innerHTML = bigNumber(workerstat.shares);
document.querySelector('#workers' + pool + ' #worker' + minerIndex + ' td:nth-child(3) span:nth-child(2)').innerHTML = minerEfficiency + '%';
document.querySelector('#workers' + pool + ' #worker' + minerIndex + ' td:nth-child(4) span:nth-child(2)').innerHTML = workerstat.hashrateString;
document.querySelector('#workers' + pool + ' #worker' + minerIndex).setAttribute('data-hashrate', workerstat.hashrate);
}
}
@ -76,4 +78,4 @@ function searchKeyPress(e)
return false;
}
return true;
}
}

Loading…
Cancel
Save