diff --git a/.env-sample b/.env-sample new file mode 100644 index 0000000..87051aa --- /dev/null +++ b/.env-sample @@ -0,0 +1,39 @@ +# The active coin: BTC/LTC +#BTCEXP_COIN = BTC + +# Bitcoin RPC Credentials (URI -OR- HOST/PORT/USER/PASS) +#BTCEXP_BITCOIND_URI = bitcoin://rpcusername:rpcpassword@127.0.0.1:8332 +#BTCEXP_BITCOIND_HOST = localhost +#BTCEXP_BITCOIND_PORT = 8332 +#BTCEXP_BITCOIND_USER = rpcusername +#BTCEXP_BITCOIND_PASS = rpcpassword + +# Optional: InfluxDB Credentials (URI -OR- HOST/PORT/DBNAME/USER/PASS) +#BTCEXP_ENABLE_INFLUXDB = true +#BTCEXP_INFLUXDB_URI = influx://username:password@127.0.0.1:8086 +#BTCEXP_INFLUXDB_HOST = 127.0.0.1 +#BTCEXP_INFLUXDB_PORT = 8086 +#BTCEXP_INFLUXDB_DBNAME = influxdb +#BTCEXP_INFLUXDB_USER = dbuser +#BTCEXP_INFLUXDB_PASS = dbpassword + +#BTCEXP_COOKIE_SECRET = 0000aaaafffffgggggg + +# Whether public-demo aspects of the site are active +#BTCEXP_DEMO = true + +# Don't request currency exchange rates +#BTCEXP_NO_RATES = true + +# Password protection for site via basic auth (enter any username, only the password is checked) +#BTCEXP_BASIC_AUTH_PASSWORD = mypassword + +# Enable to allow access to all RPC methods +#BTCEXP_RPC_ALLOWALL = true + +# Custom RPC method blacklist +#BTCEXP_RPC_BLACKLIST = signrawtransaction,sendtoaddress,stop,... + +#BTCEXP_IPSTACK_KEY = 0000aaaafffffgggggg +#BTCEXP_GANALYTICS_TRACKING = UA-XXXX-X +#BTCEXP_SENTRY_URL = https://00000fffffff@sentry.io/XXXX \ No newline at end of file diff --git a/README.md b/README.md index d9a992f..44856f0 100644 --- a/README.md +++ b/README.md @@ -38,26 +38,13 @@ The below instructions are geared toward BTC, but can be adapted easily to other 1. Clone this repo: `git clone https://github.com/janoside/btc-rpc-explorer` 2. `npm install` 3. `npm run build` -4. Set environment variables with your bitcoind rpc credentials and other settings. See [configuration](#configuration). +4. Configure via environment variables or `.env` file. See [configuration](#configuration). 5. `npm start` 6. Open [http://127.0.0.1:3002/](http://127.0.0.1:3002/) ### Configuration -Configuration options may be passed as environment variables. -You can also set them in a `.env` file in the root directory, in the following format: - -``` -BTCEXP_BITCOIND_HOST = localhost -BTCEXP_BITCOIND_PORT = 8332 -BTCEXP_BITCOIND_USER = username -BTCEXP_BITCOIND_PASS = password -BTCEXP_IPSTACK_KEY = 0000aaaafffffgggggg -BTCEXP_COOKIE_SECRET = 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f -``` - -You may enable password protection by setting `BTCEXP_LOGIN=`. -Authenticating is done with http basic auth, using the selected password and an empty (or any) username. +Configuration options may be passed as environment variables or by creating a `.env` file in the root directory. See [.env-sample](.env-sample) for a list of the options and details for formatting `.env`. ## Run via Docker diff --git a/app.js b/app.js index 56192aa..9a0de50 100755 --- a/app.js +++ b/app.js @@ -49,9 +49,9 @@ app.engine('pug', (path, options, fn) => { app.set('view engine', 'pug'); // basic http authentication -if (process.env.BTCEXP_LOGIN) { +if (process.env.BTCEXP_BASIC_AUTH_PASSWORD) { app.disable('x-powered-by'); - app.use(auth(process.env.BTCEXP_LOGIN)); + app.use(auth(process.env.BTCEXP_BASIC_AUTH_PASSWORD)); } // uncomment after placing your favicon in /public diff --git a/app/config.js b/app/config.js index 101bb08..cd062fe 100644 --- a/app/config.js +++ b/app/config.js @@ -6,14 +6,24 @@ var currentCoin = process.env.BTCEXP_COIN || "BTC"; var credentials = require("./defaultCredentials.js"); try { - Object.assign(credentials, require("./credentials.js")) -} catch (err) {} + var overrideCredentials = null; + Object.assign(overrideCredentials, require("./credentials.js")); + + for (var key in overrideCredentials) { + credentials[key] = overrideCredentials[key]; + } +} catch (err) { + console.log(`Error loading override credentials from app/credentials.js: ${err}`); +} var rpcCred = credentials.rpc; if (rpcCred.cookie && !rpcCred.username && !rpcCred.password && fs.existsSync(rpcCred.cookie)) { - [ rpcCred.username, rpcCred.password ] = fs.readFileSync(rpcCred.cookie).toString().split(':', 2); - if (!rpcCred.password) throw new Error('Cookie file '+rpcCred.cookie+' in unexpected format'); + [ rpcCred.username, rpcCred.password ] = fs.readFileSync(rpcCred.cookie).toString().split(':', 2); + + if (!rpcCred.password) { + throw new Error(`Cookie file ${rpcCred.cookie} in unexpected format`); + } } var cookieSecret = process.env.BTCEXP_COOKIE_SECRET diff --git a/app/utils.js b/app/utils.js index 68924fb..44a4a70 100644 --- a/app/utils.js +++ b/app/utils.js @@ -276,7 +276,9 @@ function getBlockTotalFeesFromCoinbaseTxAndBlockHeight(coinbaseTx, blockHeight) } function refreshExchangeRates() { - if (process.env.BTCEXP_NO_RATES) return; + if (process.env.BTCEXP_NO_RATES) { + return; + } if (coins[config.coin].exchangeRateData) { request(coins[config.coin].exchangeRateData.jsonUrl, function(error, response, body) { diff --git a/package-lock.json b/package-lock.json index 414bff8..7edb36e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -103,6 +103,11 @@ "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", "dev": true }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -120,6 +125,11 @@ "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", "dev": true }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -347,6 +357,23 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + } + } + }, "can-promise": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/can-promise/-/can-promise-0.0.1.tgz", @@ -543,6 +570,62 @@ "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz", "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=" }, + "csrf": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.0.6.tgz", + "integrity": "sha1-thEg3c7q/JHnbtUxO7XAsmZ7cQo=", + "requires": { + "rndm": "1.2.0", + "tsscmp": "1.0.5", + "uid-safe": "2.1.4" + }, + "dependencies": { + "uid-safe": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz", + "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", + "requires": { + "random-bytes": "~1.0.0" + } + } + } + }, + "csurf": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.9.0.tgz", + "integrity": "sha1-SdLGkl/87Ht95VlZfBU/pTM2QTM=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "csrf": "~3.0.3", + "http-errors": "~1.5.0" + }, + "dependencies": { + "http-errors": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", + "integrity": "sha1-eIwNLB3iyBuebowBhDtrl+uSB1A=", + "requires": { + "inherits": "2.0.3", + "setprototypeof": "1.0.2", + "statuses": ">= 1.3.1 < 2" + } + }, + "setprototypeof": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz", + "integrity": "sha1-gaVSFB7BBLiOic44MQOtXGZWTQg=" + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "requires": { + "array-find-index": "^1.0.1" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -573,6 +656,22 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + } + } + }, "decimal.js": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-7.2.3.tgz", @@ -612,6 +711,11 @@ "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=" }, + "dotenv": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", + "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==" + }, "dtrace-provider": { "version": "0.8.7", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.7.tgz", @@ -995,6 +1099,11 @@ "dev": true, "optional": true }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1079,6 +1188,11 @@ "number-is-nan": "^1.0.0" } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -1147,8 +1261,7 @@ "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "json-schema": { "version": "0.2.3", @@ -1274,6 +1387,15 @@ "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, "lru-cache": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", @@ -1283,6 +1405,11 @@ "yallist": "^2.1.2" } }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=" + }, "markdown-it": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", @@ -1328,6 +1455,89 @@ "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", "dev": true }, + "meow": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -1380,6 +1590,15 @@ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "optional": true }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + } + }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", @@ -1923,6 +2142,11 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=" + }, "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -1971,6 +2195,15 @@ "read-pkg": "^2.0.0" } }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + } + }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", @@ -2052,6 +2285,11 @@ "inherits": "^2.0.1" } }, + "rndm": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", + "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -2324,6 +2562,11 @@ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=" + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -2359,6 +2602,16 @@ } } }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=" + }, + "tsscmp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz", + "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc=" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", diff --git a/routes/baseActionsRouter.js b/routes/baseActionsRouter.js index 96da05c..f2f78e4 100644 --- a/routes/baseActionsRouter.js +++ b/routes/baseActionsRouter.js @@ -869,7 +869,9 @@ router.get("/rpc-browser", function(req, res, next) { } forceCsrf(req, res, err => { - if (err) return next(err); + if (err) { + return next(err); + } console.log("Executing RPC '" + req.query.method + "' with params: [" + argValues + "]"); diff --git a/views/index.pug b/views/index.pug index 2c723d5..0b9bb7e 100644 --- a/views/index.pug +++ b/views/index.pug @@ -87,19 +87,20 @@ block content div(class="col-md-4") ul(style="list-style-type: none;", class="pl-0") - li - div(class="float-left", style="height: 40px; width: 40px; font-size: 12px;") - span - i(class="fas fa-money-bill-wave-alt fa-2x mr-2", style="margin-top: 7px;") + if (!process.env.BTCEXP_NO_RATES) + li + div(class="float-left", style="height: 40px; width: 40px; font-size: 12px;") + span + i(class="fas fa-money-bill-wave-alt fa-2x mr-2", style="margin-top: 7px;") - span(class="font-weight-bold") Exchange Rate - span(data-toggle="tooltip", title=("Exchange-rate data from: " + coinConfig.exchangeRateData.jsonUrl)) - i(class="fas fa-info-circle") + span(class="font-weight-bold") Exchange Rate + span(data-toggle="tooltip", title=("Exchange-rate data from: " + coinConfig.exchangeRateData.jsonUrl)) + i(class="fas fa-info-circle") - if (global.exchangeRates) - p(class="lead") #{utils.formatExchangedCurrency(1.0, "usd")} - else - p(class="lead") - + if (global.exchangeRates) + p(class="lead") #{utils.formatExchangedCurrency(1.0, "usd")} + else + p(class="lead") - li div(class="float-left", style="height: 40px; width: 40px;") diff --git a/views/layout.pug b/views/layout.pug index 39e54b2..abe7702 100644 --- a/views/layout.pug +++ b/views/layout.pug @@ -70,11 +70,12 @@ html(lang="en") if (coinConfig.currencyUnits) span(class="dropdown-header") Currency Units each item in coinConfig.currencyUnits - a(class="dropdown-item", href=("/changeSetting?name=currencyFormatType&value=" + item.values[0])) - each valueName in item.values - if (currencyFormatType == valueName) - i(class="fas fa-check") - span #{item.name} + if (item.type == "native" || !process.env.BTCEXP_NO_RATES) + a(class="dropdown-item", href=("/changeSetting?name=currencyFormatType&value=" + item.values[0])) + each valueName in item.values + if (currencyFormatType == valueName) + i(class="fas fa-check") + span #{item.name} span(class="dropdown-header") Theme a(class="dropdown-item", href="/changeSetting?name=uiTheme&value=light")