2020-11-07 04:30:52 +07:00
|
|
|
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
|
|
|
|
import { ReplaySubject, BehaviorSubject, Subject, fromEvent, Observable } from 'rxjs';
|
2022-02-04 12:51:45 +09:00
|
|
|
import { Transaction } from '../interfaces/electrs.interface';
|
2022-03-08 14:49:25 +01:00
|
|
|
import { IBackendInfo, MempoolBlock, MempoolInfo, ReplacedTransaction, TransactionStripped } from '../interfaces/websocket.interface';
|
2022-02-04 12:51:45 +09:00
|
|
|
import { BlockExtended, OptimizedMempoolStats } from '../interfaces/node-api.interface';
|
2020-05-09 20:37:50 +07:00
|
|
|
import { Router, NavigationStart } from '@angular/router';
|
2020-11-07 04:30:52 +07:00
|
|
|
import { isPlatformBrowser } from '@angular/common';
|
|
|
|
import { map, shareReplay } from 'rxjs/operators';
|
2020-02-16 22:15:07 +07:00
|
|
|
|
2020-03-22 17:44:36 +07:00
|
|
|
interface MarkBlockState {
|
|
|
|
blockHeight?: number;
|
|
|
|
mempoolBlockIndex?: number;
|
|
|
|
txFeePerVSize?: number;
|
|
|
|
}
|
|
|
|
|
2021-01-05 18:57:06 +07:00
|
|
|
export interface ILoadingIndicators { [name: string]: number; }
|
|
|
|
|
2020-11-23 02:30:46 +07:00
|
|
|
export interface Env {
|
|
|
|
TESTNET_ENABLED: boolean;
|
2021-02-20 23:12:22 +07:00
|
|
|
SIGNET_ENABLED: boolean;
|
2022-01-20 17:19:16 +01:00
|
|
|
REGTEST_ENABLED: boolean;
|
2020-11-23 02:30:46 +07:00
|
|
|
LIQUID_ENABLED: boolean;
|
2021-12-27 22:54:45 +04:00
|
|
|
LIQUID_TESTNET_ENABLED: boolean;
|
2020-11-23 02:30:46 +07:00
|
|
|
BISQ_ENABLED: boolean;
|
|
|
|
BISQ_SEPARATE_BACKEND: boolean;
|
2021-01-11 21:11:09 +07:00
|
|
|
ITEMS_PER_PAGE: number;
|
2020-11-23 02:30:46 +07:00
|
|
|
KEEP_BLOCKS_AMOUNT: number;
|
2021-02-18 13:34:05 +07:00
|
|
|
OFFICIAL_MEMPOOL_SPACE: boolean;
|
2021-07-27 17:10:38 +03:00
|
|
|
BASE_MODULE: string;
|
2020-11-27 23:01:47 +09:00
|
|
|
NGINX_PROTOCOL?: string;
|
|
|
|
NGINX_HOSTNAME?: string;
|
|
|
|
NGINX_PORT?: string;
|
2021-07-31 17:30:35 +03:00
|
|
|
BLOCK_WEIGHT_UNITS: number;
|
2021-07-31 17:56:10 +03:00
|
|
|
MEMPOOL_BLOCKS_AMOUNT: number;
|
2021-04-12 22:17:13 +04:00
|
|
|
GIT_COMMIT_HASH: string;
|
|
|
|
PACKAGE_JSON_VERSION: string;
|
2022-01-07 20:17:14 +04:00
|
|
|
MEMPOOL_WEBSITE_URL: string;
|
|
|
|
LIQUID_WEBSITE_URL: string;
|
|
|
|
BISQ_WEBSITE_URL: string;
|
2022-02-15 16:02:30 +09:00
|
|
|
MINING_DASHBOARD: boolean;
|
2020-11-23 02:30:46 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
const defaultEnv: Env = {
|
|
|
|
'TESTNET_ENABLED': false,
|
2021-02-20 23:12:22 +07:00
|
|
|
'SIGNET_ENABLED': false,
|
2022-01-20 17:19:16 +01:00
|
|
|
'REGTEST_ENABLED': false,
|
2020-11-23 02:30:46 +07:00
|
|
|
'LIQUID_ENABLED': false,
|
2021-12-27 22:54:45 +04:00
|
|
|
'LIQUID_TESTNET_ENABLED': false,
|
2021-07-27 17:10:38 +03:00
|
|
|
'BASE_MODULE': 'mempool',
|
2020-11-23 02:30:46 +07:00
|
|
|
'BISQ_ENABLED': false,
|
|
|
|
'BISQ_SEPARATE_BACKEND': false,
|
2021-01-11 21:11:09 +07:00
|
|
|
'ITEMS_PER_PAGE': 10,
|
2020-11-23 02:30:46 +07:00
|
|
|
'KEEP_BLOCKS_AMOUNT': 8,
|
2021-02-18 13:34:05 +07:00
|
|
|
'OFFICIAL_MEMPOOL_SPACE': false,
|
2020-11-27 23:01:47 +09:00
|
|
|
'NGINX_PROTOCOL': 'http',
|
|
|
|
'NGINX_HOSTNAME': '127.0.0.1',
|
2021-01-11 21:06:47 +07:00
|
|
|
'NGINX_PORT': '80',
|
2021-07-31 17:30:35 +03:00
|
|
|
'BLOCK_WEIGHT_UNITS': 4000000,
|
2021-07-31 17:56:10 +03:00
|
|
|
'MEMPOOL_BLOCKS_AMOUNT': 8,
|
2021-04-12 22:17:13 +04:00
|
|
|
'GIT_COMMIT_HASH': '',
|
|
|
|
'PACKAGE_JSON_VERSION': '',
|
2022-01-07 20:17:14 +04:00
|
|
|
'MEMPOOL_WEBSITE_URL': 'https://mempool.space',
|
|
|
|
'LIQUID_WEBSITE_URL': 'https://liquid.network',
|
|
|
|
'BISQ_WEBSITE_URL': 'https://bisq.markets',
|
2022-02-15 16:02:30 +09:00
|
|
|
'MINING_DASHBOARD': true
|
2020-11-23 02:30:46 +07:00
|
|
|
};
|
|
|
|
|
2020-02-16 22:15:07 +07:00
|
|
|
@Injectable({
|
|
|
|
providedIn: 'root'
|
|
|
|
})
|
|
|
|
export class StateService {
|
2020-11-07 04:30:52 +07:00
|
|
|
isBrowser: boolean = isPlatformBrowser(this.platformId);
|
2020-05-09 20:37:50 +07:00
|
|
|
network = '';
|
2021-07-31 17:30:35 +03:00
|
|
|
blockVSize: number;
|
2020-11-23 02:30:46 +07:00
|
|
|
env: Env;
|
2022-01-19 17:11:35 +01:00
|
|
|
latestBlockHeight = -1;
|
2020-05-09 20:37:50 +07:00
|
|
|
|
|
|
|
networkChanged$ = new ReplaySubject<string>(1);
|
2022-02-04 12:51:45 +09:00
|
|
|
blocks$: ReplaySubject<[BlockExtended, boolean]>;
|
2020-09-26 02:11:30 +07:00
|
|
|
transactions$ = new ReplaySubject<TransactionStripped>(6);
|
2020-02-16 22:15:07 +07:00
|
|
|
conversions$ = new ReplaySubject<any>(1);
|
2020-07-14 21:26:02 +07:00
|
|
|
bsqPrice$ = new ReplaySubject<number>(1);
|
2020-08-12 13:33:58 +07:00
|
|
|
mempoolInfo$ = new ReplaySubject<MempoolInfo>(1);
|
2020-07-24 14:11:49 +07:00
|
|
|
mempoolBlocks$ = new ReplaySubject<MempoolBlock[]>(1);
|
2022-03-08 14:49:25 +01:00
|
|
|
txReplaced$ = new Subject<ReplacedTransaction>();
|
2022-03-07 19:45:09 +01:00
|
|
|
utxoSpent$ = new Subject<object>();
|
2020-02-23 19:16:50 +07:00
|
|
|
mempoolTransactions$ = new Subject<Transaction>();
|
|
|
|
blockTransactions$ = new Subject<Transaction>();
|
2020-07-22 19:21:40 +07:00
|
|
|
isLoadingWebSocket$ = new ReplaySubject<boolean>(1);
|
2020-08-12 13:33:58 +07:00
|
|
|
vbytesPerSecond$ = new ReplaySubject<number>(1);
|
2020-09-21 19:41:12 +07:00
|
|
|
lastDifficultyAdjustment$ = new ReplaySubject<number>(1);
|
2021-07-24 19:26:48 -03:00
|
|
|
previousRetarget$ = new ReplaySubject<number>(1);
|
2021-04-12 22:17:13 +04:00
|
|
|
backendInfo$ = new ReplaySubject<IBackendInfo>(1);
|
2021-01-05 18:57:06 +07:00
|
|
|
loadingIndicators$ = new ReplaySubject<ILoadingIndicators>(1);
|
2020-02-23 19:16:50 +07:00
|
|
|
|
2020-02-17 00:26:57 +07:00
|
|
|
live2Chart$ = new Subject<OptimizedMempoolStats>();
|
2020-02-16 22:15:07 +07:00
|
|
|
|
|
|
|
viewFiat$ = new BehaviorSubject<boolean>(false);
|
2020-03-09 17:53:54 +07:00
|
|
|
connectionState$ = new BehaviorSubject<0 | 1 | 2>(2);
|
2020-11-07 04:30:52 +07:00
|
|
|
isTabHidden$: Observable<boolean>;
|
2020-03-22 17:44:36 +07:00
|
|
|
|
2020-05-20 17:00:50 +07:00
|
|
|
markBlock$ = new ReplaySubject<MarkBlockState>();
|
2020-05-13 13:03:57 +07:00
|
|
|
keyNavigation$ = new Subject<KeyboardEvent>();
|
2020-05-09 20:37:50 +07:00
|
|
|
|
2021-12-19 15:20:21 +09:00
|
|
|
blockScrolling$: Subject<boolean> = new Subject<boolean>();
|
|
|
|
|
2020-05-09 20:37:50 +07:00
|
|
|
constructor(
|
2020-11-07 04:30:52 +07:00
|
|
|
@Inject(PLATFORM_ID) private platformId: any,
|
2020-05-09 20:37:50 +07:00
|
|
|
private router: Router,
|
|
|
|
) {
|
2021-07-27 17:10:38 +03:00
|
|
|
const browserWindow = window || {};
|
|
|
|
// @ts-ignore
|
|
|
|
const browserWindowEnv = browserWindow.__env || {};
|
|
|
|
this.env = Object.assign(defaultEnv, browserWindowEnv);
|
2020-11-07 04:30:52 +07:00
|
|
|
|
|
|
|
if (this.isBrowser) {
|
|
|
|
this.setNetworkBasedonUrl(window.location.pathname);
|
|
|
|
this.isTabHidden$ = fromEvent(document, 'visibilitychange').pipe(map(() => this.isHidden()), shareReplay());
|
|
|
|
} else {
|
|
|
|
this.setNetworkBasedonUrl('/');
|
|
|
|
this.isTabHidden$ = new BehaviorSubject(false);
|
|
|
|
}
|
2020-11-23 02:30:46 +07:00
|
|
|
|
2021-07-27 17:10:38 +03:00
|
|
|
this.router.events.subscribe((event) => {
|
|
|
|
if (event instanceof NavigationStart) {
|
|
|
|
this.setNetworkBasedonUrl(event.url);
|
|
|
|
}
|
|
|
|
});
|
2020-11-23 02:30:46 +07:00
|
|
|
|
2022-02-04 12:51:45 +09:00
|
|
|
this.blocks$ = new ReplaySubject<[BlockExtended, boolean]>(this.env.KEEP_BLOCKS_AMOUNT);
|
2021-07-27 17:10:38 +03:00
|
|
|
|
2021-12-27 22:54:45 +04:00
|
|
|
if (this.env.BASE_MODULE === 'bisq') {
|
2021-07-27 17:10:38 +03:00
|
|
|
this.network = this.env.BASE_MODULE;
|
|
|
|
this.networkChanged$.next(this.env.BASE_MODULE);
|
|
|
|
}
|
2021-07-31 17:30:35 +03:00
|
|
|
|
|
|
|
this.blockVSize = this.env.BLOCK_WEIGHT_UNITS / 4;
|
2020-05-09 20:37:50 +07:00
|
|
|
}
|
2020-05-10 12:31:57 +07:00
|
|
|
|
|
|
|
setNetworkBasedonUrl(url: string) {
|
2021-12-27 22:54:45 +04:00
|
|
|
if (this.env.BASE_MODULE !== 'mempool' && this.env.BASE_MODULE !== 'liquid') {
|
2021-07-27 17:10:38 +03:00
|
|
|
return;
|
|
|
|
}
|
2022-01-20 17:19:16 +01:00
|
|
|
const networkMatches = url.match(/\/(bisq|testnet|liquidtestnet|liquid|signet|regtest)/);
|
2021-02-01 04:17:34 +07:00
|
|
|
switch (networkMatches && networkMatches[1]) {
|
2020-05-10 12:31:57 +07:00
|
|
|
case 'liquid':
|
|
|
|
if (this.network !== 'liquid') {
|
|
|
|
this.network = 'liquid';
|
|
|
|
this.networkChanged$.next('liquid');
|
|
|
|
}
|
|
|
|
return;
|
2021-12-27 22:54:45 +04:00
|
|
|
case 'liquidtestnet':
|
|
|
|
if (this.network !== 'liquidtestnet') {
|
|
|
|
this.network = 'liquidtestnet';
|
|
|
|
this.networkChanged$.next('liquidtestnet');
|
|
|
|
}
|
|
|
|
return;
|
2021-02-20 23:12:22 +07:00
|
|
|
case 'signet':
|
|
|
|
if (this.network !== 'signet') {
|
|
|
|
this.network = 'signet';
|
|
|
|
this.networkChanged$.next('signet');
|
|
|
|
}
|
|
|
|
return;
|
2022-01-20 17:19:16 +01:00
|
|
|
case 'regtest':
|
|
|
|
if (this.network !== 'regtest') {
|
|
|
|
this.network = 'regtest';
|
|
|
|
this.networkChanged$.next('regtest');
|
|
|
|
}
|
|
|
|
return;
|
2020-05-10 12:31:57 +07:00
|
|
|
case 'testnet':
|
|
|
|
if (this.network !== 'testnet') {
|
2021-12-27 22:54:45 +04:00
|
|
|
if (this.env.BASE_MODULE === 'liquid') {
|
|
|
|
this.network = 'liquidtestnet';
|
|
|
|
this.networkChanged$.next('liquidtestnet');
|
|
|
|
} else {
|
|
|
|
this.network = 'testnet';
|
|
|
|
this.networkChanged$.next('testnet');
|
|
|
|
}
|
2020-05-10 12:31:57 +07:00
|
|
|
}
|
|
|
|
return;
|
2020-07-03 23:45:19 +07:00
|
|
|
case 'bisq':
|
|
|
|
if (this.network !== 'bisq') {
|
|
|
|
this.network = 'bisq';
|
|
|
|
this.networkChanged$.next('bisq');
|
|
|
|
}
|
|
|
|
return;
|
2020-05-10 12:31:57 +07:00
|
|
|
default:
|
2021-12-30 03:07:08 +04:00
|
|
|
if (this.env.BASE_MODULE !== 'mempool') {
|
|
|
|
if (this.network !== this.env.BASE_MODULE) {
|
|
|
|
this.network = this.env.BASE_MODULE;
|
|
|
|
this.networkChanged$.next(this.env.BASE_MODULE);
|
2021-12-27 22:54:45 +04:00
|
|
|
}
|
2021-12-30 03:07:08 +04:00
|
|
|
} else if (this.network !== '') {
|
|
|
|
this.network = '';
|
|
|
|
this.networkChanged$.next('');
|
2020-05-10 12:31:57 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-11 01:38:59 +07:00
|
|
|
|
|
|
|
getHiddenProp(){
|
|
|
|
const prefixes = ['webkit', 'moz', 'ms', 'o'];
|
|
|
|
if ('hidden' in document) { return 'hidden'; }
|
|
|
|
for (const prefix of prefixes) {
|
|
|
|
if ((prefix + 'Hidden') in document) {
|
|
|
|
return prefix + 'Hidden';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
isHidden() {
|
|
|
|
const prop = this.getHiddenProp();
|
|
|
|
if (!prop) { return false; }
|
|
|
|
return document[prop];
|
|
|
|
}
|
2021-12-19 15:20:21 +09:00
|
|
|
|
|
|
|
setBlockScrollingInProgress(value: boolean) {
|
|
|
|
this.blockScrolling$.next(value);
|
|
|
|
}
|
2022-01-04 04:42:19 +04:00
|
|
|
|
|
|
|
isLiquid() {
|
|
|
|
return this.network === 'liquid' || this.network === 'liquidtestnet';
|
|
|
|
}
|
2020-02-16 22:15:07 +07:00
|
|
|
}
|