Skip to content

Commit

Permalink
Merge branch 'janoside:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
naiba4 authored Oct 9, 2023
2 parents 3493c42 + 6a52f39 commit 0b14223
Show file tree
Hide file tree
Showing 78 changed files with 10,186 additions and 3,642 deletions.
14 changes: 12 additions & 2 deletions .env-sample
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
#BTCEXP_BASEURL=/explorer/



# Whether your site will be served via HTTPS (impacts session cookies)
# Note: if true, the express app will also have "trust proxy" set to 1, to help anyone running this tool behind a HTTPS reverse proxy
# Default: false
#BTCEXP_SECURE_SITE=false


# The active coin. Only officially supported value is "BTC".
# Default: BTC
#BTCEXP_COIN=BTC
Expand Down Expand Up @@ -199,16 +206,19 @@
#########


# Options designed for production use, on public instances like the one at BitcoinExplorer.org. These tend to be cost-reduction-oriented in nature.
# Options designed for production use, on public instances like the one at BitcoinExplorer.org.

# S3 details for uploading assets to be served via CloudFront

# This is the optional profile name that the AWS SDK will use to load credentials. By default this refers to an item in ~/.aws/credentials
#BTCEXP_S3_PROFILE_NAME=xxx
#AWS_PROFILE=xxx

# The S3 bucket where assets will be uploaded on launch
#BTCEXP_S3_BUCKET=xxx

# The region that the above S3 bucket exists
#BTCEXP_S3_BUCKET_REGION=xxx

# The path in the above S3 bucket where assets will be uploaded on launch
#BTCEXP_S3_BUCKET_PATH=xxx/

Expand Down
15 changes: 15 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports = {
"env": {
"node": true,
"commonjs": true,
"es2021": true
},
"extends": "eslint:recommended",
"overrides": [
],
"parserOptions": {
"ecmaVersion": "latest"
},
"rules": {
}
}
66 changes: 41 additions & 25 deletions CHANGELOG-API.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,51 @@
This changelog specifically tracks changes to the Public API available at `/api` and is maintained separately from the app CHANGELOG such that it can properly adhere to semantic versioning.

##### v1.2.0
###### Unreleased

* Added: /api/xyzpub/txids/:xyzpub
* Added: /api/xyzpub/addresses/:xyzpub
* Added: /api/block/header/:height
* Added: /api/block/header/:hash
* Added: /api/holidays/all
* Added: /api/holidays/today
* Added: /api/holidays/:day
* Added: /api/tx/volume/24h
* Changed: /api/tx/:txid
* Added result.vin[i].scriptSig.address
* Added result.vin[i].scriptSig.type
* Added result.fee, including result.fee.amount and result.fee.unit
* Added result.fun, when applicable, which includes special details about the tx
* Changed path: /api/util/xyzpub/:xyzpub -> /api/xyzpub/:xyzpub (auto-redirect included)
* Changed: /api/price[/...]
* Return values exclude thousands separators by default; they can be added with "?format=true"
##### v2.0.0
###### 2023-06-14

* BREAKING: All actions now return JSON content
* Added:
* `/api/blocks/tip` (replaces `/api/blocks/tip/hash` and `/api/blocks/tip/height`)
* `/api/xyzpub/txids/$XPUB`
* `/api/xyzpub/addresses/$XPUB`
* `/api/block/header/$HEIGHT`
* `/api/block/header/$HASH`
* `/api/blockchain/next-halving`
* `/api/holidays/all`
* `/api/holidays/today`
* `/api/holidays/$DAY`
* `/api/tx/volume/24h`
* `/api/price/marketcap` (replaces `/api/price/$CURRENCY/marketcap`)
* `/api/price/sats` (replaces `/api/price/$CURRENCY/sats`)
* Changed output:
* `/api/tx/$TXID`
* Added result.vin[i].scriptSig.address
* Added result.vin[i].scriptSig.type
* Added result.fee, including result.fee.amount and result.fee.unit
* Added result.fun, when applicable, which includes special details about the tx
* `/api/price[/...]`
* Return values exclude thousands separators by default; they can be added with "?format=true"
* Changed path:
* `/api/util/xyzpub/$XPUB` -> `/api/xyzpub/$XPUB` (auto-redirect included)
* Removed:
* `/api/blocks/tip/hash` (see `/api/blocks/tip`)
* `/api/blocks/tip/height` (see `/api/blocks/tip`)
* `/api/mempool/count` (see "size" field in output from `/api/mempool/summary`)
* `/api/price/$CURRENCY/marketcap` (see individual fields in output from `/api/price/marketcap`)
* `/api/price/$CURRENCY/sats` (see individual fields in output from `/api/price/sats`)



##### v1.1.0
###### 2021-12-07

* Added: /api/blockchain/utxo-set
* Added: /api/address/:address
* Added: /api/mining/next-block
* Added: /api/mining/next-block/txids
* Added: /api/mining/next-block/includes/:txid
* Added: /api/mining/miner-summary
* Added:
* `/api/blockchain/utxo-set`
* `/api/address/$ADDRESS`
* `/api/mining/next-block`
* `/api/mining/next-block/txids`
* `/api/mining/next-block/includes/$TXID`
* `/api/mining/miner-summary`



Expand Down
20 changes: 15 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
##### v3.4.0
###### Unreleased (beta)
###### 2023-06-14

* Include median fee rate for next-block estimates, on homepage and at [/next-block](./next-block)
* Minor fixes for running against Bitcoin Core v23
* URL change: /mining-template -> /next-block (redirect is included for compatibility)
* Homepage additions
* Breaking changes to the API (see [./api/changelog](/api/changelog))
* Homepage
* New "Next Halving" widget in Network Summary
* Show difficulty ATH comparison
* Show "Next Block" fullness
* Progress bar for difficulty adjustment estimate
* Include median fee rate for next-block estimates (also on [/next-block](./next-block))
* Show a banner if 'today' is a Bitcoin 'Holiday' (see more below)
* Minor fixes for running against Bitcoin Core v23
* Block Analysis: include top "days destroyed" transactions
* URL change: /mining-template -> /next-block (redirect is included for compatibility)
* On Extended PubKey pages, include balance data for various address (if Electrum server is configured)
* New [/next-halving](./next-halving) tool
* Several new API actions/changes; see [/api/changelog](./api/changelog)
* New [/holidays](./holidays), a curated list of Bitcoin 'Holidays'
* Support for different view options on [/fun](./fun)
* On [/difficulty-history](./difficulty-history), make delta graph honor timespan filtering
* Proper use of production-ready MemoryStore for session data
* Support for serving static assets via a configurable CDN
* Misc fixes for erroneous data display on non-mainnet nodes
* Switch from fontawesome to bootstrap-icons v1.8.0
* Refreshed miner-identification database
* Refreshed "Dark" theme with blues toned down (legacy dark theme still available)
* UI/UX tweaks
* Misc minor fixes
* Updated dependencies


Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ See [CHANGELOG.md](/CHANGELOG.md).

1. Install `Bitcoin Core` - [instructions](https://bitcoin.org/en/full-node). Ensure that `Bitcoin Core`'s' RPC server is enabled (`server=1`).
2. Allow `Bitcoin Core` to synchronize with the Bitcoin network (you *can* use this tool while sychronizing, but some pages may fail).
3. Install Node.js (12.9+ required, 16+ recommended).
3. Install Node.js (16+ required, 18+ recommended).

### Note about pruning and indexing configurations

Expand Down
96 changes: 79 additions & 17 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const session = require("express-session");
const csurf = require("csurf");
const MemoryStore = require('memorystore')(session);
const csrfApi = require("csurf");
const config = require("./app/config.js");
const simpleGit = require('simple-git');
const utils = require("./app/utils.js");
const moment = require("moment");
const Decimal = require('decimal.js');
const bitcoinCore = require("btc-rpc-client");
const pug = require("pug");
const momentDurationFormat = require("moment-duration-format");
const coreApi = require("./app/api/coreApi.js");
Expand All @@ -95,14 +95,15 @@ const auth = require('./app/auth.js');
const sso = require('./app/sso.js');
const markdown = require("markdown-it")();
const v8 = require("v8");
var compression = require("compression");
const compression = require("compression");
const jayson = require('jayson/promise');

const appUtils = require("@janoside/app-utils");
const s3Utils = appUtils.s3Utils;

let cdnS3Bucket = null;
if (config.cdn.active) {
cdnS3Bucket = s3Utils.createBucket(config.cdn.s3Bucket, config.cdn.s3BucketPath);
cdnS3Bucket = s3Utils.createBucket(config.cdn.s3Bucket, config.cdn.s3BucketRegion, config.cdn.s3BucketPath);
}

require("./app/currencies.js");
Expand Down Expand Up @@ -203,11 +204,31 @@ if (process.env.BTCEXP_BASIC_AUTH_PASSWORD) {
//expressApp.use(logger('dev'));
expressApp.use(bodyParser.json());
expressApp.use(bodyParser.urlencoded({ extended: false }));
expressApp.use(session({


const sessionConfig = {
secret: config.cookieSecret,
resave: false,
saveUninitialized: false
}));
saveUninitialized: true,
cookie: {
secure: config.secureSite
}
};

if (config.secureSite) {
expressApp.set('trust proxy', 1);
}

// Helpful reference for production: nginx HTTPS proxy:
// https://gist.github.com/nikmartin/5902176
debugLog(`Session config: ${JSON.stringify(utils.obfuscateProperties(sessionConfig, ["secret"]))}`);

sessionConfig.store = new MemoryStore({
checkPeriod: 86400000 // prune expired entries every 24h
});


expressApp.use(session(sessionConfig));

expressApp.use(compression());

Expand Down Expand Up @@ -729,6 +750,8 @@ expressApp.onStartup = async () => {
global.coinConfig = coins[config.coin];
global.coinConfigs = coins;

global.SATS_PER_BTC = global.coinConfig.baseCurrencyUnit.multiplier;

global.specialTransactions = {};
global.specialBlocks = {};
global.specialAddresses = {};
Expand Down Expand Up @@ -852,29 +875,67 @@ expressApp.onStartup = async () => {
}
}

expressApp.continueStartup = function() {
var rpcCred = config.credentials.rpc;
debugLog(`Connecting to RPC node at ${rpcCred.host}:${rpcCred.port}`);
function connectToRpcServer() {
// reload credentials, the main "config.credentials.rpc" can be stale
// since the username/password can be sourced from the auth cookie
// which changes each startup of bitcoind
let credentialsForRpcConnect = config.credentials.loadFreshRpcCredentials();

debugLog(`RPC Credentials: ${JSON.stringify(utils.obfuscateProperties(credentialsForRpcConnect, ["password"]), null, 4)}`);

let rpcCred = credentialsForRpcConnect;
debugLog(`Connecting to RPC node at [${rpcCred.host}]:${rpcCred.port}`);

var rpcClientProperties = {
let usernamePassword = `${rpcCred.username}:${rpcCred.password}`;
let authorizationHeader = `Basic ${btoa(usernamePassword)}`; // basic auth header format (base64 of "username:password")

let rpcClientProperties = {
host: rpcCred.host,
port: rpcCred.port,
username: rpcCred.username,
password: rpcCred.password,
timeout: rpcCred.timeout
};

global.rpcClient = new bitcoinCore(rpcClientProperties);
debugLog(`RPC Connection properties: ${JSON.stringify(utils.obfuscateProperties(rpcClientProperties, ["password"]), null, 4)}`);

// add after logging to avoid logging base64'd credentials
rpcClientProperties.headers = {
"Authorization": authorizationHeader
};

// main RPC client
global.rpcClient = jayson.Client.http(rpcClientProperties);

var rpcClientNoTimeoutProperties = {
let rpcClientNoTimeoutProperties = {
host: rpcCred.host,
port: rpcCred.port,
username: rpcCred.username,
password: rpcCred.password,
timeout: 0
timeout: 0,
headers: {
"Authorization": authorizationHeader
}
};

global.rpcClientNoTimeout = new bitcoinCore(rpcClientNoTimeoutProperties);
// no timeout RPC client, for long-running commands
global.rpcClientNoTimeout = jayson.Client.http(rpcClientNoTimeoutProperties);
}

expressApp.continueStartup = function() {
connectToRpcServer();

// if using cookie auth, watch for changes to the file and reconnect
if (config.credentials.rpc.authType == "cookie") {
debugLog(`RPC authentication is cookie based; watching for changes to the auth cookie file...`);

fs.watchFile(config.credentials.rpc.authCookieFilepath, (curr, prev) => {
debugLog(`RPC auth cookie change detected; attempting reconnect...`);

connectToRpcServer();
});
}


// default values - after we connect via RPC, we update these
global.txindexAvailable = false;
Expand All @@ -889,7 +950,7 @@ expressApp.continueStartup = function() {


if (config.addressApi) {
var supportedAddressApis = addressApi.getSupportedAddressApis();
let supportedAddressApis = addressApi.getSupportedAddressApis();
if (!supportedAddressApis.includes(config.addressApi)) {
utils.logError("32907ghsd0ge", `Unrecognized value for BTCEXP_ADDRESS_API: '${config.addressApi}'. Valid options are: ${supportedAddressApis}`);
}
Expand Down Expand Up @@ -1033,7 +1094,8 @@ expressApp.use(function(req, res, next) {
next();
});

expressApp.use(csurf(), (req, res, next) => {
const csrfProtection = csrfApi();
expressApp.use(csrfProtection, (req, res, next) => {
res.locals.csrfToken = req.csrfToken();

next();
Expand Down
4 changes: 0 additions & 4 deletions app/actionPerformanceMonitor.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
const fs = require('fs');
const path = require('path');
const onHeaders = require('on-headers');
const os = require('os');
const v8 = require('v8');
const debug = require("debug");
const debugLog = debug("monitor");
const utils = require("./utils.js");
Expand Down
2 changes: 0 additions & 2 deletions app/api/addressApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ const config = require("./../config.js");
const coins = require("../coins.js");
const utils = require("../utils.js");

const coinConfig = coins[config.coin];

const electrumAddressApi = require("./electrumAddressApi.js");
const blockchainAddressApi = require("./blockchainAddressApi.js");
const blockchairAddressApi = require("./blockchairAddressApi.js");
Expand Down
Loading

0 comments on commit 0b14223

Please sign in to comment.