Browse Source

Miner Privacy Update

dev
webworker01 5 years ago
parent
commit
a7e42712bf
  1. 5
      libs/paymentProcessor.js
  2. 661
      libs/stats.js
  3. 322
      website/default/static/miner_stats.js
  4. 7
      website/piratepool.io/static/payments.js
  5. 6
      website/piratepool.io/static/stats.js
  6. 67
      website/piratepool.io/static/style.css
  7. 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();
}
});
});

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