Browse Source

split out credentials from the rest of the site config and do some renaming

fix-133-memory-crash
Dan Janosik 7 years ago
parent
commit
e4eef424ab
  1. 4
      README.md
  2. 45
      app.js
  3. 27
      app/config.js
  4. 12
      app/credentials.js
  5. 20
      app/rpcApi.js
  6. 10
      app/utils.js
  7. 32
      routes/baseActionsRouter.js
  8. 12
      views/about.pug
  9. 2
      views/index.pug
  10. 28
      views/layout.pug
  11. 2
      views/terminal.pug

4
README.md

@ -37,8 +37,8 @@ The below instructions are geared toward BTC, but can be adapted easily to other
1. Clone this repo
2. `npm install` to install all required dependencies
3. Edit the "rpc" settings in [env.js](app/env.js) to target your node
4. Optional: Change the "coin" value in [env.js](app/env.js). Currently supported values are "BTC" and "LTC".
3. Edit the "rpc" settings in [credentials.js](app/credentials.js) to target your node
4. Optional: Change the "coin" value in [config.js](app/config.js). Currently supported values are "BTC" and "LTC".
5. `npm start` to start the local server
6. Visit http://127.0.0.1:3002/

45
app.js

@ -9,7 +9,7 @@ var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require("express-session");
var env = require("./app/env.js");
var config = require("./app/config.js");
var simpleGit = require('simple-git');
var utils = require("./app/utils.js");
var moment = require("moment");
@ -45,7 +45,7 @@ app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
secret: env.cookiePassword,
secret: config.cookiePassword,
resave: false,
saveUninitialized: false
}));
@ -53,17 +53,17 @@ app.use(express.static(path.join(__dirname, 'public')));
function refreshExchangeRate() {
if (coins[env.coin].exchangeRateData) {
request(coins[env.coin].exchangeRateData.jsonUrl, function(error, response, body) {
if (coins[config.coin].exchangeRateData) {
request(coins[config.coin].exchangeRateData.jsonUrl, function(error, response, body) {
if (!error && response && response.statusCode && response.statusCode == 200) {
var responseBody = JSON.parse(body);
var exchangeRate = coins[env.coin].exchangeRateData.responseBodySelectorFunction(responseBody);
var exchangeRate = coins[config.coin].exchangeRateData.responseBodySelectorFunction(responseBody);
if (exchangeRate > 0) {
global.exchangeRate = exchangeRate;
global.exchangeRateUpdateTime = new Date();
console.log("Using exchange rate: " + global.exchangeRate + " USD/" + coins[env.coin].name + " starting at " + global.exchangeRateUpdateTime);
console.log("Using exchange rate: " + global.exchangeRate + " USD/" + coins[config.coin].name + " starting at " + global.exchangeRateUpdateTime);
} else {
console.log("Unable to get exchange rate data");
@ -81,34 +81,34 @@ function refreshExchangeRate() {
app.runOnStartup = function() {
global.env = env;
global.coinConfig = coins[env.coin];
global.config = config;
global.coinConfig = coins[config.coin];
global.coinConfigs = coins;
console.log("Running RPC Explorer for coin: " + global.coinConfig.name);
if (env.rpc) {
console.log("Connecting via RPC to node at " + env.rpc.host + ":" + env.rpc.port);
if (config.credentials.rpc) {
console.log("Connecting via RPC to node at " + config.credentials.rpc.host + ":" + config.credentials.rpc.port);
global.client = new bitcoinCore({
host: env.rpc.host,
port: env.rpc.port,
username: env.rpc.username,
password: env.rpc.password,
host: config.credentials.rpc.host,
port: config.credentials.rpc.port,
username: config.credentials.rpc.username,
password: config.credentials.rpc.password,
timeout: 5000
});
}
if (env.donationAddresses) {
if (config.donationAddresses) {
var getDonationAddressQrCode = function(coinId) {
qrcode.toDataURL(env.donationAddresses[coinId].address, function(err, url) {
qrcode.toDataURL(config.donationAddresses[coinId].address, function(err, url) {
global.donationAddressQrCodeUrls[coinId] = url;
});
};
global.donationAddressQrCodeUrls = {};
env.donationAddresses.coins.forEach(function(item) {
config.donationAddresses.coins.forEach(function(item) {
getDonationAddressQrCode(item);
});
}
@ -145,15 +145,14 @@ app.runOnStartup = function() {
app.use(function(req, res, next) {
// make session available in templates
res.locals.session = req.session;
res.locals.debug = env.debug;
if (env.rpc && req.session.host == null) {
req.session.host = env.rpc.host;
req.session.port = env.rpc.port;
req.session.username = env.rpc.username;
if (config.credentials.rpc && req.session.host == null) {
req.session.host = config.credentials.rpc.host;
req.session.port = config.credentials.rpc.port;
req.session.username = config.credentials.rpc.username;
}
res.locals.env = global.env;
res.locals.config = global.config;
res.locals.coinConfig = global.coinConfig;
res.locals.host = req.session.host;

27
app/env.js → app/config.js

@ -1,3 +1,5 @@
var credentials = require("./credentials.js");
module.exports = {
cookiePassword: "0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
demoSite: true,
@ -24,15 +26,7 @@ module.exports = {
"walletpassphrasechange"
],
// Edit "rpc" below to target your node.
// You may delete this section if you wish to connect manually via the UI.
rpc: {
host:"127.0.0.1",
port:8332,
username:"rpc-username",
password:"rpc-password"
},
credentials: credentials,
// Edit "ipWhitelistForRpcCommands" regex to limit access to RPC Browser / Terminal to matching IPs
ipWhitelistForRpcCommands:/^(127\.0\.0\.1)?(\:\:1)?$/,
@ -40,10 +34,21 @@ module.exports = {
googleAnalyticsTrackingId:"",
sentryUrl:"",
miningPoolsConfigUrl:"https://raw.githubusercontent.com/blockchain/Blockchain-Known-Pools/master/pools.json",
donationAddresses:{
coins:["BTC", "LTC"],
"BTC":{address:"3NPGpNyLLmVKCEcuipBs7G4KpQJoJXjDGe", urlPrefix:"bitcoin:"},
"LTC":{address:"ME4pXiXuWfEi1ANBDo9irUJVcZBhsTx14i", urlPrefix:"litecoin:"}
},
};
headerDropdownLinks: {
title:"Related Tools",
links:[
{name: "Bitcoin Explorer", url:"https://btc-explorer.chaintools.io", imgUrl:"/img/logo/btc.svg"},
{name: "Litecoin Explorer", url:"https://ltc-explorer.chaintools.io", imgUrl:"/img/logo/ltc.svg"},
{name: "Lightning Explorer", url:"https://lightning-explorer.chaintools.io", imgUrl:"/img/logo/lightning.svg"},
]
}
};

12
app/credentials.js

@ -0,0 +1,12 @@
module.exports = {
// Edit "rpc" below to target your node.
// You may delete this section if you wish to connect manually via the UI.
rpc: {
host:"localhost",
port:8332,
username:"username",
password:"password"
}
};

20
app/rpcApi.js

@ -1,16 +1,16 @@
var utils = require("./utils.js");
var env = require("./env.js");
var config = require("./config.js");
var coins = require("./coins.js");
function getGenesisBlockHash() {
return coins[env.coin].genesisBlockHash;
return coins[config.coin].genesisBlockHash;
}
function getGenesisCoinbaseTransactionId() {
return coins[env.coin].genesisCoinbaseTransactionId;
return coins[config.coin].genesisCoinbaseTransactionId;
}
function getRpcData(cmd) {
@ -92,7 +92,7 @@ function getMempoolStats() {
}
}
var satoshiPerByteBucketMaxima = coins[env.coin].feeSatoshiPerByteBucketMaxima;
var satoshiPerByteBucketMaxima = coins[config.coin].feeSatoshiPerByteBucketMaxima;
var bucketCount = satoshiPerByteBucketMaxima.length + 1;
var satoshiPerByteBuckets = [];
@ -263,9 +263,9 @@ function getTransactionInputs(transaction, inputLimit=0) {
function getRawTransaction(txid) {
return new Promise(function(resolve, reject) {
if (txid == coins[env.coin].genesisCoinbaseTransactionId) {
if (txid == coins[config.coin].genesisCoinbaseTransactionId) {
getBlockByHeight(0).then(function(blockZeroResult) {
var result = coins[env.coin].genesisCoinbaseTransaction;
var result = coins[config.coin].genesisCoinbaseTransaction;
result.confirmations = blockZeroResult.getblock.confirmations;
resolve(result);
@ -302,11 +302,11 @@ function getRawTransactions(txids) {
return;
}
if (coins[env.coin].genesisCoinbaseTransactionId) {
if (txids.length == 1 && txids[0] == coins[env.coin].genesisCoinbaseTransactionId) {
if (coins[config.coin].genesisCoinbaseTransactionId) {
if (txids.length == 1 && txids[0] == coins[config.coin].genesisCoinbaseTransactionId) {
// copy the "confirmations" field from genesis block to the genesis-coinbase tx
getBlockByHeight(0).then(function(blockZeroResult) {
var result = coins[env.coin].genesisCoinbaseTransaction;
var result = coins[config.coin].genesisCoinbaseTransaction;
result.confirmations = blockZeroResult.getblock.confirmations;
resolve([result]);
@ -558,7 +558,7 @@ function getRpcMethodHelp(methodName) {
}
function getHistoricalData() {
var sortedList = coins[env.coin].historicalData;
var sortedList = coins[config.coin].historicalData;
sortedList.sort(function(a, b){
return ((a.date > b.date) ? 1 : -1);
});

10
app/utils.js

@ -1,5 +1,5 @@
var Decimal = require("decimal.js");
var env = require("./env.js");
var config = require("./config.js");
var coins = require("./coins.js");
function doSmartRedirect(req, res, defaultUrl) {
@ -103,8 +103,8 @@ function formatCurrencyAmount(amount, formatType) {
return addThousandsSeparators(dec.toDecimalPlaces(decimalPlaces)) + " " + formatCurrencyCache[formatType].name;
}
for (var x = 0; x < coins[env.coin].currencyUnits.length; x++) {
var currencyUnit = coins[env.coin].currencyUnits[x];
for (var x = 0; x < coins[config.coin].currencyUnits.length; x++) {
var currencyUnit = coins[config.coin].currencyUnits[x];
for (var y = 0; y < currencyUnit.values.length; y++) {
var currencyUnitValue = currencyUnit.values[y];
@ -129,7 +129,7 @@ function formatCurrencyAmount(amount, formatType) {
}
function formatCurrencyAmountInSmallestUnits(amount) {
return formatCurrencyAmount(amount, coins[env.coin].currencyUnits[coins[env.coin].currencyUnits.length - 1].name);
return formatCurrencyAmount(amount, coins[config.coin].currencyUnits[coins[config.coin].currencyUnits.length - 1].name);
}
// ref: https://stackoverflow.com/a/2901298/673828
@ -145,7 +145,7 @@ function formatExchangedCurrency(amount) {
var dec = new Decimal(amount);
dec = dec.times(global.exchangeRate);
return addThousandsSeparators(dec.toDecimalPlaces(2)) + " " + coins[env.coin].exchangeRateData.exchangedCurrencyName;
return addThousandsSeparators(dec.toDecimalPlaces(2)) + " " + coins[config.coin].exchangeRateData.exchangedCurrencyName;
}
return "";

32
routes/baseActionsRouter.js

@ -3,7 +3,7 @@ var router = express.Router();
var util = require('util');
var moment = require('moment');
var utils = require('./../app/utils');
var env = require("./../app/env");
var config = require("./../app/config.js");
var bitcoinCore = require("bitcoin-core");
var rpcApi = require("./../app/rpcApi");
var qrcode = require('qrcode');
@ -104,7 +104,7 @@ router.get("/mempool-summary", function(req, res) {
res.render("mempool-summary");
});
}).catch(function(err) {
res.locals.userMessage = "Unable to connect to Bitcoin Node at " + env.rpc.host + ":" + env.rpc.port;
res.locals.userMessage = "Error: " + err;
res.render("mempool-summary");
});
@ -214,7 +214,7 @@ router.get("/blocks", function(req, res) {
res.render("blocks");
});
}).catch(function(err) {
res.locals.userMessage = "Unable to connect to Bitcoin Node at " + env.rpc.host + ":" + env.rpc.port;
res.locals.userMessage = "Error: " + err;
res.render("blocks");
});
@ -467,12 +467,12 @@ router.get("/address/:address", function(req, res) {
});
router.get("/rpc-terminal", function(req, res) {
if (!env.demoSite) {
if (!config.demoSite) {
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
var match = env.ipWhitelistForRpcCommands.exec(ip);
var match = config.ipWhitelistForRpcCommands.exec(ip);
if (!match) {
res.send("RPC Terminal / Browser may not be accessed from '" + ip + "'. This restriction can be modified in your env.js file.");
res.send("RPC Terminal / Browser may not be accessed from '" + ip + "'. This restriction can be modified in your config.js file.");
return;
}
@ -482,12 +482,12 @@ router.get("/rpc-terminal", function(req, res) {
});
router.post("/rpc-terminal", function(req, res) {
if (!env.demoSite) {
if (!config.demoSite) {
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
var match = env.ipWhitelistForRpcCommands.exec(ip);
var match = config.ipWhitelistForRpcCommands.exec(ip);
if (!match) {
res.send("RPC Terminal / Browser may not be accessed from '" + ip + "'. This restriction can be modified in your env.js file.");
res.send("RPC Terminal / Browser may not be accessed from '" + ip + "'. This restriction can be modified in your config.js file.");
return;
}
@ -506,8 +506,8 @@ router.post("/rpc-terminal", function(req, res) {
}
});
if (env.rpcBlacklist.includes(cmd.toLowerCase())) {
res.write("Sorry, that RPC command is blacklisted. If this is your server, you may allow this command by removing it from the 'rpcBlacklist' setting in env.js.", function() {
if (config.rpcBlacklist.includes(cmd.toLowerCase())) {
res.write("Sorry, that RPC command is blacklisted. If this is your server, you may allow this command by removing it from the 'rpcBlacklist' setting in config.js.", function() {
res.end();
});
@ -540,12 +540,12 @@ router.post("/rpc-terminal", function(req, res) {
});
router.get("/rpc-browser", function(req, res) {
if (!env.demoSite) {
if (!config.demoSite) {
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
var match = env.ipWhitelistForRpcCommands.exec(ip);
var match = config.ipWhitelistForRpcCommands.exec(ip);
if (!match) {
res.send("RPC Terminal / Browser may not be accessed from '" + ip + "'. This restriction can be modified in your env.js file.");
res.send("RPC Terminal / Browser may not be accessed from '" + ip + "'. This restriction can be modified in your config.js file.");
return;
}
@ -599,8 +599,8 @@ router.get("/rpc-browser", function(req, res) {
res.locals.argValues = argValues;
if (env.rpcBlacklist.includes(req.query.method.toLowerCase())) {
res.locals.methodResult = "Sorry, that RPC command is blacklisted. If this is your server, you may allow this command by removing it from the 'rpcBlacklist' setting in env.js.";
if (config.rpcBlacklist.includes(req.query.method.toLowerCase())) {
res.locals.methodResult = "Sorry, that RPC command is blacklisted. If this is your server, you may allow this command by removing it from the 'rpcBlacklist' setting in config.js.";
res.render("browser");

12
views/about.pug

@ -14,21 +14,21 @@ block content
p Pull requests are welcome!
a(href="https://github.com/janoside/btc-rpc-explorer") github.com/janoside/btc-rpc-explorer
if (env.donationAddresses)
if (config.donationAddresses)
hr
p If you value this tool and want to support my work on this project, please consider a small donation. Anything is appreciated!
each coin, index in env.donationAddresses.coins
each coin, index in config.donationAddresses.coins
div(style="display: inline-block;", class="text-md-center mb-3", class=(index > 0 ? "ml-md-5" : false))
if (env.donationAddresses[coin].urlPrefix)
a(href=("bitcoin:" + env.donationAddresses["BTC"])) #{coinConfigs[coin].name} (#{coin})
if (config.donationAddresses[coin].urlPrefix)
a(href=("bitcoin:" + config.donationAddresses["BTC"])) #{coinConfigs[coin].name} (#{coin})
else
span #{coinConfigs[coin].name} (#{coin})
br
span #{env.donationAddresses[coin].address}
span #{config.donationAddresses[coin].address}
br
img(src=donationAddressQrCodeUrls[coin], alt=env.donationAddresses[coin].address, style="border: solid 1px #ccc;")
img(src=donationAddressQrCodeUrls[coin], alt=config.donationAddresses[coin].address, style="border: solid 1px #ccc;")
br

2
views/index.pug

@ -7,7 +7,7 @@ block content
h1(class="h2") #{coinConfig.siteTitle}
hr
if (env.demoSite)
if (config.demoSite)
div(class="alert alert-primary", role="alert")
p
strong #{coinConfig.siteTitle}

28
views/layout.pug

@ -10,7 +10,7 @@ html
link(rel="stylesheet", href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css")
link(rel='stylesheet', href='/css/styling.css')
link(rel="icon", type="image/png", href=("/img/logo/" + env.coin.toLowerCase() + ".png"))
link(rel="icon", type="image/png", href=("/img/logo/" + config.coin.toLowerCase() + ".png"))
block headContent
title Explorer
@ -34,12 +34,12 @@ html
a(href="/about", class="nav-link")
span About
if (env.headerDropdownLinks)
if (config.headerDropdownLinks)
li(class="nav-item dropdown")
a(class="nav-link dropdown-toggle", href="javascript:void(0)", id="navbarDropdown", role="button", data-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
span #{env.headerDropdownLinks.title}
span #{config.headerDropdownLinks.title}
div(class="dropdown-menu", aria-labelledby="navbarDropdown")
each item in env.headerDropdownLinks.links
each item in config.headerDropdownLinks.links
a(class="dropdown-item", href=item.url)
img(src=item.imgUrl, style="width: 24px; height: 24px; margin-right: 8px;")
span #{item.name}
@ -104,7 +104,7 @@ html
a(href=("https://github.com/janoside/btc-rpc-explorer/commit/" + sourcecodeVersion)) #{sourcecodeVersion}
span(style="color: #ccc;") (#{sourcecodeDate})
if (env.demoSite)
if (config.demoSite)
dt Public Demos
dd
if (coinConfig.demoSiteUrl)
@ -126,13 +126,13 @@ html
dt Support Development of #{coinConfig.siteTitle}
dd
div(class="text-md-right text-center")
each coin, index in env.donationAddresses.coins
each coin, index in config.donationAddresses.coins
div(style="display: inline-block;", class="text-center mb-3", class=(index > 0 ? "ml-md-3" : false))
img(src=donationAddressQrCodeUrls[coin], alt=env.donationAddresses[coin].address, style="border: solid 1px #ccc;")
img(src=donationAddressQrCodeUrls[coin], alt=config.donationAddresses[coin].address, style="border: solid 1px #ccc;")
br
if (env.donationAddresses[coin].urlPrefix)
if (config.donationAddresses[coin].urlPrefix)
span #{coin}:
a(href=(env.donationAddresses[coin].urlPrefix + env.donationAddresses[coin].address)) #{env.donationAddresses[coin].address.substring(0, 10)}...
a(href=(config.donationAddresses[coin].urlPrefix + config.donationAddresses[coin].address)) #{config.donationAddresses[coin].address.substring(0, 10)}...
else
span #{coin}
@ -152,19 +152,19 @@ html
hljs.initHighlightingOnLoad();
if (env.sentryUrl && env.sentryUrl.length > 0)
if (config.sentryUrl && config.sentryUrl.length > 0)
script(src="https://cdn.ravenjs.com/3.25.2/raven.min.js", crossorigin="anonymous")
script.
Raven.config("#{env.sentryUrl}").install();
Raven.config("#{config.sentryUrl}").install();
if (env.googleAnalyticsTrackingId && env.googleAnalyticsTrackingId.length > 0)
script(async, src=("https://www.googletagmanager.com/gtag/js?id=#{env.googleAnalyticsTrackingId}"))
if (config.googleAnalyticsTrackingId && config.googleAnalyticsTrackingId.length > 0)
script(async, src=("https://www.googletagmanager.com/gtag/js?id=#{config.googleAnalyticsTrackingId}"))
script.
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '#{env.googleAnalyticsTrackingId}');
gtag('config', '#{config.googleAnalyticsTrackingId}');
block endOfBody

2
views/terminal.pug

@ -6,7 +6,7 @@ block content
h1(class="h2") RPC Terminal
div(class="col")
if (!env.demoSite && (!env.rpc || !env.rpc.rpc))
if (!config.demoSite && (!config.credentials.rpc || !config.credentials.rpc.rpc))
span(style="float: right;")
a(href="/disconnect", class="btn btn-secondary") Disconnect from node

Loading…
Cancel
Save