diff --git a/backend/mempool-config.sample.json b/backend/mempool-config.sample.json
index c444929b5..1582929aa 100644
--- a/backend/mempool-config.sample.json
+++ b/backend/mempool-config.sample.json
@@ -39,6 +39,13 @@
"USERNAME": "mempool",
"PASSWORD": "mempool"
},
+ "SYSLOG": {
+ "ENABLED": true,
+ "HOST": "127.0.0.1",
+ "PORT": 514,
+ "MIN_PRIORITY": "info",
+ "FACILITY": "local7"
+ },
"STATISTICS": {
"ENABLED": true,
"TX_PER_SECOND_SAMPLE_PERIOD": 150
diff --git a/backend/package.json b/backend/package.json
index b1dae4dca..c955793e1 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -1,6 +1,6 @@
{
"name": "mempool-backend",
- "version": "2.0.0",
+ "version": "2.2.0-dev",
"description": "Bitcoin mempool visualizer and blockchain explorer backend",
"license": "GNU Affero General Public License v3.0",
"homepage": "https://mempool.space",
diff --git a/backend/src/api/backend-info.ts b/backend/src/api/backend-info.ts
index eb3f1f664..7c6456522 100644
--- a/backend/src/api/backend-info.ts
+++ b/backend/src/api/backend-info.ts
@@ -1,20 +1,24 @@
import * as fs from 'fs';
import * as os from 'os';
import logger from '../logger';
+import { IBackendInfo } from '../mempool.interfaces';
class BackendInfo {
- gitCommitHash = '';
- hostname = '';
+ private gitCommitHash = '';
+ private hostname = '';
+ private version = '';
constructor() {
this.setLatestCommitHash();
+ this.setVersion();
this.hostname = os.hostname();
}
- public getBackendInfo() {
+ public getBackendInfo(): IBackendInfo {
return {
- 'hostname': this.hostname,
- 'git-commit': this.gitCommitHash,
+ hostname: this.hostname,
+ gitCommit: this.gitCommitHash,
+ version: this.version,
};
}
@@ -29,6 +33,15 @@ class BackendInfo {
logger.err('Could not load git commit info: ' + e.message || e);
}
}
+
+ private setVersion(): void {
+ try {
+ const packageJson = fs.readFileSync('package.json').toString();
+ this.version = JSON.parse(packageJson).version;
+ } catch (e) {
+ throw new Error(e);
+ }
+ }
}
export default new BackendInfo();
diff --git a/backend/src/api/mempool.ts b/backend/src/api/mempool.ts
index 4f8638c3e..81330a3ce 100644
--- a/backend/src/api/mempool.ts
+++ b/backend/src/api/mempool.ts
@@ -169,7 +169,7 @@ class Mempool {
if (!this.inSync && transactions.length === Object.keys(this.mempoolCache).length) {
this.inSync = true;
- logger.info('The mempool is now in sync!');
+ logger.notice('The mempool is now in sync!');
loadingIndicators.setProgress('mempool', 100);
}
diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts
index fab55119b..74a06a588 100644
--- a/backend/src/api/websocket-handler.ts
+++ b/backend/src/api/websocket-handler.ts
@@ -167,8 +167,7 @@ class WebsocketHandler {
'conversions': fiatConversion.getConversionRates(),
'mempool-blocks': mempoolBlocks.getMempoolBlocks(),
'transactions': memPool.getLatestTransactions(),
- 'git-commit': backendInfo.gitCommitHash,
- 'hostname': backendInfo.hostname,
+ 'backendInfo': backendInfo.getBackendInfo(),
'loadingIndicators': loadingIndicators.getLoadingIndicators(),
...this.extraInitProperties
};
diff --git a/backend/src/config.ts b/backend/src/config.ts
index ace63394c..d5828f922 100644
--- a/backend/src/config.ts
+++ b/backend/src/config.ts
@@ -41,6 +41,13 @@ interface IConfig {
USERNAME: string;
PASSWORD: string;
};
+ SYSLOG: {
+ ENABLED: boolean;
+ HOST: string;
+ PORT: number;
+ MIN_PRIORITY: 'emerg' | 'alert' | 'crit' | 'err' |'warn' | 'notice' | 'info' | 'debug';
+ FACILITY: string;
+ };
STATISTICS: {
ENABLED: boolean;
TX_PER_SECOND_SAMPLE_PERIOD: number;
@@ -96,6 +103,13 @@ const defaults: IConfig = {
'USERNAME': 'mempool',
'PASSWORD': 'mempool'
},
+ 'SYSLOG': {
+ 'ENABLED': true,
+ 'HOST': '127.0.0.1',
+ 'PORT': 514,
+ 'MIN_PRIORITY': 'info',
+ 'FACILITY': 'local7'
+ },
'STATISTICS': {
'ENABLED': true,
'TX_PER_SECOND_SAMPLE_PERIOD': 150
@@ -117,6 +131,7 @@ class Config implements IConfig {
CORE_RPC: IConfig['CORE_RPC'];
CORE_RPC_MINFEE: IConfig['CORE_RPC_MINFEE'];
DATABASE: IConfig['DATABASE'];
+ SYSLOG: IConfig['SYSLOG'];
STATISTICS: IConfig['STATISTICS'];
BISQ_BLOCKS: IConfig['BISQ_BLOCKS'];
BISQ_MARKETS: IConfig['BISQ_MARKETS'];
@@ -129,6 +144,7 @@ class Config implements IConfig {
this.CORE_RPC = configs.CORE_RPC;
this.CORE_RPC_MINFEE = configs.CORE_RPC_MINFEE;
this.DATABASE = configs.DATABASE;
+ this.SYSLOG = configs.SYSLOG;
this.STATISTICS = configs.STATISTICS;
this.BISQ_BLOCKS = configs.BISQ_BLOCKS;
this.BISQ_MARKETS = configs.BISQ_MARKETS;
diff --git a/backend/src/index.ts b/backend/src/index.ts
index f99cc4132..54cf383d3 100644
--- a/backend/src/index.ts
+++ b/backend/src/index.ts
@@ -81,7 +81,7 @@ class Server {
await checkDbConnection();
}
- if (config.STATISTICS.ENABLED && config.DATABASE.ENABLED) {
+ if (config.STATISTICS.ENABLED && config.DATABASE.ENABLED && cluster.isMaster) {
statistics.startStatistics();
}
diff --git a/backend/src/logger.ts b/backend/src/logger.ts
index 41aaf5c8f..f14af0104 100644
--- a/backend/src/logger.ts
+++ b/backend/src/logger.ts
@@ -50,17 +50,11 @@ class Logger {
public debug: ((msg: string) => void);
private name = 'mempool';
- private fac: any;
- private loghost: string;
- private logport: number;
private client: dgram.Socket;
private network: string;
- constructor(fac) {
+ constructor() {
let prio;
- this.fac = fac != null ? fac : Logger.facilities.local0;
- this.loghost = '127.0.0.1';
- this.logport = 514;
for (prio in Logger.priorities) {
if (true) {
this.addprio(prio);
@@ -97,10 +91,12 @@ class Logger {
}
const network = this.network ? ' <' + this.network + '>' : '';
prionum = Logger.priorities[priority] || Logger.priorities.info;
- syslogmsg = `<${(this.fac * 8 + prionum)}> ${this.name}[${process.pid}]: ${priority.toUpperCase()}${network} ${msg}`;
consolemsg = `${this.ts()} [${process.pid}] ${priority.toUpperCase()}:${network} ${msg}`;
- this.syslog(syslogmsg);
+ if (config.SYSLOG.ENABLED && Logger.priorities[priority] <= Logger.priorities[config.SYSLOG.MIN_PRIORITY]) {
+ syslogmsg = `<${(Logger.facilities[config.SYSLOG.FACILITY] * 8 + prionum)}> ${this.name}[${process.pid}]: ${priority.toUpperCase()}${network} ${msg}`;
+ this.syslog(syslogmsg);
+ }
if (priority === 'warning') {
priority = 'warn';
}
@@ -116,7 +112,7 @@ class Logger {
private syslog(msg) {
let msgbuf;
msgbuf = Buffer.from(msg);
- this.client.send(msgbuf, 0, msgbuf.length, this.logport, this.loghost, function(err, bytes) {
+ this.client.send(msgbuf, 0, msgbuf.length, config.SYSLOG.PORT, config.SYSLOG.HOST, function(err, bytes) {
if (err) {
console.log(err);
}
@@ -146,4 +142,4 @@ class Logger {
}
}
-export default new Logger(Logger.facilities.local7);
+export default new Logger();
diff --git a/backend/src/mempool.interfaces.ts b/backend/src/mempool.interfaces.ts
index d2a6d2818..fae78ef9b 100644
--- a/backend/src/mempool.interfaces.ts
+++ b/backend/src/mempool.interfaces.ts
@@ -161,3 +161,9 @@ interface RequiredParams {
export interface ILoadingIndicators { [name: string]: number; }
export interface IConversionRates { [currency: string]: number; }
+
+export interface IBackendInfo {
+ hostname: string;
+ gitCommit: string;
+ version: string;
+}
diff --git a/frontend/generate-config.js b/frontend/generate-config.js
index 5b26fb41b..6540ccf56 100644
--- a/frontend/generate-config.js
+++ b/frontend/generate-config.js
@@ -5,6 +5,8 @@ const GENERATED_CONFIG_FILE_NAME = 'generated-config.js';
let settings = [];
let configContent = {};
+let gitCommitHash = '';
+let packetJsonVersion = '';
try {
const rawConfig = fs.readFileSync(CONFIG_FILE_NAME);
@@ -15,6 +17,13 @@ try {
}
}
+try {
+ const packageJson = fs.readFileSync('package.json');
+ packetJsonVersion = JSON.parse(packageJson).version;
+} catch (e) {
+ throw new Error(e);
+}
+
for (setting in configContent) {
settings.push({
key: setting,
@@ -22,9 +31,17 @@ for (setting in configContent) {
});
}
+try {
+ gitCommitHash = fs.readFileSync('../.git/refs/heads/master').toString().trim();
+} catch (e) {
+ console.log('Could not load git commit info: ' + e.message || e);
+}
+
const code = `(function (window) {
window.__env = window.__env || {};${settings.reduce((str, obj) => `${str}
window.__env.${obj.key} = ${ typeof obj.value === 'string' ? `'${obj.value}'` : obj.value };`, '')}
+ window.__env.GIT_COMMIT_HASH = '${gitCommitHash}';
+ window.__env.PACKAGE_JSON_VERSION = '${packetJsonVersion}';
}(global || this));`;
try {
diff --git a/frontend/package.json b/frontend/package.json
index 8e0be0b94..1b39c6435 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "mempool-frontend",
- "version": "2.0.0",
+ "version": "2.2.0-dev",
"description": "Bitcoin mempool visualizer and blockchain explorer backend",
"license": "GNU Affero General Public License v3.0",
"homepage": "https://mempool.space",
@@ -25,12 +25,14 @@
"i18n-extract-from-source": "./node_modules/@angular/cli/bin/ng xi18n --ivy --out-file ./src/locale/messages.xlf",
"i18n-pull-from-transifex": "tx pull -a --parallel --minimum-perc 1 --force",
"serve": "ng serve --proxy-config proxy.conf.json",
+ "serve:stg": "ng serve --host 0.0.0.0 --disable-host-check --proxy-config proxy.stg.conf.json --verbose",
"start": "npm run generate-config && npm run sync-assets-dev && ng serve --proxy-config proxy.conf.json",
- "build": "npm run generate-config && ng build --prod --localize && npm run sync-assets && npm run build-mempool-js",
+ "start:stg": "npm run generate-config && npm run sync-assets-dev && ng serve --host 0.0.0.0 --disable-host-check --proxy-config proxy.stg.conf.json",
+ "build": "npm run generate-config && ng build --prod --localize && npm run sync-assets && npm run build-mempool.js",
"sync-assets": "node sync-assets.js && rsync -av ./dist/mempool/browser/en-US/resources ./dist/mempool/browser/resources",
"sync-assets-dev": "node sync-assets.js dev",
"generate-config": "node generate-config.js",
- "build-mempool-js": "tsc | browserify -p tinyify ./node_modules/@mempool/mempool-js/lib/index.js --standalone mempoolJS > ./dist/mempool/browser/en-US/mempool.js",
+ "build-mempool.js": "tsc | browserify -p tinyify ./node_modules/@mempool/mempool.js/lib/index.js --standalone mempoolJS > ./dist/mempool/browser/en-US/mempool.js",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
@@ -55,7 +57,7 @@
"@fortawesome/fontawesome-svg-core": "^1.2.35",
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@mempool/chartist": "^0.11.4",
- "@mempool/mempool-js": "^2.2.1",
+ "@mempool/mempool.js": "^2.2.0",
"@ng-bootstrap/ng-bootstrap": "^7.0.0",
"@nguniversal/express-engine": "11.2.1",
"@types/qrcode": "^1.3.4",
diff --git a/frontend/proxy.conf.json b/frontend/proxy.conf.json
index bc184bc05..3f989d565 100644
--- a/frontend/proxy.conf.json
+++ b/frontend/proxy.conf.json
@@ -1,8 +1,4 @@
{
- "/api/v1/donations": {
- "target": "http://localhost:9000/",
- "secure": false
- },
"/api/v1": {
"target": "http://localhost:8999/",
"secure": false
diff --git a/frontend/proxy.stg.conf.json b/frontend/proxy.stg.conf.json
new file mode 100644
index 000000000..18b26b602
--- /dev/null
+++ b/frontend/proxy.stg.conf.json
@@ -0,0 +1,68 @@
+{
+ "/api/v1/ws": {
+ "target": "https://mempool.ninja",
+ "secure": false,
+ "ws": true
+ },
+ "/api/*": {
+ "target": "https://mempool.ninja",
+ "secure": false,
+ "changeOrigin": true,
+ "logLevel": "debug",
+ "pathRewrite": {
+ "^/api": "https://mempool.ninja/api"
+ },
+ "timeout": 3600000
+ },
+ "/testnet/api/v1/ws": {
+ "target": "https://mempool.ninja/testnet",
+ "secure": false,
+ "ws": true,
+ "pathRewrite": {
+ "^/testnet/api": "/api/v1/ws"
+ }
+ },
+ "/testnet/api/v1/*": {
+ "target": "https://mempool.ninja/testnet",
+ "secure": false,
+ "changeOrigin": true,
+ "pathRewrite": {
+ "^/testnet/api/v1": "/api/v1"
+ },
+ "timeout": 3600000
+ },
+ "/bisq/api/v1/ws": {
+ "target": "https://mempool.ninja/bisq",
+ "secure": false,
+ "ws": true,
+ "pathRewrite": {
+ "^/bisq/api": "/api/v1/ws"
+ }
+ },
+ "/bisq/api/*": {
+ "target": "https://mempool.ninja/bisq",
+ "secure": false,
+ "changeOrigin": true,
+ "pathRewrite": {
+ "^/bisq/api/": "/api/v1/bisq/"
+ },
+ "timeout": 3600000
+ },
+ "/liquid/api/v1/ws": {
+ "target": "https://mempool.ninja/liquid",
+ "secure": false,
+ "ws": true,
+ "pathRewrite": {
+ "^/liquid/api": "/api/v1/ws"
+ }
+ },
+ "/liquid/api/*": {
+ "target": "https://mempool.ninja/liquid",
+ "secure": false,
+ "changeOrigin": true,
+ "pathRewrite": {
+ "^/liquid/api/": "/api/v1/liquid/"
+ },
+ "timeout": 3600000
+ }
+}
diff --git a/frontend/src/app/components/about/about.component.html b/frontend/src/app/components/about/about.component.html
index 3a98c904b..3466c275e 100644
--- a/frontend/src/app/components/about/about.component.html
+++ b/frontend/src/app/components/about/about.component.html
@@ -5,7 +5,7 @@
Height | Timestamp | diff --git a/frontend/src/app/components/master-page/master-page.component.html b/frontend/src/app/components/master-page/master-page.component.html index 89a92b44a..42de6b17a 100644 --- a/frontend/src/app/components/master-page/master-page.component.html +++ b/frontend/src/app/components/master-page/master-page.component.html @@ -26,7 +26,7 @@ diff --git a/frontend/src/app/components/master-page/master-page.component.scss b/frontend/src/app/components/master-page/master-page.component.scss index 3c0e31490..cac4681d7 100644 --- a/frontend/src/app/components/master-page/master-page.component.scss +++ b/frontend/src/app/components/master-page/master-page.component.scss @@ -8,14 +8,16 @@ fa-icon { .navbar { z-index: 100; + min-height: 64px; } li.nav-item { + margin: auto 10px; padding-left: 10px; padding-right: 10px; } -@media (min-width: 768px) { +@media (min-width: 992px) { .navbar { padding: 0rem 2rem; } @@ -26,17 +28,50 @@ li.nav-item { margin-right: 16px; } li.nav-item { + margin: auto 0px; padding: 10px; } } -li.nav-item a { - color: #ffffff; +.navbar-nav { + background: #212121; + bottom: 0; + box-shadow: 0px 0px 15px 0px #000; + flex-direction: row; + left: 0; + justify-content: center; + position: fixed; + width: 100%; } -.navbar-nav { - flex-direction: row; - justify-content: center; +@media (min-width: 992px) { + .navbar-nav { + background: transparent; + box-shadow: none; + position: relative; + width: auto; + } +} + +.navbar-collapse { + flex-basis: auto; + justify-content: flex-end; +} + +@media (min-width: 992px) { + .navbar-collapse { + justify-content: space-between; + } +} + +.navbar-brand { + width: 60%; +} + +@media (min-width: 576px) { + .navbar-brand { + width: 140px; + } } nav { @@ -81,5 +116,16 @@ nav { .dropdown-item { display: flex; - align-items:center; + align-items: center; } + +@media (min-width: 992px) { + .search-form-container { + width: 100%; + max-width: 500px; + padding-left: 15px; + } +} +.navbar-dark .navbar-nav .nav-link { + color: #f1f1f1; +} \ No newline at end of file diff --git a/frontend/src/app/components/search-form/search-form.component.scss b/frontend/src/app/components/search-form/search-form.component.scss index d80a0bb16..b6aa14d04 100644 --- a/frontend/src/app/components/search-form/search-form.component.scss +++ b/frontend/src/app/components/search-form/search-form.component.scss @@ -5,12 +5,53 @@ text-overflow: ellipsis; } +form { + margin-top: 5px; +} + +@media (min-width: 576px) { + form { + margin-top: 0px; + margin-left: 8px; + } +} + +@media (min-width: 992px) { + form { + width: 100%; + } +} + +.btn-block { + width: 58.55px; +} + .search-box-container { width: 100%; } -@media (min-width: 992px) { +.search-box-container input { + border: 0px; +} + +.search-box-container .btn { + width: 100px; +} + +@media (min-width: 768px) { .search-box-container { - width: 350px; + min-width: 400px; + } +} + +@media (min-width: 992px) { + .search-box-container { + min-width: 260px; + } +} + +@media (min-width: 1200px) { + .search-box-container { + min-width: 300px; } } diff --git a/frontend/src/app/components/statistics/statistics.component.html b/frontend/src/app/components/statistics/statistics.component.html index e876f41fa..e0b1ec90a 100644 --- a/frontend/src/app/components/statistics/statistics.component.html +++ b/frontend/src/app/components/statistics/statistics.component.html @@ -15,7 +15,7 @@
---|