cryptonote-universal-pool/website/pages/home.html

738 lines
25 KiB
HTML

<style>
.marketFooter{
font-size: 10px;
opacity: 0.6;
}
#networkLastReward{
text-transform: uppercase;
}
#lastHash{
font-family: 'Inconsolata', monospace;
font-size: 0.8em;
}
#poolDonations{
font-size: 0.75em;
}
#miningProfitCalc{
margin: 35px 0;
}
#calcHashDropdown{
border-radius: 0;
border-left: 0;
border-right: 0;
}
#calcHashHolder{
width: 590px;
max-width: 100%;
}
#calcHashRate{
z-index: inherit;
font-family: 'Inconsolata', monospace;
}
#calcHashAmount{
font-family: 'Inconsolata', monospace;
}
#calcHashResultsHolder{
min-width: 145px;
max-width: 145px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#yourStatsInput{
z-index: inherit;
font-family: 'Inconsolata', monospace;
}
#yourAddressDisplay > span {
font-family: 'Inconsolata', monospace;
}
#lookUp > span:nth-child(2){
display: none;
}
.yourStats{
display: none;
}
#yourAddressDisplay{
display: inline-block;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
font-family: 'Inconsolata', monospace;
font-size: 0.9em;
}
#addressError{
color: red;
}
#payments_rows > tr > td{
vertical-align: middle;
font-family: 'Inconsolata', monospace;
font-size: 0.95em;
text-align: center;
}
#payments_rows > tr > td:nth-child(2){
text-align: left;
}
</style>
<div id="siteInfo">
<!-- Description or information about this pool -->
</div>
<div class="row">
<div class="col-md-4 stats">
<h3>Network</h3>
<div><i class="fa fa-tachometer"></i> Hash Rate: <span id="networkHashrate"></span></div>
<div><i class="fa fa-clock-o"></i> Block Found: <span id="networkLastBlockFound"></span></div>
<div><i class="fa fa-unlock-alt"></i> Difficulty: <span id="networkDifficulty"></span></div>
<div><i class="fa fa-bars"></i> Blockchain Height: <span id="blockchainHeight"></span></div>
<div><i class="fa fa-money"></i> Last Reward: <span id="networkLastReward"></span></div>
<div><i class="fa fa-paw"></i> Last Hash: <a id="lastHash" target="_blank"></a></div>
</div>
<div class="col-md-4 stats">
<h3>Our Pool</h3>
<div><i class="fa fa-tachometer"></i> Hash Rate: <span id="poolHashrate"></span></div>
<div><i class="fa fa-clock-o"></i> Block Found: <span id="poolLastBlockFound"></span></div>
<div><i class="fa fa-users"></i> Connected Miners: <span id="poolMiners"></span></div>
<div id="donations"><i class="fa fa-gift"></i> Donations: <span id="poolDonations"></span></div>
<div><i class="fa fa-money"></i> Total Pool Fee: <span id="poolFee"></span></div>
<div><i class="fa fa-history"></i> Block Found Every: <span id="blockSolvedTime"></span> (est.)</div>
</div>
<div class="col-md-4 stats marketRate">
<h3 id="marketHeader">Market</h3>
<div class="marketFooter">Updated: <span id="marketLastUpdated"></span></div>
<div class="marketFooter">Powered by <a href="https://www.cryptonator.com/">Cryptonator</a></div>
</div>
</div>
<!-- <hr> -->
<div class="row chartsPoolStat">
<div class="col-sm-2 chartWrap">
<h4>Hash/USD <span data-toggle="tooltip" data-placement="top" data-original-title="Reward * Rate / Difficulty"><i class="fa fa-question-circle"></i></span></h4>
<div id="chartHashUsd" data-chart="profit">
<div class="chart"></div>
<!-- <p class="text-center" id="cur_profit">-</p> -->
</div>
</div>
<div class="col-sm-20 chartWrap">
<h4>Price in USD</h4>
<div id="chartPriceUsd" data-chart="price">
<div class="chart"></div>
<!-- <p class="text-center" id="cur_price">-</p> -->
</div>
</div>
<div class="col-sm-20 chartWrap">
<h4>Difficulty</h4>
<div id="chartDifficulty" data-chart="diff">
<div class="chart"></div>
<!-- <p class="text-center" id="cur_diff">-</p> -->
</div>
</div>
<div class="col-sm-20 chartWrap">
<h4>Hashrate</h4>
<div id="chartHashrate" data-chart="hashrate">
<div class="chart"></div>
<!-- <p class="text-center" id="cur_hashrate">-</p> -->
</div>
</div>
<div class="col-sm-20 chartWrap">
<h4>Workers</h4>
<div id="chartWorkers" data-chart="workers">
<div class="chart"></div>
<!-- <p class="text-center" id="cur_workers">-</p> -->
</div>
</div>
<script>
var currencyGraphStat = {
type: 'line',
width: '100%',
height: '75',
lineColor: '#03a678',
fillColor: 'rgba(3, 166, 120, .3)',
spotColor: '#00bf00',
minSpotColor: '#00bf00',
maxSpotColor: '#00bf00',
highlightLineColor: '#236d26',
spotRadius: 3,
// chartRangeMin: 0,
minSpotColor: null,
maxSpotColor: null,
drawNormalOnTop: false,
tooltipFormat: '<b>{{y}}</b>, {{offset:names}}',
tooltipValueLookups: {
names: null
}
}
var userGraphStat = {
type: 'line',
width: '100%',
height: '180',
lineColor: '#03a678',
fillColor: 'rgba(3, 166, 120, .3)',
spotColor: '#00bf00',
minSpotColor: '#00bf00',
maxSpotColor: '#00bf00',
highlightLineColor: '#236d26',
spotRadius: 3,
minSpotColor: null,
maxSpotColor: null,
drawNormalOnTop: false,
chartRangeMin: 0,
tooltipFormat: '<b>{{y}}</b>, {{offset:names}}',
tooltipValueLookups: {
names: null
}
}, userGraphStat2 = {
type: 'line',
width: '100%',
height: '180',
lineColor: '#03a678',
fillColor: 'rgba(3, 166, 120, .3)',
spotColor: '#00bf00',
minSpotColor: '#00bf00',
maxSpotColor: '#00bf00',
highlightLineColor: '#236d26',
spotRadius: 3,
minSpotColor: null,
maxSpotColor: null,
drawNormalOnTop: false,
chartRangeMin: 0,
tooltipFormat: '<b>{{y}}</b>, {{offset:names}}',
tooltipValueLookups: {
names: null
}
}
$(function() {
$('[data-toggle="tooltip"]').tooltip();
});
</script>
</div>
<!-- <hr> -->
<div id="miningProfitCalc">
<h3>Estimate Mining Profits</h3>
<div id="calcHashHolder">
<div class="input-group">
<input type="number" class="form-control" id="calcHashRate" placeholder="Enter Your Hash Rate">
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" id="calcHashDropdown">
<span id="calcHashUnit" data-mul="1">KH/s</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right" role="menu" id="calcHashUnits">
<li><a href="#" data-mul="0">H/s</a></li>
<li><a href="#" data-mul="1">KH/s</a></li>
<li><a href="#" data-mul="2">MH/s</a></li>
</ul>
</div>
<span class="input-group-addon">=</span>
<span class="input-group-addon" id="calcHashResultsHolder"><span id="calcHashAmount"></span> <span id="calcHashSymbol"></span>/day</span>
</div>
</div>
</div>
<hr>
<div class="stats">
<h3>Your Stats & Payment History</h3>
<div class="input-group">
<input class="form-control" id="yourStatsInput" type="text" placeholder="Enter Your Address">
<span class="input-group-btn"><button class="btn btn-default" type="button" id="lookUp">
<span><i class="fa fa-search"></i> Lookup</span>
<span><i class="fa fa-refresh fa-spin"></i> Searching...</span>
</button></span>
</div>
<div class="row">
<div class="col-sm-4 stats">
<div id="addressError"></div>
<!-- <div class="yourStats"><i class="fa fa-key"></i> Address: <span id="yourAddressDisplay"></span></div> -->
<div class="yourStats"><i class="fa fa-bank"></i> Pending Balance: <span id="yourPendingBalance"></span></div>
<div class="yourStats"><i class="fa fa-money"></i> Total Paid: <span id="yourPaid"></span></div>
<div class="yourStats"><i class="fa fa-clock-o"></i> Last Share Submitted: <span id="yourLastShare"></span></div>
<div class="yourStats"><i class="fa fa-tachometer"></i> Hash Rate: <span id="yourHashrateHolder"></span></div>
<div class="yourStats"><i class="fa fa-cloud-upload"></i> Total Hashes Submitted: <span id="yourHashes"></span></div>
</div>
<div class="col-sm-4">
<div class="userChart" data-chart="user_hashrate">
<h4>Hash Rate</h4>
<div class="chart">
</div>
</div>
</div>
<div class="col-sm-4">
<div class="userChart" data-chart="user_payments">
<h4>Payments</h4>
<div class="chart">
</div>
</div>
</div>
</div>
<br class="yourStats">
<h4 class="yourStats">Payments</h4>
<div class="yourStats table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th><i class="fa fa-clock-o"></i> Time Sent</th>
<th><i class="fa fa-paw"></i> Transaction Hash</th>
<th><i class="fa fa-money"></i> Amount</th>
<th><i class="fa fa-sitemap"></i> Mixin</th>
</tr>
</thead>
<tbody id="payments_rows">
</tbody>
</table>
</div>
<p class="yourStats text-center">
<button type="button" class="btn btn-default" id="loadMorePayments">Load More</button>
</p>
</div>
<script>
currentPage = {
destroy: function(){
$('#networkLastBlockFound,#poolLastBlockFound,#yourLastShare,#marketLastUpdated').timeago('dispose');
if (xhrAddressPoll) xhrAddressPoll.abort();
if (addressTimeout) clearTimeout(addressTimeout);
clearInterval(intervalMarketPolling);
for (var marketPoll in xhrMarketGets){
xhrMarketGets[marketPoll].abort();
}
if (xhrGetPayments) xhrGetPayments.abort();
},
update: function(){
$('#networkLastBlockFound').timeago('update', new Date(lastStats.network.timestamp * 1000).toISOString());
updateText('networkHashrate', getReadableHashRateString(lastStats.network.difficulty / 60) + '/sec');
updateText('networkDifficulty', lastStats.network.difficulty.toString());
updateText('blockchainHeight', lastStats.network.height.toString());
updateText('networkLastReward', getReadableCoins(lastStats.network.reward, 4));
updateText('lastHash', lastStats.network.hash.substr(0, 13) + '...').setAttribute('href', getBlockchainUrl(lastStats.network.hash));
updateText('poolHashrate', getReadableHashRateString(lastStats.pool.hashrate) + '/sec');
if (lastStats.pool.lastBlockFound){
var d = new Date(parseInt(lastStats.pool.lastBlockFound)).toISOString();
$('#poolLastBlockFound').timeago('update', d);
}
else
$('#poolLastBlockFound').removeAttr('title').data('ts', '').update('Never');
//updateText('poolRoundHashes', lastStats.pool.roundHashes.toString());
updateText('poolMiners', lastStats.pool.miners.toString());
var totalFee = lastStats.config.fee;
if (lastStats.config.doDonations){
totalFee += lastStats.config.donation;
totalFee += lastStats.config.coreDonation;
var feeText = [];
if (lastStats.config.donation > 0) feeText.push(lastStats.config.donation + '% to pool dev');
if (lastStats.config.coreDonation > 0) feeText.push(lastStats.config.coreDonation + '% to core devs');
updateText('poolDonations', feeText.join(', '));
}
else{
$('#donations').hide()
}
updateText('poolFee', totalFee + '%');
updateText('blockSolvedTime', getReadableTime(lastStats.network.difficulty / lastStats.pool.hashrate));
updateText('calcHashSymbol', lastStats.config.symbol);
calcEstimateProfit();
}
};
$('#networkLastBlockFound,#poolLastBlockFound,#yourLastShare,#marketLastUpdated').timeago();
function getBlockchainUrl(id) {
return blockchainExplorer.replace('{symbol}', lastStats.config.symbol.toLowerCase()).replace('{id}', id);
}
function getReadableTime(seconds){
var units = [ [60, 'second'], [60, 'minute'], [24, 'hour'],
[7, 'day'], [4, 'week'], [12, 'month'], [1, 'year'] ];
function formatAmounts(amount, unit){
var rounded = Math.round(amount);
return '' + rounded + ' ' + unit + (rounded > 1 ? 's' : '');
}
var amount = seconds;
for (var i = 0; i < units.length; i++){
if (amount < units[i][0])
return formatAmounts(amount, units[i][1]);
amount = amount / units[i][0];
}
return formatAmounts(amount, units[units.length - 1][1]);
}
function getReadableHashRateString(hashrate){
var i = 0;
var byteUnits = [' H', ' KH', ' MH', ' GH', ' TH', ' PH' ];
while (hashrate > 1024){
hashrate = hashrate / 1024;
i++;
}
return hashrate.toFixed(2) + byteUnits[i];
}
/* Market data polling */
var intervalMarketPolling = setInterval(updateMarkets, 300000); //poll market data every 5 minutes
var xhrMarketGets = {};
updateMarkets();
function updateMarkets(){
var completedFetches = 0;
var marketsData = [];
for (var i = 0; i < cryptonatorWidget.length; i++){
(function(i){
xhrMarketGets[cryptonatorWidget[i]] = $.get('https://www.cryptonator.com/api/ticker/' + cryptonatorWidget[i], function(data){
if(data.error) {
return;
}
$('.marketRate').show();
marketsData[i] = data;
completedFetches++;
if (completedFetches !== cryptonatorWidget.length) return;
var $marketHeader = $('#marketHeader');
$('.marketTicker').remove();
for (var f = marketsData.length - 1; f >= 0 ; f--){
var price = parseFloat(marketsData[f].ticker.price);
if (price > 1) price = Math.round(price * 100) / 100;
else price = marketsData[f].ticker.price;
$marketHeader.after('<div class="marketTicker">' + marketsData[f].ticker.base + ': <span>' + price + ' ' + marketsData[f].ticker.target + '</span></div>');
}
$('#marketLastUpdated').timeago('update', new Date(marketsData[0].timestamp * 1000).toISOString());
}, 'json');
})(i);
}
}
/* Hash Profitability Calculator */
$('#calcHashRate').keyup(calcEstimateProfit).change(calcEstimateProfit);
$('#calcHashUnits > li > a').click(function(e){
e.preventDefault();
$('#calcHashUnit').text($(this).text()).data('mul', $(this).data('mul'));
calcEstimateProfit();
});
function calcEstimateProfit(){
try {
var rateUnit = Math.pow(1024,parseInt($('#calcHashUnit').data('mul')));
var inp2 = parseFloat($('#calcHashRate').val()) * rateUnit;
var resl = 16 / ((lastStats.network.difficulty / inp2) / 86400);
if (!isNaN(resl)) {
updateText('calcHashAmount', (Math.round(resl * 100) / 100).toString());
return;
}
}
catch(e){ }
updateText('calcHashAmount', '');
}
/* Stats by mining address lookup */
function getPaymentCells(payment){
return '<td>' + formatDate(payment.time) + '</td>' +
'<td>' + formatPaymentLink(payment.hash) + '</td>' +
'<td>' + getReadableCoins(payment.amount, 4, true) + '</td>' +
'<td>' + payment.mixin + '</td>';
}
var xhrAddressPoll;
var addressTimeout;
$('#lookUp').click(function(){
var address = $('#yourStatsInput').val().trim();
if (!address){
$('#yourStatsInput').focus();
return;
}
$('#addressError').hide();
$('.yourStats').hide();
$('#payments_rows').empty();
$('#lookUp > span:first-child').hide();
$('#lookUp > span:last-child').show();
if (xhrAddressPoll) xhrAddressPoll.abort();
if (addressTimeout) clearTimeout(addressTimeout);
function fetchAddressStats(longpoll){
xhrAddressPoll = $.ajax({
url: api + '/stats_address',
data: {
address: address,
longpoll: longpoll
},
dataType: 'json',
cache: 'false',
success: function(data){
$('#lookUp > span:last-child').hide();
$('#lookUp > span:first-child').show();
if (!data.stats){
$('.yourStats, .userChart').hide();
$('#addressError').text(data.error).show();
if (addressTimeout) clearTimeout(addressTimeout);
addressTimeout = setTimeout(function(){
fetchAddressStats(false);
}, 2000);
return;
}
$('#addressError').hide();
if (data.stats.lastShare)
$('#yourLastShare').timeago('update', new Date(parseInt(data.stats.lastShare) * 1000).toISOString());
else
updateText('yourLastShare', 'Never');
updateText('yourHashrateHolder', (data.stats.hashrate || '0 H') + '/sec');
updateText('yourHashes', (data.stats.hashes || 0).toString());
updateText('yourPaid', getReadableCoins(data.stats.paid));
updateText('yourPendingBalance', getReadableCoins(data.stats.balance));
renderPayments(data.payments);
$('.yourStats, .userChart').show(function(){
xhrRenderUserCharts = $.ajax({
url: api + '/stats_address?address=' + address + '&longpoll=false',
cache: false,
dataType: 'json',
success: function(data) {
createUserCharts(data);
}
});
});
docCookies.setItem('mining_address', address, Infinity);
fetchAddressStats(true);
},
error: function(e){
if (e.statusText === 'abort') return;
$('#addressError').text('Connection error').show();
if (addressTimeout) clearTimeout(addressTimeout);
addressTimeout = setTimeout(function(){
fetchAddressStats(false);
}, 2000);
}
});
}
fetchAddressStats(false);
});
var urlWalletAddress = location.search.split('wallet=')[1] || 0;
var address = urlWalletAddress || docCookies.getItem('mining_address');
var xhrRenderUserCharts;
function createUserCharts(data) {
if (data.hasOwnProperty("charts")) {
var graphData = {
hashrate: getGraphData(data["charts"].hashrate),
payments: getGraphData(data["charts"].payments)
};
for (var graphType in graphData) {
if (graphData.hasOwnProperty("hashrate")) {
$('[data-chart=user_hashrate] .chart').sparkline(graphData["hashrate"].values, userGraphStat);
userGraphStat.tooltipValueLookups.names = graphData["hashrate"].names;
}
if (graphData.hasOwnProperty("payments")) {
$('[data-chart=user_payments] .chart').sparkline(graphData["payments"].values, userGraphStat2);
userGraphStat2.tooltipValueLookups.names = graphData["payments"].names;
}
}
}
}
if (address){
$('#yourStatsInput').val(address);
$('#lookUp').click();
}
$('#yourStatsInput').keyup(function(e){
if(e.keyCode === 13)
$('#lookUp').click();
});
var xhrGetPayments;
$('#loadMorePayments').click(function(){
if (xhrGetPayments) xhrGetPayments.abort();
xhrGetPayments = $.ajax({
url: api + '/get_payments',
data: {
time: $('#payments_rows').children().last().data('time'),
address: address
},
dataType: 'json',
cache: 'false',
success: function(data){
renderPayments(data);
}
});
});
/* Show stats of the currency */
function getGraphData (rawData) {
var graphData = {
names: [],
values: []
};
if(rawData) {
for (var i = 0, xy; xy = rawData[i]; i++) {
graphData.names.push(new Date(xy[0]*1000).toUTCString());
graphData.values.push(xy[1]);
}
}
return graphData;
}
function createCharts(data) {
if (data.hasOwnProperty("charts")) {
var graphData = {
profit: getGraphData(data.charts.profit),
diff: getGraphData(data.charts.difficulty),
hashrate: getGraphData(data.charts.hashrate),
price: getGraphData(data.charts.price),
workers: getGraphData(data.charts.workers)
};
for(var graphType in graphData) {
if(graphData.hasOwnProperty(graphType)) {
currencyGraphStat.tooltipValueLookups.names = graphData[graphType].names;
$('[data-chart=' + graphType + '] .chart').sparkline(graphData[graphType].values, currencyGraphStat);
}
}
}
}
function loadStatistics () {
$.get(api + '/stats', function (stats) {
if (stats) {
showStats(stats)
}
});
}
function showStats (stats) {
$('#cur_diff').text(stats.network.difficulty);
$('#cur_hashrate').text(getReadableHashRateString(stats.pool.hashrate) + '/s');
$('#cur_workers').text(stats.pool.miners);
// Some values aren't available in stats.
// Get the values from charts data.
if (stats.hasOwnProperty('charts')) {
var priceData = stats.charts.price;
$('#cur_price').text(priceData ? priceData[priceData.length-1][1] : '---');
}
if (stats.hasOwnProperty('charts')) {
var profitValue;
var profitData = stats.charts.profit;
if (profitData) {
profitValue = profitData[profitData.length-1][1];
if (profitValue) {
profitValue = profitValue.toPrecision(3).toString().replace(/(.*?)e(\+|\-)(\d+)/, '$1<sup>10<sup>$2$3</sup></sup>');
}
else {
profitValue = '---';
}
}
else {
profitValue = '---';
}
$('#cur_profit').html(profitValue);
}
}
var xhrRenderCharts;
$(function(){
xhrRenderCharts = $.ajax({
url: api + '/stats',
cache: false,
success: function(data) {
createCharts(data);
}
});
});
</script>