Merge branch 'master' into simon/bisq-dashboard
# Conflicts: # frontend/package-lock.json # frontend/src/app/components/master-page/master-page.component.html
This commit is contained in:
		
						commit
						5d242aa39f
					
				@ -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
 | 
			
		||||
 | 
			
		||||
@ -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",
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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}`;
 | 
			
		||||
 | 
			
		||||
    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();
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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 {
 | 
			
		||||
 | 
			
		||||
@ -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",
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,4 @@
 | 
			
		||||
{
 | 
			
		||||
  "/api/v1/donations": {
 | 
			
		||||
    "target": "http://localhost:9000/",
 | 
			
		||||
    "secure": false
 | 
			
		||||
  },
 | 
			
		||||
  "/api/v1": {
 | 
			
		||||
    "target": "http://localhost:8999/",
 | 
			
		||||
    "secure": false
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										68
									
								
								frontend/proxy.stg.conf.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								frontend/proxy.stg.conf.json
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -5,7 +5,7 @@
 | 
			
		||||
    <br>
 | 
			
		||||
 | 
			
		||||
    <div class="text-small text-center offset-md-1">
 | 
			
		||||
      v2.2-dev ({{ gitCommit$ | async }})
 | 
			
		||||
      v{{ packetJsonVersion }} [{{ frontendGitCommitHash }}]
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <br>
 | 
			
		||||
@ -48,7 +48,7 @@
 | 
			
		||||
 | 
			
		||||
    <a href="https://squarecrypto.org/" target="_blank">
 | 
			
		||||
      <div class="profile_photo enterprise_sponsor d-inline-block" title="Square Crypto">
 | 
			
		||||
        <img class="profile_img" src="/resources/profile/sqcrypto.png" />
 | 
			
		||||
        <img class="profile_img" src="/resources/profile/sqcrypto.svg" />
 | 
			
		||||
        Square
 | 
			
		||||
      </div>
 | 
			
		||||
    </a>
 | 
			
		||||
@ -60,6 +60,13 @@
 | 
			
		||||
      </div>
 | 
			
		||||
    </a>
 | 
			
		||||
 | 
			
		||||
    <a href="https://exodus.com/" target="_blank">
 | 
			
		||||
      <div class="profile_photo enterprise_sponsor d-inline-block" title="Exodus">
 | 
			
		||||
        <img class="profile_img" src="/resources/profile/exodus.svg" />
 | 
			
		||||
        Exodus
 | 
			
		||||
      </div>
 | 
			
		||||
    </a>
 | 
			
		||||
 | 
			
		||||
    <br><br>
 | 
			
		||||
    <br><br>
 | 
			
		||||
 | 
			
		||||
@ -392,4 +399,10 @@
 | 
			
		||||
    <a [routerLink]="['/terms-of-service']" i18n="shared.terms-of-service|Terms of Service">Terms of Service</a>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <br>
 | 
			
		||||
 | 
			
		||||
  <div class="text-small text-center" *ngIf="officialMempoolSpace">
 | 
			
		||||
    {{ (backendInfo$ | async)?.hostname }} (v{{ (backendInfo$ | async )?.version }}) [{{ (backendInfo$ | async )?.gitCommit | slice:0:8 }}]
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,8 @@ import { Observable, Subscription } from 'rxjs';
 | 
			
		||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 | 
			
		||||
import { ApiService } from 'src/app/services/api.service';
 | 
			
		||||
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
 | 
			
		||||
import { delay, map, retryWhen, switchMap, tap } from 'rxjs/operators';
 | 
			
		||||
import { delay, retryWhen, switchMap, tap } from 'rxjs/operators';
 | 
			
		||||
import { IBackendInfo } from 'src/app/interfaces/websocket.interface';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-about',
 | 
			
		||||
@ -14,7 +15,7 @@ import { delay, map, retryWhen, switchMap, tap } from 'rxjs/operators';
 | 
			
		||||
  styleUrls: ['./about.component.scss'],
 | 
			
		||||
})
 | 
			
		||||
export class AboutComponent implements OnInit, OnDestroy {
 | 
			
		||||
  gitCommit$: Observable<string>;
 | 
			
		||||
  backendInfo$: Observable<IBackendInfo>;
 | 
			
		||||
  donationForm: FormGroup;
 | 
			
		||||
  paymentForm: FormGroup;
 | 
			
		||||
  donationStatus = 1;
 | 
			
		||||
@ -22,6 +23,9 @@ export class AboutComponent implements OnInit, OnDestroy {
 | 
			
		||||
  contributors$: Observable<any>;
 | 
			
		||||
  donationObj: any;
 | 
			
		||||
  sponsorsEnabled = this.stateService.env.OFFICIAL_MEMPOOL_SPACE;
 | 
			
		||||
  frontendGitCommitHash = this.stateService.env.GIT_COMMIT_HASH.substr(0, 8);
 | 
			
		||||
  packetJsonVersion = this.stateService.env.PACKAGE_JSON_VERSION;
 | 
			
		||||
  officialMempoolSpace = this.stateService.env.OFFICIAL_MEMPOOL_SPACE;
 | 
			
		||||
  sponsors = null;
 | 
			
		||||
  contributors = null;
 | 
			
		||||
  requestSubscription: Subscription | undefined;
 | 
			
		||||
@ -36,7 +40,7 @@ export class AboutComponent implements OnInit, OnDestroy {
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.gitCommit$ = this.stateService.gitCommit$.pipe(map((str) => str.substr(0, 8)));
 | 
			
		||||
    this.backendInfo$ = this.stateService.backendInfo$;
 | 
			
		||||
    this.seoService.setTitle($localize`:@@004b222ff9ef9dd4771b777950ca1d0e4cd4348a:About`);
 | 
			
		||||
    this.websocketService.want(['blocks']);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
 | 
			
		||||
  <div class="clearfix"></div>
 | 
			
		||||
 | 
			
		||||
  <table class="table table-borderless" [alwaysCallback]="true" [fromRoot]="true" [infiniteScrollContainer]="'body'" infiniteScroll [infiniteScrollDistance]="1.5" [infiniteScrollUpDistance]="1.5" [infiniteScrollThrottle]="50" (scrolled)="loadMore()">
 | 
			
		||||
  <table class="table table-borderless" [alwaysCallback]="true" infiniteScroll [infiniteScrollDistance]="1.5" [infiniteScrollUpDistance]="1.5" [infiniteScrollThrottle]="50" (scrolled)="loadMore()">
 | 
			
		||||
    <thead>
 | 
			
		||||
      <th style="width: 15%;" i18n="latest-blocks.height">Height</th>
 | 
			
		||||
      <th class="d-none d-md-block" style="width: 20%;" i18n="latest-blocks.timestamp">Timestamp</th>
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <div class="navbar-collapse" id="navbarCollapse">
 | 
			
		||||
    <ul class="navbar-nav mr-auto pt-2 pb-2 pb-md-0 pt-md-0 {{ network.val }}">
 | 
			
		||||
    <ul class="navbar-nav {{ network.val }}">
 | 
			
		||||
      <li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">
 | 
			
		||||
        <a class="nav-link" [routerLink]="['/' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'tachometer-alt']" [fixedWidth]="true" i18n-title="master-page.dashboard" title="Dashboard"></fa-icon></a>
 | 
			
		||||
      </li>
 | 
			
		||||
@ -62,7 +62,7 @@
 | 
			
		||||
        <a class="nav-link" [routerLink]="['/about']" (click)="collapse()"><fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true" i18n-title="master-page.about" title="About"></fa-icon></a>
 | 
			
		||||
      </li>
 | 
			
		||||
    </ul>
 | 
			
		||||
    <app-search-form location="top" (searchTriggered)="collapse()"></app-search-form>
 | 
			
		||||
    <app-search-form class="search-form-container" location="top" (searchTriggered)="collapse()"></app-search-form>
 | 
			
		||||
  </div>
 | 
			
		||||
</nav>
 | 
			
		||||
</header>
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
@ -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;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@
 | 
			
		||||
        <div class="card-header">
 | 
			
		||||
          <i class="fa fa-area-chart"></i> <span i18n="statistics.memory-by-vBytes">Mempool by vBytes (sat/vByte)</span>
 | 
			
		||||
 | 
			
		||||
          <form [formGroup]="radioGroupForm" style="float: right;">
 | 
			
		||||
          <form [formGroup]="radioGroupForm" style="float: right;" (click)="saveGraphPreference()">
 | 
			
		||||
            <div class="spinner-border text-light bootstrap-spinner" *ngIf="spinnerLoading"></div>
 | 
			
		||||
            <div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="dateSpan">
 | 
			
		||||
              <label ngbButtonLabel class="btn-primary btn-sm">
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,7 @@ export class StatisticsComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
  radioGroupForm: FormGroup;
 | 
			
		||||
  inverted: boolean;
 | 
			
		||||
  graphWindowPreference: String;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    @Inject(LOCALE_ID) private locale: string,
 | 
			
		||||
@ -45,16 +46,13 @@ export class StatisticsComponent implements OnInit {
 | 
			
		||||
    private stateService: StateService,
 | 
			
		||||
    private seoService: SeoService,
 | 
			
		||||
    private storageService: StorageService,
 | 
			
		||||
  ) {
 | 
			
		||||
    this.radioGroupForm = this.formBuilder.group({
 | 
			
		||||
      dateSpan: '2h'
 | 
			
		||||
    });
 | 
			
		||||
   }
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.seoService.setTitle($localize`:@@5d4f792f048fcaa6df5948575d7cb325c9393383:Graphs`);
 | 
			
		||||
    this.stateService.networkChanged$.subscribe((network) => this.network = network);
 | 
			
		||||
    this.inverted = this.storageService.getValue('inverted-graph') === 'true';
 | 
			
		||||
    this.graphWindowPreference = this.storageService.getValue('graphWindowPreference') ? this.storageService.getValue('graphWindowPreference').trim() : '2h';
 | 
			
		||||
    const isMobile = window.innerWidth <= 767.98;
 | 
			
		||||
    let labelHops = isMobile ? 48 : 24;
 | 
			
		||||
 | 
			
		||||
@ -62,8 +60,12 @@ export class StatisticsComponent implements OnInit {
 | 
			
		||||
      labelHops = 96;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.radioGroupForm = this.formBuilder.group({
 | 
			
		||||
      dateSpan: this.graphWindowPreference
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const labelInterpolationFnc = (value: any, index: any) => {
 | 
			
		||||
      switch (this.radioGroupForm.controls.dateSpan.value) {
 | 
			
		||||
      switch (this.graphWindowPreference) {
 | 
			
		||||
        case '2h':
 | 
			
		||||
        case '24h':
 | 
			
		||||
          value = formatDate(value, 'HH:mm', this.locale);
 | 
			
		||||
@ -166,4 +168,8 @@ export class StatisticsComponent implements OnInit {
 | 
			
		||||
    this.storageService.setValue('inverted-graph', !this.inverted);
 | 
			
		||||
    document.location.reload();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  saveGraphPreference() {
 | 
			
		||||
    this.storageService.setValue('graphWindowPreference', this.radioGroupForm.controls.dateSpan.value);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,7 @@
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="clearfix"></div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="header-bg box" infiniteScroll [alwaysCallback]="true" [fromRoot]="true" [infiniteScrollContainer]="'body'" [infiniteScrollDistance]="2" [infiniteScrollUpDistance]="1.5" [infiniteScrollThrottle]="50" (scrolled)="onScroll()">
 | 
			
		||||
  <div class="header-bg box" infiniteScroll [alwaysCallback]="true" [infiniteScrollDistance]="2" [infiniteScrollUpDistance]="1.5" [infiniteScrollThrottle]="50" (scrolled)="onScroll()">
 | 
			
		||||
    <div class="row">
 | 
			
		||||
      <div class="col">
 | 
			
		||||
        <table class="table table-borderless smaller-text table-xs" style="margin: 0;">
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
 | 
			
		||||
<div class="container-xl mt-2">
 | 
			
		||||
<div class="container-xl mt-2 dashboard-container">
 | 
			
		||||
 | 
			
		||||
  <div class="row row-cols-1 row-cols-md-2" *ngIf="{ value: (mempoolInfoData$ | async) } as mempoolInfoData">
 | 
			
		||||
    <ng-template [ngIf]="collapseLevel === 'three'" [ngIfElse]="expanded">
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,12 @@
 | 
			
		||||
.dashboard-container {
 | 
			
		||||
  padding-bottom: 60px;
 | 
			
		||||
}
 | 
			
		||||
@media (min-width: 992px) {
 | 
			
		||||
  .dashboard-container {
 | 
			
		||||
    padding-bottom: 0px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.card {
 | 
			
		||||
  background-color: #1d1f31;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@ export interface WebsocketResponse {
 | 
			
		||||
  rbfTransaction?: Transaction;
 | 
			
		||||
  transactions?: TransactionStripped[];
 | 
			
		||||
  loadingIndicators?: ILoadingIndicators;
 | 
			
		||||
  backendInfo?: IBackendInfo;
 | 
			
		||||
  'track-tx'?: string;
 | 
			
		||||
  'track-address'?: string;
 | 
			
		||||
  'track-asset'?: string;
 | 
			
		||||
@ -50,3 +51,8 @@ export interface TransactionStripped {
 | 
			
		||||
  value: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IBackendInfo {
 | 
			
		||||
  hostname: string;
 | 
			
		||||
  gitCommit: string;
 | 
			
		||||
  version: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
 | 
			
		||||
import { ReplaySubject, BehaviorSubject, Subject, fromEvent, Observable } from 'rxjs';
 | 
			
		||||
import { Block, Transaction } from '../interfaces/electrs.interface';
 | 
			
		||||
import { MempoolBlock, MempoolInfo, TransactionStripped } from '../interfaces/websocket.interface';
 | 
			
		||||
import { IBackendInfo, MempoolBlock, MempoolInfo, TransactionStripped } from '../interfaces/websocket.interface';
 | 
			
		||||
import { OptimizedMempoolStats } from '../interfaces/node-api.interface';
 | 
			
		||||
import { Router, NavigationStart } from '@angular/router';
 | 
			
		||||
import { isPlatformBrowser } from '@angular/common';
 | 
			
		||||
@ -28,6 +28,8 @@ export interface Env {
 | 
			
		||||
  NGINX_PROTOCOL?: string;
 | 
			
		||||
  NGINX_HOSTNAME?: string;
 | 
			
		||||
  NGINX_PORT?: string;
 | 
			
		||||
  GIT_COMMIT_HASH: string;
 | 
			
		||||
  PACKAGE_JSON_VERSION: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const defaultEnv: Env = {
 | 
			
		||||
@ -43,6 +45,8 @@ const defaultEnv: Env = {
 | 
			
		||||
  'NGINX_PROTOCOL': 'http',
 | 
			
		||||
  'NGINX_HOSTNAME': '127.0.0.1',
 | 
			
		||||
  'NGINX_PORT': '80',
 | 
			
		||||
  'GIT_COMMIT_HASH': '',
 | 
			
		||||
  'PACKAGE_JSON_VERSION': '',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
@ -67,7 +71,7 @@ export class StateService {
 | 
			
		||||
  isLoadingWebSocket$ = new ReplaySubject<boolean>(1);
 | 
			
		||||
  vbytesPerSecond$ = new ReplaySubject<number>(1);
 | 
			
		||||
  lastDifficultyAdjustment$ = new ReplaySubject<number>(1);
 | 
			
		||||
  gitCommit$ = new ReplaySubject<string>(1);
 | 
			
		||||
  backendInfo$ = new ReplaySubject<IBackendInfo>(1);
 | 
			
		||||
  loadingIndicators$ = new ReplaySubject<ILoadingIndicators>(1);
 | 
			
		||||
 | 
			
		||||
  live2Chart$ = new Subject<OptimizedMempoolStats>();
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
 | 
			
		||||
import { WebsocketResponse } from '../interfaces/websocket.interface';
 | 
			
		||||
import { WebsocketResponse, IBackendInfo } from '../interfaces/websocket.interface';
 | 
			
		||||
import { StateService } from './state.service';
 | 
			
		||||
import { Block, Transaction } from '../interfaces/electrs.interface';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
@ -244,13 +244,13 @@ export class WebsocketService {
 | 
			
		||||
      this.stateService.bsqPrice$.next(response['bsq-price']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (response['git-commit']) {
 | 
			
		||||
      this.stateService.gitCommit$.next(response['git-commit']);
 | 
			
		||||
    if (response.backendInfo) {
 | 
			
		||||
      this.stateService.backendInfo$.next(response.backendInfo);
 | 
			
		||||
 | 
			
		||||
      if (!this.latestGitCommit) {
 | 
			
		||||
        this.latestGitCommit = response['git-commit'];
 | 
			
		||||
        this.latestGitCommit = response.backendInfo.gitCommit;
 | 
			
		||||
      } else {
 | 
			
		||||
        if (this.latestGitCommit !== response['git-commit']) {
 | 
			
		||||
        if (this.latestGitCommit !== response.backendInfo.gitCommit) {
 | 
			
		||||
          setTimeout(() => {
 | 
			
		||||
            window.location.reload();
 | 
			
		||||
          }, Math.floor(Math.random() * 60000) + 60000);
 | 
			
		||||
@ -291,7 +291,7 @@ export class WebsocketService {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (response['git-commit']) {
 | 
			
		||||
      this.stateService.gitCommit$.next(response['git-commit']);
 | 
			
		||||
      this.stateService.backendInfo$.next(response['git-commit']);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										16
									
								
								frontend/src/resources/profile/exodus.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								frontend/src/resources/profile/exodus.svg
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<svg width="400px" height="400px" viewBox="0 0 400 400" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
 | 
			
		||||
    <title>Exodus_logo</title>
 | 
			
		||||
    <defs>
 | 
			
		||||
        <linearGradient x1="0%" y1="50%" x2="100%" y2="50%" id="linearGradient-1">
 | 
			
		||||
            <stop stop-color="#00BFFF" offset="0%"></stop>
 | 
			
		||||
            <stop stop-color="#6619FF" offset="100%"></stop>
 | 
			
		||||
        </linearGradient>
 | 
			
		||||
    </defs>
 | 
			
		||||
    <g id="Exodus_logo" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
 | 
			
		||||
        <g id="Exodus-logo">
 | 
			
		||||
            <rect id="Rectangle" fill="#1A1D40" x="0" y="0" width="400" height="400"></rect>
 | 
			
		||||
            <path d="M244.25,200 L310,265.75 L286.8,265.75 C282.823093,265.746499 279.010347,264.16385 276.2,261.35 L215,200 L276.25,138.6 C279.068515,135.804479 282.880256,134.240227 286.85,134.249954 L310,134.249954 L244.25,200 Z M123.75,138.6 C120.931485,135.804479 117.119744,134.240227 113.15,134.249954 L90,134.249954 L155.75,200 L90,265.75 L113.2,265.75 C117.176907,265.746499 120.989653,264.16385 123.8,261.35 L185,200 L123.75,138.6 Z M200,215 L138.6,276.25 C135.804479,279.068515 134.240227,282.880256 134.249954,286.85 L134.249954,310 L200,244.25 L265.750046,310 L265.750046,286.85 C265.759773,282.880256 264.195521,279.068515 261.4,276.25 L200,215 Z M200,185 L261.4,123.75 C264.195521,120.931485 265.759773,117.119744 265.750046,113.15 L265.750046,90 L200,155.75 L134.249954,90 L134.249954,113.15 C134.240227,117.119744 135.804479,120.931485 138.6,123.75 L200,185 Z" id="01-Exodus-wallet" fill="url(#linearGradient-1)" fill-rule="nonzero"></path>
 | 
			
		||||
        </g>
 | 
			
		||||
    </g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.6 KiB  | 
							
								
								
									
										26
									
								
								frontend/src/resources/profile/sqcrypto.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								frontend/src/resources/profile/sqcrypto.svg
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
 | 
			
		||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
 | 
			
		||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="200" height="200" viewBox="0 0 200 200" xml:space="preserve">
 | 
			
		||||
<defs>
 | 
			
		||||
</defs>
 | 
			
		||||
<rect x="0" y="0" width="100%" height="100%" fill="transparent"></rect>
 | 
			
		||||
<g transform="matrix(1 0 0 1 100 100)" id="83eb3c06-e75b-4ba8-8ae0-6ecee4a0a0b2">
 | 
			
		||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(255,255,255); fill-rule: nonzero; opacity: 1; visibility: hidden;" vector-effect="non-scaling-stroke"  x="-100" y="-100" rx="0" ry="0" width="200" height="200" />
 | 
			
		||||
</g>
 | 
			
		||||
<g transform="matrix(Infinity NaN NaN Infinity 0 0)" id="dde875c5-c3d7-4902-975f-2f9bad8740df">
 | 
			
		||||
</g>
 | 
			
		||||
<g transform="matrix(0.63 0 0 0.63 100 100)">
 | 
			
		||||
<g style="" vector-effect="non-scaling-stroke" >
 | 
			
		||||
<g transform="matrix(1 0 0 1 0 0)">
 | 
			
		||||
<rect style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(27,20,100); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  x="-250" y="-250" rx="0" ry="0" width="500" height="500" />
 | 
			
		||||
</g>
 | 
			
		||||
<g transform="matrix(1 0 0 1 0 0.18)">
 | 
			
		||||
<linearGradient id="SVGID_linear-gradient_3" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1 0 0 1 0 0)"  x1="175" y1="250" x2="325" y2="250">
 | 
			
		||||
<stop offset="0%" style="stop-color:rgb(255,0,255);stop-opacity: 1"/>
 | 
			
		||||
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity: 1"/>
 | 
			
		||||
</linearGradient>
 | 
			
		||||
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: url(#SVGID_linear-gradient_3); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke"  transform=" translate(-250, -250.18)" d="M 188.66 297.69 C 185.0380626090283 297.68734656530177 181.56356211596963 299.12429596327104 179.00152732293847 301.6844551817831 C 176.4394925299073 304.24461440029523 174.99999902804578 307.71806163707413 175 311.34 L 175 311.34 C 174.86558420938763 316.3065680538503 177.43841429565256 320.95448731944555 181.7185832795378 323.47738630824387 C 185.99875226342303 326.0002852970422 191.31124773657697 326.0002852970422 195.5914167204622 323.47738630824387 C 199.87158570434744 320.95448731944555 202.44441579061237 316.3065680538503 202.31 311.34 L 202.31 311.34 C 202.30999999999997 303.80131316480964 196.1986868351903 297.69 188.66 297.69 Z M 270.38 236.34 L 175 236.34 L 175 263.66 L 270.38 263.66 Z M 188.66 202.34 C 196.20160441229743 202.33999191662778 202.31630849754845 196.22826042470857 202.319983736653 188.6866569079313 C 202.32365897575752 181.14505339115408 196.2149146365801 175.02736506319306 188.67331381425902 175.02000650248846 C 181.13171299193795 175.01264794178383 175.01104188054944 181.11840367107047 175 188.66 C 174.99999902804578 192.2819383629258 176.4394925299073 195.75538559970477 179.00152732293847 198.3155448182169 C 181.56356211596963 200.875704036729 185.03806260902826 202.31265343469823 188.66 202.31 Z M 309.65999999999997 175.03 L 229.65999999999997 175.03 L 229.65999999999997 202.34 L 325 202.34 L 325 190.34 C 325 181.86795193759565 318.1320480624044 175.00000000000003 309.66 175 Z M 229.65999999999997 325.03 L 309.65999999999997 325.03 C 313.7336241240884 325.03000779010233 317.63996644087825 323.4097163707201 320.5176384181544 320.52641661252363 C 323.3953103954305 317.6431168543272 325.00796667039356 313.73361633399355 325 309.66 L 325 297.66 L 229.62 297.66 Z M 311.38 236.36999999999998 C 305.8487069817187 236.35381616694565 300.8536160844738 239.674936531664 298.7284620682323 244.7817148485476 C 296.6033080519909 249.8884931654312 297.7676142525571 255.7728083014525 301.67741021826106 259.68547489561877 C 305.587206183965 263.59814148978506 311.4706651985733 264.7667661395809 316.5790018858666 262.645360789396 C 321.6873385731599 260.52395543921114 325.01212416464153 255.53130340653732 325 250 C 325 246.3771427487918 323.5608255606084 242.90266829859192 320.9990786310082 240.34092136899176 C 318.4373317014081 237.7791744393916 314.96285725120816 236.34 311.34 236.34 Z" stroke-linecap="round" />
 | 
			
		||||
</g>
 | 
			
		||||
</g>
 | 
			
		||||
</g>
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 4.3 KiB  | 
@ -50,11 +50,11 @@ $dropdown-link-active-bg: #11131f;
 | 
			
		||||
 | 
			
		||||
html, body {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  overflow-x: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
  background-color: #11131f;
 | 
			
		||||
  min-width: 320px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.container {
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,7 @@
 | 
			
		||||
    "MINED_BLOCKS_CACHE": 144,
 | 
			
		||||
    "SPAWN_CLUSTER_PROCS": 0,
 | 
			
		||||
    "API_URL_PREFIX": "/api/v1/",
 | 
			
		||||
    "CLEAR_PROTECTION_MINUTES": 5,
 | 
			
		||||
    "POLL_RATE_MS": 2000
 | 
			
		||||
  },
 | 
			
		||||
  "CORE_RPC": {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								production/sysctl.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								production/sysctl.conf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
net.inet.tcp.fast_finwait2_recycle=1
 | 
			
		||||
kern.ipc.soacceptqueue=1024
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user