Add new settings to disable individual public apis

-All coind + extended public api calls can now be enabled/disabled individually via settings.json; Disabled apis still work internally when disabled; The only noteworthy exception is the extended /ext/getlasttxs endpoint which is the only extended api consumed by the explorer itself, although it works to prevent outside access by default, it is controlled by http headers which can be manipulated and it's extremely likely that a savvy user could enable usage of /ext/getlasttxs for their own needs even if the site has specifically disabled that public api. More thought may be needed to properly resolve that problem, but it may also not be a big deal since it's data that is available to the explorer and in no way hidden or secret
-Disabled apis do not show up on the /info page and will return a "This method is disabled" msg if the endpoint is called
-Applied some code formatting to the /lib/nodeapi.js file
This commit is contained in:
joeuhren
2020-12-28 15:12:56 -07:00
parent ac237ad8e9
commit 374ab2d7aa
5 changed files with 505 additions and 397 deletions
+181 -152
View File
@@ -55,184 +55,212 @@ app.use(express.static(path.join(__dirname, 'public')));
// routes
app.use('/api', nodeapi.app);
app.use('/', routes);
app.use('/ext/getmoneysupply', function(req,res) {
lib.get_supply(function(supply) {
res.setHeader('content-type', 'text/plain');
res.end((supply ? supply.toString() : '0'));
});
app.use('/ext/getmoneysupply', function(req, res) {
// check if the getmoneysupply api is enabled
if (settings.public_api.ext['getmoneysupply']) {
lib.get_supply(function(supply) {
res.setHeader('content-type', 'text/plain');
res.end((supply ? supply.toString() : '0'));
});
} else
res.end('This method is disabled');
});
app.use('/ext/getaddress/:hash', function(req,res){
db.get_address(req.params.hash, false, function(address){
db.get_address_txs_ajax(req.params.hash, 0, settings.txcount, function(txs, count){
if (address) {
var last_txs = [];
for(i=0; i<txs.length; i++){
if(typeof txs[i].txid !== "undefined") {
var out = 0,
vin = 0,
tx_type = 'vout',
row = {};
txs[i].vout.forEach(function (r) {
if (r.addresses == req.params.hash) {
out += r.amount;
}
});
txs[i].vin.forEach(function (s) {
if (s.addresses == req.params.hash) {
vin += s.amount;
}
});
if (vin > out) {
tx_type = 'vin';
app.use('/ext/getaddress/:hash', function(req, res) {
// check if the getaddress api is enabled
if (settings.public_api.ext['getaddress']) {
db.get_address(req.params.hash, false, function(address) {
db.get_address_txs_ajax(req.params.hash, 0, settings.txcount, function(txs, count) {
if (address) {
var last_txs = [];
for (i = 0; i < txs.length; i++) {
if (typeof txs[i].txid !== "undefined") {
var out = 0,
vin = 0,
tx_type = 'vout',
row = {};
txs[i].vout.forEach(function (r) {
if (r.addresses == req.params.hash)
out += r.amount;
});
txs[i].vin.forEach(function (s) {
if (s.addresses == req.params.hash)
vin += s.amount;
});
if (vin > out)
tx_type = 'vin';
row['addresses'] = txs[i].txid;
row['type'] = tx_type;
last_txs.push(row);
}
row['addresses'] = txs[i].txid;
row['type'] = tx_type;
last_txs.push(row);
}
}
var a_ext = {
address: address.a_id,
sent: (address.sent / 100000000),
received: (address.received / 100000000),
balance: (address.balance / 100000000).toString().replace(/(^-+)/mg, ''),
last_txs: last_txs
};
res.send(a_ext);
} else {
res.send({ error: 'address not found.', hash: req.params.hash});
}
var a_ext = {
address: address.a_id,
sent: (address.sent / 100000000),
received: (address.received / 100000000),
balance: (address.balance / 100000000).toString().replace(/(^-+)/mg, ''),
last_txs: last_txs
};
res.send(a_ext);
} else
res.send({ error: 'address not found.', hash: req.params.hash});
});
});
});
} else
res.end('This method is disabled');
});
app.use('/ext/gettx/:txid', function(req, res) {
var txid = req.params.txid;
db.get_tx(txid, function(tx) {
if (tx) {
lib.get_blockcount(function(blockcount) {
res.send({ active: 'tx', tx: tx, confirmations: settings.confirmations, blockcount: (blockcount ? blockcount : 0)});
});
}
else {
lib.get_rawtransaction(txid, function(rtx) {
if (rtx && rtx.txid) {
lib.prepare_vin(rtx, function(vin) {
lib.prepare_vout(rtx.vout, rtx.txid, vin, ((typeof rtx.vjoinsplit === 'undefined' || rtx.vjoinsplit == null) ? [] : rtx.vjoinsplit), function(rvout, rvin) {
lib.calculate_total(rvout, function(total){
if (!rtx.confirmations > 0) {
var utx = {
txid: rtx.txid,
vin: rvin,
vout: rvout,
total: total.toFixed(8),
timestamp: rtx.time,
blockhash: '-',
blockindex: -1,
};
res.send({ active: 'tx', tx: utx, confirmations: settings.confirmations, blockcount:-1});
} else {
var utx = {
txid: rtx.txid,
vin: rvin,
vout: rvout,
total: total.toFixed(8),
timestamp: rtx.time,
blockhash: rtx.blockhash,
blockindex: rtx.blockheight,
};
lib.get_blockcount(function(blockcount) {
res.send({ active: 'tx', tx: utx, confirmations: settings.confirmations, blockcount: (blockcount ? blockcount : 0)});
});
}
// check if the gettx api is enabled
if (settings.public_api.ext['gettx']) {
var txid = req.params.txid;
db.get_tx(txid, function(tx) {
if (tx) {
lib.get_blockcount(function(blockcount) {
res.send({ active: 'tx', tx: tx, confirmations: settings.confirmations, blockcount: (blockcount ? blockcount : 0)});
});
}
else {
lib.get_rawtransaction(txid, function(rtx) {
if (rtx && rtx.txid) {
lib.prepare_vin(rtx, function(vin) {
lib.prepare_vout(rtx.vout, rtx.txid, vin, ((typeof rtx.vjoinsplit === 'undefined' || rtx.vjoinsplit == null) ? [] : rtx.vjoinsplit), function(rvout, rvin) {
lib.calculate_total(rvout, function(total) {
if (!rtx.confirmations > 0) {
var utx = {
txid: rtx.txid,
vin: rvin,
vout: rvout,
total: total.toFixed(8),
timestamp: rtx.time,
blockhash: '-',
blockindex: -1,
};
res.send({ active: 'tx', tx: utx, confirmations: settings.confirmations, blockcount:-1});
} else {
var utx = {
txid: rtx.txid,
vin: rvin,
vout: rvout,
total: total.toFixed(8),
timestamp: rtx.time,
blockhash: rtx.blockhash,
blockindex: rtx.blockheight,
};
lib.get_blockcount(function(blockcount) {
res.send({ active: 'tx', tx: utx, confirmations: settings.confirmations, blockcount: (blockcount ? blockcount : 0)});
});
}
});
});
});
});
} else {
res.send({ error: 'tx not found.', hash: txid});
}
});
}
});
});
app.use('/ext/getbalance/:hash', function(req,res){
db.get_address(req.params.hash, false, function(address){
if (address) {
res.setHeader('content-type', 'text/plain');
res.end((address.balance / 100000000).toString().replace(/(^-+)/mg, ''));
} else {
res.send({ error: 'address not found.', hash: req.params.hash})
}
});
});
app.use('/ext/getdistribution', function(req,res){
db.get_richlist(settings.coin, function(richlist){
db.get_stats(settings.coin, function(stats){
db.get_distribution(richlist, stats, function(dist){
res.send(dist);
});
} else {
res.send({ error: 'tx not found.', hash: txid});
}
});
}
});
});
} else
res.end('This method is disabled');
});
app.use('/ext/getcurrentprice', function(req,res){
db.get_stats(settings.coin, function (stats) {
eval('var p_ext = { "last_price_'+settings.markets.exchange.toLowerCase()+'": stats.last_price, "last_price_usd": stats.last_usd_price, }');
res.send(p_ext);
});
app.use('/ext/getbalance/:hash', function(req, res) {
// check if the getbalance api is enabled
if (settings.public_api.ext['getbalance']) {
db.get_address(req.params.hash, false, function(address) {
if (address) {
res.setHeader('content-type', 'text/plain');
res.end((address.balance / 100000000).toString().replace(/(^-+)/mg, ''));
} else
res.send({ error: 'address not found.', hash: req.params.hash });
});
} else
res.end('This method is disabled');
});
app.use('/ext/getbasicstats', function(req,res) {
lib.get_blockcount(function(blockcount) {
lib.get_supply(function(supply) {
db.get_stats(settings.coin, function (stats) {
lib.get_masternodecount(function(masternodestotal) {
eval('var p_ext = { "block_count": (blockcount ? blockcount : 0), "money_supply": (supply ? supply : 0), "last_price_'+settings.markets.exchange.toLowerCase()+'": stats.last_price, "last_price_usd": stats.last_usd_price, "masternode_count": masternodestotal.total }');
res.send(p_ext);
app.use('/ext/getdistribution', function(req, res) {
// check if the getdistribution api is enabled
if (settings.public_api.ext['getdistribution']) {
db.get_richlist(settings.coin, function(richlist) {
db.get_stats(settings.coin, function(stats) {
db.get_distribution(richlist, stats, function(dist) {
res.send(dist);
});
});
});
});
} else
res.end('This method is disabled');
});
app.use('/ext/getcurrentprice', function(req, res) {
// check if the getcurrentprice api is enabled
if (settings.public_api.ext['getcurrentprice']) {
db.get_stats(settings.coin, function (stats) {
eval('var p_ext = { "last_price_'+settings.markets.exchange.toLowerCase()+'": stats.last_price, "last_price_usd": stats.last_usd_price, }');
res.send(p_ext);
});
} else
res.end('This method is disabled');
});
app.use('/ext/getbasicstats', function(req, res) {
// check if the getbasicstats api is enabled
if (settings.public_api.ext['getbasicstats']) {
lib.get_blockcount(function(blockcount) {
lib.get_supply(function(supply) {
db.get_stats(settings.coin, function (stats) {
lib.get_masternodecount(function(masternodestotal) {
eval('var p_ext = { "block_count": (blockcount ? blockcount : 0), "money_supply": (supply ? supply : 0), "last_price_'+settings.markets.exchange.toLowerCase()+'": stats.last_price, "last_price_usd": stats.last_usd_price, "masternode_count": masternodestotal.total }');
res.send(p_ext);
});
});
});
});
} else
res.end('This method is disabled');
});
app.use('/ext/getlasttxs/:min', function(req, res) {
var min = req.params.min, start, length;
// split url suffix by forward slash and remove blank entries
var split = req.url.split('/').filter(function(v) { return v; });
// determine how many parameters were passed
switch (split.length) {
case 2:
// capture start and length
start = split[0];
length = split[1];
break;
default:
if (split.length == 1) {
// capture start
start = split[0];
} else if (split.length > 2) {
// check if the getlasttxs api is enabled or else check the headers to see if it matches an internal ajax request from the explorer itself (TODO: come up with a more secure method of whitelisting ajax calls from the explorer)
if (settings.public_api.ext['getlasttxs'] || (req.headers['x-requested-with'] != null && req.headers['x-requested-with'].toLowerCase() == 'xmlhttprequest' && req.headers.referer != null && req.headers.accept.indexOf('text/javascript') > -1 && req.headers.accept.indexOf('application/json') > -1)) {
var min = req.params.min, start, length;
// split url suffix by forward slash and remove blank entries
var split = req.url.split('/').filter(function(v) { return v; });
// determine how many parameters were passed
switch (split.length) {
case 2:
// capture start and length
start = split[0];
length = split[1];
}
break;
}
break;
default:
if (split.length == 1) {
// capture start
start = split[0];
} else if (split.length > 2) {
// capture start and length
start = split[0];
length = split[1];
}
break;
}
// fix parameters
if (typeof length === 'undefined' || isNaN(length) || length > settings.index.last_txs)
length = settings.index.last_txs;
if (typeof start === 'undefined' || isNaN(start) || start < 0)
start = 0;
if (typeof min === 'undefined' || isNaN(min) || min < 0)
min = 0;
else
min = (min * 100000000);
// fix parameters
if (typeof length === 'undefined' || isNaN(length) || length > settings.index.last_txs)
length = settings.index.last_txs;
if (typeof start === 'undefined' || isNaN(start) || start < 0)
start = 0;
if (typeof min === 'undefined' || isNaN(min) || min < 0)
min = 0;
else
min = (min * 100000000);
db.get_last_txs(start, length, min, function(data, count) {
res.json({"data":data, "recordsTotal": count, "recordsFiltered": count});
});
db.get_last_txs(start, length, min, function(data, count) {
res.json({"data":data, "recordsTotal": count, "recordsFiltered": count});
});
} else
res.end('This method is disabled');
});
app.use('/ext/getaddresstxs/:address/:start/:length', function(req,res) {
@@ -362,6 +390,7 @@ app.set('labels', settings.labels);
app.set('homelink', settings.homelink);
app.set('logoheight', settings.logoheight);
app.set('burned_coins', settings.burned_coins);
app.set('public_api', settings.public_api);
app.set('api_cmds', settings.api_cmds);
app.set('sticky_header', settings.sticky_header);
+76 -78
View File
@@ -2,27 +2,28 @@ var onode = require('./node');
var express = require('express');
var settings = require('./settings');
module.exports = function(){
function express_app(){
module.exports = function() {
function express_app() {
var app = express();
app.get('*', hasAccess, function(req, res){
var method = req.path.substring(1,req.path.length);
if('undefined' != typeof requires_passphrase[method]){
if(wallet_passphrase) client.walletPassphrase(wallet_passphrase, 10);
else res.send('A wallet passphrase is needed and has not been set.');
app.get('*', hasAccess, function(req, res) {
var method = req.path.substring(1, req.path.length);
if ('undefined' != typeof requires_passphrase[method]) {
if (wallet_passphrase)
client.walletPassphrase(wallet_passphrase, 10);
else
res.send('A wallet passphrase is needed and has not been set.');
}
var query_parameters = req.query;
var params = [];
for(var parameter in query_parameters){
if(query_parameters.hasOwnProperty(parameter)){
for (var parameter in query_parameters) {
if (query_parameters.hasOwnProperty(parameter)) {
var param = query_parameters[parameter];
if(!isNaN(param)){
if (!isNaN(param))
param = parseFloat(param);
}
params.push(param);
}
}
@@ -64,38 +65,46 @@ module.exports = function(){
break;
}
client.cmd(command, function(err, response){
if(err){console.log(err); res.send("There was an error. Check your console.");}
else{
if(typeof response === 'object'){
client.cmd(command, function(err, response) {
if (err) {
console.log(err);
res.send("There was an error. Check your console.");
} else {
if (typeof response === 'object')
res.json(response);
}
else{
else {
res.setHeader('content-type', 'text/plain');
res.end(response.toString());
}
}
});
});
function hasAccess(req, res, next){
if(accesslist.type == 'all'){
return next();
}
var method = req.path.substring(1,req.path.length);
if('undefined' == typeof accesslist[method]){
if(accesslist.type == 'only') res.end('This method is restricted.');
else return next();
}
else{
if(accesslist[method] == true){
function hasAccess(req, res, next) {
var method = req.path.substring(1, req.path.length);
var method_enabled = settings.public_api.rpc[method];
// only show disabled msg for outside calls. internal calls should always go through
if (method_enabled == null || !method_enabled && req.headers.host.indexOf('127.0.0.1') == -1)
res.end('This method is disabled');
else {
if (accesslist.type == 'all')
return next();
if ('undefined' == typeof accesslist[method]) {
if (accesslist.type == 'only')
res.end('This method is restricted');
else
return next();
} else {
if (accesslist[method] == true)
return next();
else
res.end('This method is restricted');
}
else res.end('This method is restricted.');
}
}
}
function prepareRpcCommand(cmd, addParams) {
var method_name = '';
var params = addParams || [];
@@ -116,9 +125,9 @@ module.exports = function(){
return { method: method_name, parameters: params };
}
function specialApiCase(method_name, query_parameters){
function specialApiCase(method_name, query_parameters) {
var params = [];
switch (method_name) {
case 'getnetworkhashps':
case 'getmininginfo':
@@ -185,9 +194,8 @@ module.exports = function(){
params.push(query_parameters[parameter]);
if (parameter == 'signature') {
var param = decodeURIComponent(query_parameters[parameter]);
while (param.indexOf(" ") > -1) {
while (param.indexOf(" ") > -1)
param = param.replace(" ", "+");
}
params.push(param);
}
}
@@ -200,28 +208,25 @@ module.exports = function(){
var after_account = false;
var before_min_conf = true;
var address_info = {};
for(var parameter in query_parameters){
if(query_parameters.hasOwnProperty(parameter)){
if(parameter == 'minconf'){
for (var parameter in query_parameters) {
if (query_parameters.hasOwnProperty(parameter)) {
if (parameter == 'minconf') {
before_min_conf = false;
params.push(address_info);
}
var param = query_parameters[parameter];
if(!isNaN(param)){
if (!isNaN(param))
param = parseFloat(param);
}
if(after_account && before_min_conf){
if (after_account && before_min_conf)
address_info[parameter] = param;
}
else {
else
params.push(param);
}
if(parameter == 'account') after_account = true;
if (parameter == 'account')
after_account = true;
}
}
if(before_min_conf){
if (before_min_conf)
params.push(address_info);
}
break;
}
@@ -249,56 +254,49 @@ module.exports = function(){
'signrawtransaction': true
};
function setAccess(type, access_list){
function setAccess(type, access_list) {
//Reset//
accesslist = {};
accesslist.type = type;
if(type == "only"){
var i=0;
for(; i<access_list.length; i++){
if (type == "only") {
for (i = 0; i < access_list.length; i++)
accesslist[access_list[i]] = true;
}
}
if(type == "restrict"){
var i=0;
for(; i<access_list.length; i++){
if (type == "restrict") {
for (i = 0; i < access_list.length; i++)
accesslist[access_list[i]] = false;
}
}
//Default is for security reasons. Prevents accidental theft of coins/attack
if(type == 'default-safe'){
accesslist.type = 'restrict';
if (type == 'default-safe') {
var restrict_list = ['dumpprivkey', 'walletpassphrasechange', 'stop'];
var i=0;
for(;i<restrict_list.length;i++){
accesslist[restrict_list[i]] = false;
}
}
if(type == 'read-only'){
accesslist.type = 'restrict';
var restrict_list = ['addmultisigaddress', 'addnode', 'backupwallet', 'createmultisig', 'createrawtransaction', 'encryptwallet', 'importprivkey', 'keypoolrefill', 'lockunspent', 'move', 'sendfrom', 'sendmany', 'sendrawtransaction', 'sendtoaddress', 'setaccount', 'setgenerate', 'settxfee', 'signmessage', 'signrawtransaction', 'stop', 'submitblock', 'walletlock', 'walletpassphrasechange'];
var i=0;
for(;i<restrict_list.length;i++){
for (i = 0; i < restrict_list.length; i++)
accesslist[restrict_list[i]] = false;
}
if (type == 'read-only') {
var restrict_list = ['addmultisigaddress', 'addnode', 'backupwallet', 'createmultisig', 'createrawtransaction', 'encryptwallet', 'importprivkey', 'keypoolrefill', 'lockunspent', 'move', 'sendfrom', 'sendmany', 'sendrawtransaction', 'sendtoaddress', 'setaccount', 'setgenerate', 'settxfee', 'signmessage', 'signrawtransaction', 'stop', 'submitblock', 'walletlock', 'walletpassphrasechange'];
accesslist.type = 'restrict';
for (i=0; i < restrict_list.length; i++)
accesslist[restrict_list[i]] = false;
}
}
};
function setWalletDetails(details){
if('undefined' == typeof details.rpc){
function setWalletDetails(details) {
if ('undefined' == typeof details.rpc)
client = new onode.Client(details);
}
else{
else
client = details;
}
};
function setWalletPassphrase(passphrase){
function setWalletPassphrase(passphrase) {
wallet_passphrase = passphrase;
};
@@ -308,4 +306,4 @@ module.exports = function(){
setWalletDetails: setWalletDetails,
setWalletPassphrase: setWalletPassphrase
}
}();
}();
+34
View File
@@ -189,6 +189,40 @@ exports.corsorigin = "*";
exports.labels = {};
exports.burned_coins = [];
// Enable/disable the use of specific public apis
exports.public_api = {
"rpc": {
"getdifficulty": true,
"getconnectioncount": true,
"getblockcount": true,
"getblockhash": true,
"getblock": true,
"getrawtransaction": true,
"getnetworkhashps": true,
"getvotelist": true,
"getmasternodecount": true,
"getmasternodelist": true,
"getmaxmoney": true,
"getmaxvote": true,
"getvote": true,
"getphase": true,
"getreward": true,
"getsupply": true,
"getnextrewardestimate": true,
"getnextrewardwhenstr": true
},
"ext": {
"getmoneysupply": true,
"getdistribution": true,
"getaddress": true,
"gettx": true,
"getbalance": true,
"getlasttxs": true,
"getcurrentprice": true,
"getbasicstats": true
}
};
// Customized API commands
exports.api_cmds = {
"getnetworkhashps": "getnetworkhashps",
+35
View File
@@ -271,6 +271,41 @@
// }
//]
"burned_coins": [],
// Enable/disable the use of specific public apis
// Setting any of these apis to false will remove the api definition from the /info page and will return a "This method is disabled" msg if the api endpoint is called
"public_api": {
"rpc": {
"getdifficulty": true,
"getconnectioncount": true,
"getblockcount": true,
"getblockhash": true,
"getblock": true,
"getrawtransaction": true,
"getnetworkhashps": true,
"getvotelist": true,
"getmasternodecount": true,
"getmasternodelist": true,
"getmaxmoney": true,
"getmaxvote": true,
"getvote": true,
"getphase": true,
"getreward": true,
"getsupply": true,
"getnextrewardestimate": true,
"getnextrewardwhenstr": true
},
"ext": {
"getmoneysupply": true,
"getdistribution": true,
"getaddress": true,
"gettx": true,
"getbalance": true,
"getlasttxs": true,
"getcurrentprice": true,
"getbasicstats": true
}
},
// Customized API commands
// Not all blockchains utilize the same rpc cmds for accessing the internal daemon api.
+179 -167
View File
@@ -10,197 +10,209 @@ block content
p
em #{settings.locale.api_message}
hr
h3 #{settings.locale.api_calls}
p
em Return data from coind
ul
if settings.api_cmds['getdifficulty'] != null && settings.api_cmds['getdifficulty'] != ''
li
p
div.font-weight-bold getdifficulty
div
em #{settings.locale.api_getdifficulty}
a(href='/api/getdifficulty') #{address}/api/getdifficulty
if settings.api_cmds['getconnectioncount'] != null && settings.api_cmds['getconnectioncount'] != ''
li
p
div.font-weight-bold getconnectioncount
div
em #{settings.locale.api_getconnectioncount}
a(href='/api/getconnectioncount') #{address}/api/getconnectioncount
if settings.api_cmds['getblockcount'] != null && settings.api_cmds['getblockcount'] != ''
li
p
div.font-weight-bold getblockcount
div
em #{settings.locale.api_getblockcount}
a(href='/api/getblockcount') #{address}/api/getblockcount
if settings.api_cmds['getblockhash'] != null && settings.api_cmds['getblockhash'] != ''
li
p
div.font-weight-bold getblockhash [index]
div
em #{settings.locale.api_getblockhash}
a(href='/api/getblockhash?index=' + hashes.blockindex) #{address}/api/getblockhash?index=#{hashes.blockindex}
if settings.api_cmds['getblock'] != null && settings.api_cmds['getblock'] != ''
li
p
div.font-weight-bold getblock [hash]
div
em #{settings.locale.api_getblock}
a(href='/api/getblock?hash=' + hashes.blockhash) #{address}/api/getblock?hash=#{hashes.blockhash}
if settings.api_cmds['getrawtransaction'] != null && settings.api_cmds['getrawtransaction'] != ''
li
p
div.font-weight-bold getrawtransaction [txid] [decrypt]
div
em #{settings.locale.api_getrawtransaction}
div
a(href='/api/getrawtransaction?txid=' + hashes.txhash + '&decrypt=0') #{address}/api/getrawtransaction?txid=#{hashes.txhash}&decrypt=0
div
a(href='/api/getrawtransaction?txid=' + hashes.txhash + '&decrypt=1') #{address}/api/getrawtransaction?txid=#{hashes.txhash}&decrypt=1
if settings.index.show_hashrate == true && settings.api_cmds['getnetworkhashps'] != null && settings.api_cmds['getnetworkhashps'] != ''
li
p
div.font-weight-bold getnetworkhashps
div
em #{settings.locale.api_getnetworkhashps}
a(href='/api/getnetworkhashps') #{address}/api/getnetworkhashps
if settings.api_cmds['getvotelist'] != null && settings.api_cmds['getvotelist'] != ''
li
p
div.font-weight-bold getvotelist
div
em #{settings.locale.api_getvotelist}
a(href='/api/getvotelist') #{address}/api/getvotelist
if settings.api_cmds['getmasternodecount'] != null && settings.api_cmds['getmasternodecount'] != ''
li
p
div.font-weight-bold getmasternodecount
div
em #{settings.locale.api_getmasternodecount}
a(href='/api/getmasternodecount') #{address}/api/getmasternodecount
if settings.api_cmds['getmasternodelist'] != null && settings.api_cmds['getmasternodelist'] != ''
li
p
div.font-weight-bold getmasternodelist
div
em #{settings.locale.api_getmasternodelist}
a(href='/api/getmasternodelist') #{address}/api/getmasternodelist
if settings.heavy == true
if settings.api_cmds.heavies['getmaxmoney'] != null && settings.api_cmds.heavies['getmaxmoney'] != ''
- 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.public_api.rpc['getmasternodelist'] == true && settings.api_cmds['getmasternodelist'] != null && settings.api_cmds['getmasternodelist'] != '') && (!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'];
if !hide_rpc_api_section
h3 #{settings.locale.api_calls}
p
em Return data from coind
ul
if settings.public_api.rpc['getdifficulty'] == true && settings.api_cmds['getdifficulty'] != null && settings.api_cmds['getdifficulty'] != ''
li
p
div.font-weight-bold getmaxmoney
div.font-weight-bold getdifficulty
div
em #{settings.locale.api_getmaxmoney}
a(href='/api/getmaxmoney') #{address}/api/getmaxmoney
if settings.api_cmds.heavies['getmaxvote'] != null && settings.api_cmds.heavies['getmaxvote'] != ''
em #{settings.locale.api_getdifficulty}
a(href='/api/getdifficulty') #{address}/api/getdifficulty
if settings.public_api.rpc['getconnectioncount'] == true && settings.api_cmds['getconnectioncount'] != null && settings.api_cmds['getconnectioncount'] != ''
li
p
div.font-weight-bold getmaxvote
div.font-weight-bold getconnectioncount
div
em #{settings.locale.api_getmaxvote}
a(href='/api/getmaxvote') #{address}/api/getmaxvote
if settings.api_cmds.heavies['getvote'] != null && settings.api_cmds.heavies['getvote'] != ''
em #{settings.locale.api_getconnectioncount}
a(href='/api/getconnectioncount') #{address}/api/getconnectioncount
if settings.public_api.rpc['getblockcount'] == true && settings.api_cmds['getblockcount'] != null && settings.api_cmds['getblockcount'] != ''
li
p
div.font-weight-bold getvote
div.font-weight-bold getblockcount
div
em #{settings.locale.api_getvote}
a(href='/api/getvote') #{address}/api/getvote
if settings.api_cmds.heavies['getphase'] != null && settings.api_cmds.heavies['getphase'] != ''
em #{settings.locale.api_getblockcount}
a(href='/api/getblockcount') #{address}/api/getblockcount
if settings.public_api.rpc['getblockhash'] == true && settings.api_cmds['getblockhash'] != null && settings.api_cmds['getblockhash'] != ''
li
p
div.font-weight-bold getphase
div.font-weight-bold getblockhash [index]
div
em #{settings.locale.api_getphase}
a(href='/api/getphase') #{address}/api/getphase
if settings.api_cmds.heavies['getreward'] != null && settings.api_cmds.heavies['getreward'] != ''
em #{settings.locale.api_getblockhash}
a(href='/api/getblockhash?index=' + hashes.blockindex) #{address}/api/getblockhash?index=#{hashes.blockindex}
if settings.public_api.rpc['getblock'] == true && settings.api_cmds['getblock'] != null && settings.api_cmds['getblock'] != ''
li
p
div.font-weight-bold getreward
div.font-weight-bold getblock [hash]
div
em #{settings.locale.api_getreward}
a(href='/api/getreward') #{address}/api/getreward
if settings.api_cmds.heavies['getsupply'] != null && settings.api_cmds.heavies['getsupply'] != ''
em #{settings.locale.api_getblock}
a(href='/api/getblock?hash=' + hashes.blockhash) #{address}/api/getblock?hash=#{hashes.blockhash}
if settings.public_api.rpc['getrawtransaction'] == true && settings.api_cmds['getrawtransaction'] != null && settings.api_cmds['getrawtransaction'] != ''
li
p
div.font-weight-bold getsupply
div.font-weight-bold getrawtransaction [txid] [decrypt]
div
em #{settings.locale.api_getsupply}
a(href='/api/getsupply') #{address}/api/getsupply
if settings.api_cmds.heavies['getnextrewardestimate'] != null && settings.api_cmds.heavies['getnextrewardestimate'] != ''
em #{settings.locale.api_getrawtransaction}
div
a(href='/api/getrawtransaction?txid=' + hashes.txhash + '&decrypt=0') #{address}/api/getrawtransaction?txid=#{hashes.txhash}&decrypt=0
div
a(href='/api/getrawtransaction?txid=' + hashes.txhash + '&decrypt=1') #{address}/api/getrawtransaction?txid=#{hashes.txhash}&decrypt=1
if settings.public_api.rpc['getnetworkhashps'] == true && settings.index.show_hashrate == true && settings.api_cmds['getnetworkhashps'] != null && settings.api_cmds['getnetworkhashps'] != ''
li
p
div.font-weight-bold getnextrewardestimate
div.font-weight-bold getnetworkhashps
div
em #{settings.locale.api_getnextrewardestimate}
a(href='/api/getnextrewardestimate') #{address}/api/getnextrewardestimate
if settings.api_cmds.heavies['getnextrewardwhenstr'] != null && settings.api_cmds.heavies['getnextrewardwhenstr'] != ''
em #{settings.locale.api_getnetworkhashps}
a(href='/api/getnetworkhashps') #{address}/api/getnetworkhashps
if settings.public_api.rpc['getvotelist'] == true && settings.api_cmds['getvotelist'] != null && settings.api_cmds['getvotelist'] != ''
li
p
div.font-weight-bold getnextrewardwhenstr
div.font-weight-bold getvotelist
div
em #{settings.locale.api_getnextrewardwhenstr}
a(href='/api/getnextrewardwhenstr') #{address}/api/getnextrewardwhenstr
hr
h3 Extended API
p
em Return data from local indexes
ul
li
p
div.font-weight-bold getmoneysupply
div
em Returns current money supply
a(href='/ext/getmoneysupply') #{address}/ext/getmoneysupply
li
p
div.font-weight-bold getdistribution
div
em Returns wealth distribution stats
a(href='/ext/getdistribution') #{address}/ext/getdistribution
li
p
div.font-weight-bold getaddress (/ext/getaddress/hash)
div
em Returns information for given address
a(href='/ext/getaddress/' + hashes.address) #{address}/ext/getaddress/#{hashes.address}
li
p
div.font-weight-bold gettx (/ext/gettx/hash)
div
em Returns information for given tx hash
a(href='/ext/gettx/' + hashes.txhash) #{address}/ext/gettx/#{hashes.txhash}
li
p
div.font-weight-bold getbalance (/ext/getbalance/hash)
div
em Returns current balance of given address
a(href='/ext/getbalance/' + hashes.address) #{address}/ext/getbalance/#{hashes.address}
li
p
div.font-weight-bold getlasttxs (/ext/getlasttxs/min/start/length)
div
em Returns last [length] transactions greater than [min], starting from offset [start]
div
em Note: returned values are in satoshis
div
a(href='/ext/getlasttxs/100/0/100') #{address}/ext/getlasttxs/100/0/100
li
p
div.font-weight-bold getcurrentprice
div
em Returns last known exchange price
a(href='/ext/getcurrentprice') #{address}/ext/getcurrentprice
li
p
div.font-weight-bold getbasicstats
div
em Returns basic statistics about the coin including: block count, circulating supply, USD price, BTC price and # of masternodes
a(href='/ext/getbasicstats') #{address}/ext/getbasicstats
hr
em #{settings.locale.api_getvotelist}
a(href='/api/getvotelist') #{address}/api/getvotelist
if settings.public_api.rpc['getmasternodecount'] == true && settings.api_cmds['getmasternodecount'] != null && settings.api_cmds['getmasternodecount'] != ''
li
p
div.font-weight-bold getmasternodecount
div
em #{settings.locale.api_getmasternodecount}
a(href='/api/getmasternodecount') #{address}/api/getmasternodecount
if settings.public_api.rpc['getmasternodelist'] == true && settings.api_cmds['getmasternodelist'] != null && settings.api_cmds['getmasternodelist'] != ''
li
p
div.font-weight-bold getmasternodelist
div
em #{settings.locale.api_getmasternodelist}
a(href='/api/getmasternodelist') #{address}/api/getmasternodelist
if settings.heavy == true
if settings.public_api.rpc['getmaxmoney'] == true && settings.api_cmds.heavies['getmaxmoney'] != null && settings.api_cmds.heavies['getmaxmoney'] != ''
li
p
div.font-weight-bold getmaxmoney
div
em #{settings.locale.api_getmaxmoney}
a(href='/api/getmaxmoney') #{address}/api/getmaxmoney
if settings.public_api.rpc['getmaxvote'] == true && settings.api_cmds.heavies['getmaxvote'] != null && settings.api_cmds.heavies['getmaxvote'] != ''
li
p
div.font-weight-bold getmaxvote
div
em #{settings.locale.api_getmaxvote}
a(href='/api/getmaxvote') #{address}/api/getmaxvote
if settings.public_api.rpc['getvote'] == true && settings.api_cmds.heavies['getvote'] != null && settings.api_cmds.heavies['getvote'] != ''
li
p
div.font-weight-bold getvote
div
em #{settings.locale.api_getvote}
a(href='/api/getvote') #{address}/api/getvote
if settings.public_api.rpc['getphase'] == true && settings.api_cmds.heavies['getphase'] != null && settings.api_cmds.heavies['getphase'] != ''
li
p
div.font-weight-bold getphase
div
em #{settings.locale.api_getphase}
a(href='/api/getphase') #{address}/api/getphase
if settings.public_api.rpc['getreward'] == true && settings.api_cmds.heavies['getreward'] != null && settings.api_cmds.heavies['getreward'] != ''
li
p
div.font-weight-bold getreward
div
em #{settings.locale.api_getreward}
a(href='/api/getreward') #{address}/api/getreward
if settings.public_api.rpc['getsupply'] == true && settings.api_cmds.heavies['getsupply'] != null && settings.api_cmds.heavies['getsupply'] != ''
li
p
div.font-weight-bold getsupply
div
em #{settings.locale.api_getsupply}
a(href='/api/getsupply') #{address}/api/getsupply
if settings.public_api.rpc['getnextrewardestimate'] == true && settings.api_cmds.heavies['getnextrewardestimate'] != null && settings.api_cmds.heavies['getnextrewardestimate'] != ''
li
p
div.font-weight-bold getnextrewardestimate
div
em #{settings.locale.api_getnextrewardestimate}
a(href='/api/getnextrewardestimate') #{address}/api/getnextrewardestimate
if settings.public_api.rpc['getnextrewardwhenstr'] == true && settings.api_cmds.heavies['getnextrewardwhenstr'] != null && settings.api_cmds.heavies['getnextrewardwhenstr'] != ''
li
p
div.font-weight-bold getnextrewardwhenstr
div
em #{settings.locale.api_getnextrewardwhenstr}
a(href='/api/getnextrewardwhenstr') #{address}/api/getnextrewardwhenstr
hr
if !hide_ext_api_section
h3 Extended API
p
em Return data from local indexes
ul
if settings.public_api.ext['getmoneysupply'] == true
li
p
div.font-weight-bold getmoneysupply
div
em Returns current money supply
a(href='/ext/getmoneysupply') #{address}/ext/getmoneysupply
if settings.public_api.ext['getdistribution'] == true
li
p
div.font-weight-bold getdistribution
div
em Returns wealth distribution stats
a(href='/ext/getdistribution') #{address}/ext/getdistribution
if settings.public_api.ext['getaddress'] == true
li
p
div.font-weight-bold getaddress (/ext/getaddress/hash)
div
em Returns information for given address
a(href='/ext/getaddress/' + hashes.address) #{address}/ext/getaddress/#{hashes.address}
if settings.public_api.ext['gettx'] == true
li
p
div.font-weight-bold gettx (/ext/gettx/hash)
div
em Returns information for given tx hash
a(href='/ext/gettx/' + hashes.txhash) #{address}/ext/gettx/#{hashes.txhash}
if settings.public_api.ext['getbalance'] == true
li
p
div.font-weight-bold getbalance (/ext/getbalance/hash)
div
em Returns current balance of given address
a(href='/ext/getbalance/' + hashes.address) #{address}/ext/getbalance/#{hashes.address}
if settings.public_api.ext['getlasttxs'] == true
li
p
div.font-weight-bold getlasttxs (/ext/getlasttxs/min/start/length)
div
em Returns last [length] transactions greater than [min], starting from offset [start]
div
em Note: returned values are in satoshis
div
a(href='/ext/getlasttxs/100/0/100') #{address}/ext/getlasttxs/100/0/100
if settings.public_api.ext['getcurrentprice'] == true
li
p
div.font-weight-bold getcurrentprice
div
em Returns last known exchange price
a(href='/ext/getcurrentprice') #{address}/ext/getcurrentprice
if settings.public_api.ext['getbasicstats'] == true
li
p
div.font-weight-bold getbasicstats
div
em Returns basic statistics about the coin including: block count, circulating supply, USD price, BTC price and # of masternodes
a(href='/ext/getbasicstats') #{address}/ext/getbasicstats
hr
h3 Linking (GET)
p
em Linking to the block explorer