Skip to content

Commit

Permalink
Added payments page tab (w/ payments to address lookup) & core dev do…
Browse files Browse the repository at this point in the history
…nations
  • Loading branch information
zone117x committed Jul 13, 2014
1 parent f0717a3 commit 59a29c2
Show file tree
Hide file tree
Showing 11 changed files with 395 additions and 74 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,9 @@ Explanation for each field:
/* Block depth required for a block to unlocked/mature. Found in daemon source as
the variable CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW */
"depth": 60,
"poolFee": 2, //2% pool fee
"devDonation": 0.1 //0.1% donation to send to pool dev - only works with Monero
"poolFee": 1.8, //1.8% pool fee (2% total fee total including donations)
"devDonation": 0.1, //0.1% donation to send to pool dev - only works with Monero
"coreDevDonation": 0.1 //0.1% donation to send to core devs - only works with Monero
},

/* AJAX API used for front-end website. */
Expand All @@ -259,6 +260,7 @@ Explanation for each field:
"updateInterval": 3, //gather stats and broadcast every this many seconds
"port": 8117,
"blocks": 30, //amount of blocks to send at a time
"payments": 30, //amount of payments to send at a time
"password": "test" //password required for admin stats
},

Expand Down Expand Up @@ -361,6 +363,9 @@ var simplewalletDownload = "http://bit.ly/monero-starter-pack";
Bytecoin you can use "https://minergate.com/blockchain/bcn/block/". */
var blockchainExplorer = "http://monerochain.info/block/";

/* Used by front-end transaction links. Change for other coins. */
var transactionExplorer = "http://monerochain.info/tx/";

```

#### 6) Customize your website
Expand Down
4 changes: 3 additions & 1 deletion config_example.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@
"interval": 30,
"depth": 60,
"poolFee": 2,
"devDonation": 0.1
"devDonation": 0.1,
"coreDevDonation": 0.1
},

"api": {
Expand All @@ -84,6 +85,7 @@
"updateInterval": 5,
"port": 8117,
"blocks": 30,
"payments": 30,
"password": "your_password"
},

Expand Down
91 changes: 75 additions & 16 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ var url = require("url");
var zlib = require('zlib');

var async = require('async');
var redis = require('redis');

var apiInterfaces = require('./apiInterfaces.js')(config.daemon, config.wallet);

Expand All @@ -16,10 +15,13 @@ var redisCommands = [
['zrange', config.coin + ':hashrate', 0, -1],
['hgetall', config.coin + ':stats'],
['zrange', config.coin + ':blocks:candidates', 0, -1, 'WITHSCORES'],
['zrevrange', config.coin + ':blocks:matured', 0, config.api.blocks, 'WITHSCORES'],
['zrevrange', config.coin + ':blocks:matured', 0, config.api.blocks - 1, 'WITHSCORES'],
['hgetall', config.coin + ':shares:roundCurrent'],
['hgetall', config.coin + ':stats'],
['zcard', config.coin + ':blocks:matured']
['zcard', config.coin + ':blocks:matured'],
['zrevrange', config.coin + ':payments:all', 0, config.api.payments - 1, 'WITHSCORES'],
['zcard', config.coin + ':payments:all'],
['keys', config.coin + ':payments:*']
];

var currentStats = "";
Expand Down Expand Up @@ -56,7 +58,10 @@ function collectStats(){
var data = {
stats: replies[2],
blocks: replies[3].concat(replies[4]),
totalBlocks: parseInt(replies[7]) + (replies[3].length / 2)
totalBlocks: parseInt(replies[7]) + (replies[3].length / 2),
payments: replies[8],
totalPayments: parseInt(replies[9]),
totalMinersPaid: replies[10].length - 1
};

var hashrates = replies[1];
Expand Down Expand Up @@ -122,8 +127,11 @@ function collectStats(){
symbol: config.symbol,
depth: config.blockUnlocker.depth,
donation: config.blockUnlocker.devDonation,
coreDonation: config.blockUnlocker.coreDevDonation,
doDonations: doDonations,
version: version
version: version,
minPaymentThreshold: config.payments.minPayment,
denominationUnit: config.payments.denomination
});
}
}, function(error, results){
Expand Down Expand Up @@ -169,16 +177,23 @@ function broadcastLiveStats(){
var redisCommands = [];
for (var address in addressConnections){
redisCommands.push(['hgetall', config.coin + ':workers:' + address]);
redisCommands.push(['zrevrange', config.coin + ':payments:' + address, 0, config.api.payments - 1, 'WITHSCORES']);
}
redisClient.multi(redisCommands).exec(function(error, replies){

var addresses = Object.keys(addressConnections);

for (var i = 0; i < addresses.length; i++){
var offset = i * 2;
var address = addresses[i];
var stats = replies[i];
var stats = replies[offset];
var res = addressConnections[address];
res.end(stats ? formatMinerStats(stats, address) : '{"error": "not found"');
if (!stats){
res.end(JSON.stringify({error: "not found"}));
return;
}
stats.hashrate = minerStats[address];
res.end(JSON.stringify({stats: stats, payments: replies[offset + 1]}));
}
});
}
Expand Down Expand Up @@ -206,26 +221,67 @@ function handleMinerStats(urlParts, response){
});
}
else{
redisClient.hgetall(config.coin + ':workers:' + address, function(error, stats){
if (!stats){
redisClient.multi([
['hgetall', config.coin + ':workers:' + address],
['zrevrange', config.coin + ':payments:' + address, 0, config.api.payments - 1, 'WITHSCORES']
]).exec(function(error, replies){
if (error || !replies[0]){
response.end(JSON.stringify({error: 'not found'}));
return;
}
response.end(formatMinerStats(stats, address));
var stats = replies[0];
stats.hashrate = minerStats[address];
response.end(JSON.stringify({stats: stats, payments: replies[1]}));
});
}
}


function formatMinerStats(redisData, address){
redisData.hashrate = minerStats[address];
redisData.symbol = config.symbol;
return JSON.stringify({stats: redisData});
}
function handleGetPayments(urlParts, response){
var paymentKey = ':payments:all';

if (urlParts.query.address)
paymentKey = ':payments:' + urlParts.query.address;

redisClient.zrevrangebyscore(
config.coin + paymentKey,
'(' + urlParts.query.time,
'-inf',
'WITHSCORES',
'LIMIT',
0,
config.api.payments,
function(err, result){

var reply;

if (err)
reply = JSON.stringify({error: 'query failed'});
else
reply = JSON.stringify(result);

response.writeHead("200", {
'Access-Control-Allow-Origin': '*',
'Cache-Control': 'no-cache',
'Content-Type': 'application/json',
'Content-Length': reply.length
});
response.end(reply);

}
)
}

function handleGetBlocks(urlParts, response){
redisClient.zrevrangebyscore(config.coin + ':blocks:matured', '(' + urlParts.query.height, '-inf', 'WITHSCORES', 'LIMIT', 0, config.api.blocks, function(err, result){
redisClient.zrevrangebyscore(
config.coin + ':blocks:matured',
'(' + urlParts.query.height,
'-inf',
'WITHSCORES',
'LIMIT',
0,
config.api.blocks,
function(err, result){

var reply;

Expand Down Expand Up @@ -391,6 +447,9 @@ var server = http.createServer(function(request, response){
case '/stats_address':
handleMinerStats(urlParts, response);
break;
case '/get_payments':
handleGetPayments(urlParts, response);
break;
case '/get_blocks':
handleGetBlocks(urlParts, response);
break;
Expand Down
5 changes: 5 additions & 0 deletions lib/blockUnlocker.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,13 @@ function runInterval(){

if (doDonations) {
feePercent += config.blockUnlocker.devDonation / 100;
feePercent += config.blockUnlocker.coreDevDonation / 100;

var devDonation = block.reward * (config.blockUnlocker.devDonation / 100);
payments[devDonationAddress] = devDonation;

var coreDevDonation = block.reward * (config.blockUnlocker.coreDevDonation / 100);
payments[coreDevDonationAddress] = coreDevDonation;
}

var reward = block.reward - (block.reward * feePercent);
Expand Down
5 changes: 4 additions & 1 deletion lib/configReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ catch(e){

global.version = "v0.99.2.4";
global.devDonationAddress = '45Jmf8PnJKziGyrLouJMeBFw2yVyX1QB52sKEQ4S1VSU2NVsaVGPNu4bWKkaHaeZ6tWCepP6iceZk8XhTLzDaEVa72QrtVh';
global.doDonations = config.blockUnlocker.devDonation > 0 && devDonationAddress[0] === config.poolServer.poolAddress[0];
global.coreDevDonationAddress = '46BeWrHpwXmHDpDEUmZBWZfoQpdc6HaERCNmx1pEYL2rAcuwufPN9rXHHtyUA4QVy66qeFQkn6sfK8aHYjA3jk3o1Bv16em';
global.doDonations = devDonationAddress[0] === config.poolServer.poolAddress[0] && (
config.blockUnlocker.devDonation > 0 || config.blockUnlocker.coreDevDonation > 0
);
4 changes: 3 additions & 1 deletion lib/paymentProcessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ function runInterval(){
}
}

var timeOffset = 0;

async.filter(transferCommands, function(transferCmd, cback){
apiInterfaces.rpcWallet('transfer', transferCmd.rpc, function(error, result){
if (error){
Expand All @@ -113,7 +115,7 @@ function runInterval(){
return;
}

var now = Date.now() / 1000 | 0;
var now = (timeOffset++) + Date.now() / 1000 | 0;
var txHash = result.tx_hash.replace('<', '').replace('>', '');


Expand Down
4 changes: 3 additions & 1 deletion website_example/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ var easyminerDownload = "https://github.com/zone117x/cryptonote-easy-miner/relea

var simplewalletDownload = 'http://monero.cc/getting-started';

var blockchainExplorer = "http://monerochain.info/block/";
var blockchainExplorer = "http://monerochain.info/block/";

var transactionExplorer = "http://monerochain.info/tx/";
84 changes: 81 additions & 3 deletions website_example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
}
body {
padding-top: 90px;
padding-bottom: 70px;
padding-bottom: 80px;
overflow-y: scroll;
}
.container{
Expand Down Expand Up @@ -138,6 +138,80 @@
var currentPage;
var lastStats;

function getReadableCoins(coins, digits, withoutSymbol){
var amount = (parseInt(coins || 0) / coinUnits).toFixed(digits || coinUnits.toString().length - 1);
return amount + (withoutSymbol ? '' : (' ' + lastStats.config.symbol));
}

function formatDate(time){
if (!time) return '';
return new Date(parseInt(time) * 1000).toLocaleString();
}

function formatPaymentLink(hash){
return '<a target="_blank" href="' + transactionExplorer + hash + '">' + hash + '</a>';
}

function getPaymentRowElement(payment, jsonString){

var row = document.createElement('tr');
row.setAttribute('data-json', jsonString);
row.setAttribute('data-time', payment.time);
row.setAttribute('id', 'paymentRow' + payment.time);

row.innerHTML = getPaymentCells(payment);

return row;
}


function parsePayment(time, serializedPayment){
var parts = serializedPayment.split(':');
return {
time: parseInt(time),
hash: parts[0],
amount: parts[1],
fee: parts[2],
mixin: parts[3],
recipients: parts[4]
};
}

function renderPayments(paymentsResults){

var $paymentsRows = $('#payments_rows');

for (var i = 0; i < paymentsResults.length; i += 2){

var payment = parsePayment(paymentsResults[i + 1], paymentsResults[i]);

var paymentJson = JSON.stringify(payment);

var existingRow = document.getElementById('paymentRow' + payment.time);

if (existingRow && existingRow.getAttribute('data-json') !== paymentJson){
$(existingRow).replaceWith(getPaymentRowElement(payment, paymentJson));
}
else if (!existingRow){

var paymentElement = getPaymentRowElement(payment, paymentJson);

var inserted = false;
var rows = $paymentsRows.children().get();
for (var f = 0; f < rows.length; f++) {
var pTime = parseInt(rows[f].getAttribute('data-time'));
if (pTime < payment.time){
inserted = true;
$(rows[f]).before(paymentElement);
break;
}
}
if (!inserted)
$paymentsRows.append(paymentElement);
}

}
}

function pulseLiveUpdate(){
var stats_update = document.getElementById('stats_updated');
Expand Down Expand Up @@ -232,12 +306,16 @@
<i class="fa fa-home"></i> Home
</a></li>

<li><a class="hot_link" data-page="getting_started.html" href="#getting_started">
<i class="fa fa-rocket"></i> Getting Started
</a></li>

<li><a class="hot_link" data-page="pool_blocks.html" href="#pool_blocks">
<i class="fa fa-cubes"></i> Pool Blocks
</a></li>

<li><a class="hot_link" data-page="getting_started.html" href="#getting_started">
<i class="fa fa-rocket"></i> Getting Started
<li><a class="hot_link" data-page="payments.html" href="#payments">
<i class="fa fa-paper-plane-o"></i> Payments
</a></li>

<li><a class="hot_link" data-page="support.html" href="#support">
Expand Down
Loading

0 comments on commit 59a29c2

Please sign in to comment.