diff --git a/app.js b/app.js index ae245c0..8e30469 100644 --- a/app.js +++ b/app.js @@ -375,6 +375,46 @@ app.use('/ext/getmasternodelist', function(req, res) { res.end('This method is disabled'); }); +// returns a list of masternode reward txs for a single masternode address from a specific block height +app.use('/ext/getmasternoderewards/:hash/:since', function(req, res) { + // check if the getmasternoderewards api is enabled + if (settings.public_api.ext['getmasternoderewards']) { + db.get_masternode_rewards(req.params.hash, req.params.since, function(rewards) { + if (rewards != null) { + // loop through the tx list to fix vout values and remove unnecessary data such as the always empty vin array and the mongo _id and __v keys + for (i = 0; i < rewards.length; i++) { + // remove unnecessary data keys + delete rewards[i]['vin']; + delete rewards[i]['_id']; + delete rewards[i]['__v']; + // convert amounts from satoshis + rewards[i]['total'] = rewards[i]['total'] / 100000000; + rewards[i]['vout']['amount'] = rewards[i]['vout']['amount'] / 100000000; + } + // return list of masternode rewards + res.json(rewards); + } else + res.send({error: "failed to retrieve masternode rewards", hash: req.params.hash, since: req.params.since}); + }); + } else + res.end('This method is disabled'); +}); + +// returns the total masternode rewards received for a single masternode address from a specific block height +app.use('/ext/getmasternoderewardstotal/:hash/:since', function(req, res) { + // check if the getmasternoderewardstotal api is enabled + if (settings.public_api.ext['getmasternoderewardstotal']) { + db.get_masternode_rewards_totals(req.params.hash, req.params.since, function(total_rewards) { + if (total_rewards != null) { + // return the total of masternode rewards + res.json(total_rewards); + } else + res.send({error: "failed to retrieve masternode rewards", hash: req.params.hash, since: req.params.since}); + }); + } else + res.end('This method is disabled'); +}); + // locals app.set('title', settings.title); app.set('explorer_version', package_metadata.version); diff --git a/lib/database.js b/lib/database.js index 4f4cc88..f5d48fa 100644 --- a/lib/database.js +++ b/lib/database.js @@ -1154,6 +1154,45 @@ module.exports = { }); }, + get_masternode_rewards: function(mnPayees, since, cb) { + Tx.aggregate([ + { $match: { + "blockindex": { $gt: Number(since) }, + "vin": [] + }}, + { "$unwind": "$vout" }, + { $match: { + "vout.addresses": { $in: [mnPayees] } + }} + ], function(err, data) { + if (err) { + console.log(err); + return cb(null); + } else + return cb(data); + }); + }, + + get_masternode_rewards_totals: function(mnPayees, since, cb) { + Tx.aggregate([ + { $match: { + "blockindex": { $gt: Number(since) }, + "vin": [] + }}, + { "$unwind": "$vout" }, + { $match: { + "vout.addresses": { $in: [mnPayees] } + }}, + { $group: { _id: null, total: { $sum: "$vout.amount" } } } + ], function(err, data) { + if (err) { + console.log(err); + return cb(null); + } else + return cb((data.length > 0 ? data[0].total / 100000000 : 0)); + }); + }, + // updates last_updated stats; called by sync.js update_last_updated_stats: function (coin, param, cb) { if (param.masternodes_last_updated) { diff --git a/lib/settings.js b/lib/settings.js index 9bcd85e..752e638 100644 --- a/lib/settings.js +++ b/lib/settings.js @@ -220,7 +220,9 @@ exports.public_api = { "getlasttxs": true, "getcurrentprice": true, "getbasicstats": true, - "getmasternodelist": true + "getmasternodelist": true, + "getmasternoderewards": true, + "getmasternoderewardstotal": true } }; diff --git a/settings.json.template b/settings.json.template index 5043fa4..ec75963 100644 --- a/settings.json.template +++ b/settings.json.template @@ -305,7 +305,9 @@ "getlasttxs": true, "getcurrentprice": true, "getbasicstats": true, - "getmasternodelist": true + "getmasternodelist": true, + "getmasternoderewards": true, + "getmasternoderewardstotal": true } }, diff --git a/views/info.pug b/views/info.pug index a301193..afb739a 100644 --- a/views/info.pug +++ b/views/info.pug @@ -11,7 +11,7 @@ block content em #{settings.locale.api_message} hr - var hide_rpc_api_section = !(settings.public_api.rpc['getdifficulty'] == true && settings.api_cmds['getdifficulty'] != null && settings.api_cmds['getdifficulty'] != '') && !(settings.public_api.rpc['getconnectioncount'] == true && settings.api_cmds['getconnectioncount'] != null && settings.api_cmds['getconnectioncount'] != '') && !(settings.public_api.rpc['getblockcount'] == true && settings.api_cmds['getblockcount'] != null && settings.api_cmds['getblockcount'] != '') && !(settings.public_api.rpc['getblockhash'] == true && settings.api_cmds['getblockhash'] != null && settings.api_cmds['getblockhash'] != '') && !(settings.public_api.rpc['getblock'] == true && settings.api_cmds['getblock'] != null && settings.api_cmds['getblock'] != '') && !(settings.public_api.rpc['getrawtransaction'] == true && settings.api_cmds['getrawtransaction'] != null && settings.api_cmds['getrawtransaction'] != '') && !(settings.public_api.rpc['getnetworkhashps'] == true && settings.index.show_hashrate == true && settings.api_cmds['getnetworkhashps'] != null && settings.api_cmds['getnetworkhashps'] != '') && !(settings.public_api.rpc['getvotelist'] == true && settings.api_cmds['getvotelist'] != null && settings.api_cmds['getvotelist'] != '') && !(settings.public_api.rpc['getmasternodecount'] == true && settings.api_cmds['getmasternodecount'] != null && settings.api_cmds['getmasternodecount'] != '') && (!settings.heavy || (!(settings.public_api.rpc['getmaxmoney'] == true && settings.api_cmds.heavies['getmaxmoney'] != null && settings.api_cmds.heavies['getmaxmoney'] != '') && !(settings.public_api.rpc['getmaxvote'] == true && settings.api_cmds.heavies['getmaxvote'] != null && settings.api_cmds.heavies['getmaxvote'] != '') && !(settings.public_api.rpc['getvote'] == true && settings.api_cmds.heavies['getvote'] != null && settings.api_cmds.heavies['getvote'] != '') && !(settings.public_api.rpc['getphase'] == true && settings.api_cmds.heavies['getphase'] != null && settings.api_cmds.heavies['getphase'] != '') && !(settings.public_api.rpc['getreward'] == true && settings.api_cmds.heavies['getreward'] != null && settings.api_cmds.heavies['getreward'] != '') && !(settings.public_api.rpc['getsupply'] == true && settings.api_cmds.heavies['getsupply'] != null && settings.api_cmds.heavies['getsupply'] != '') && !(settings.public_api.rpc['getnextrewardestimate'] == true && settings.api_cmds.heavies['getnextrewardestimate'] != null && settings.api_cmds.heavies['getnextrewardestimate'] != '') && !(settings.public_api.rpc['getnextrewardwhenstr'] == true && settings.api_cmds.heavies['getnextrewardwhenstr'] != null && settings.api_cmds.heavies['getnextrewardwhenstr'] != ''))); - - var hide_ext_api_section = !settings.public_api.ext['getmoneysupply'] && !settings.public_api.ext['getdistribution'] && !settings.public_api.ext['getaddress'] && !settings.public_api.ext['gettx'] && !settings.public_api.ext['getbalance'] && !settings.public_api.ext['getlasttxs'] && !settings.public_api.ext['getcurrentprice'] && !settings.public_api.ext['getbasicstats'] && !(settings.public_api.ext['getmasternodelist'] == true && settings.api_cmds['getmasternodelist'] != null && settings.api_cmds['getmasternodelist'] != ''); + - var hide_ext_api_section = !settings.public_api.ext['getmoneysupply'] && !settings.public_api.ext['getdistribution'] && !settings.public_api.ext['getaddress'] && !settings.public_api.ext['gettx'] && !settings.public_api.ext['getbalance'] && !settings.public_api.ext['getlasttxs'] && !settings.public_api.ext['getcurrentprice'] && !settings.public_api.ext['getbasicstats'] && !(settings.public_api.ext['getmasternodelist'] == true && settings.api_cmds['getmasternodelist'] != null && settings.api_cmds['getmasternodelist'] != '') && !settings.public_api.ext['getmasternoderewards'] && !settings.public_api.ext['getmasternoderewardstotal']; if !hide_rpc_api_section h3 #{settings.locale.api_calls} p @@ -212,6 +212,20 @@ block content div em #{settings.locale.api_getmasternodelist} a(href='/ext/getmasternodelist') #{address}/ext/getmasternodelist + if settings.public_api.ext['getmasternoderewards'] == true + li + p + div.font-weight-bold getmasternoderewards (/ext/getmasternoderewards/hash/since) + div + em Returns a list of masternode reward transactions for address [hash] that arrived after block height [since] + a(href='/ext/getmasternoderewards/' + hashes.address + '/' + hashes.blockindex) #{address}/ext/getmasternoderewards/#{hashes.address}/#{hashes.blockindex} + if settings.public_api.ext['getmasternoderewardstotal'] == true + li + p + div.font-weight-bold getmasternoderewardstotal (/ext/getmasternoderewardstotal/hash/since) + div + em Returns the total number of coins earned in masternode rewards for address [hash] that arrived after block height [since] + a(href='/ext/getmasternoderewardstotal/' + hashes.address + '/' + hashes.blockindex) #{address}/ext/getmasternoderewardstotal/#{hashes.address}/#{hashes.blockindex} hr h3 Linking (GET) p