mirror of
https://github.com/mempool/mempool.git
synced 2025-03-26 17:51:45 +01:00
Frontend config support for AU. New absolute server url settings.
refs #104
This commit is contained in:
parent
83126b83f1
commit
c36addd8c1
@ -25,7 +25,7 @@ for (setting in configContent) {
|
||||
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 };`, '')}
|
||||
}(this));`;
|
||||
}(global || this));`;
|
||||
|
||||
try {
|
||||
fs.writeFileSync(GENERATED_CONFIG_FILE_NAME, code, 'utf8');
|
||||
|
@ -3,7 +3,10 @@
|
||||
"LIQUID_ENABLED": false,
|
||||
"BISQ_ENABLED": false,
|
||||
"BISQ_SEPARATE_BACKEND": false,
|
||||
"ELCTRS_ITEMS_PER_PAGE": 25,
|
||||
"ELECTRS_ITEMS_PER_PAGE": 25,
|
||||
"KEEP_BLOCKS_AMOUNT": 8,
|
||||
"SPONSORS_ENABLED": false
|
||||
"SPONSORS_ENABLED": false,
|
||||
"BACKEND_ABSOLUTE_URL": "http://localhost:8999",
|
||||
"ELECTRS_ABSOLUTE_URL": "http://localhost:4200",
|
||||
"ELECTRS_ABSOLUTE_URL_SERVER": "http://localhost:50001"
|
||||
}
|
@ -30,7 +30,7 @@
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e",
|
||||
"dev:ssr": "ng run mempool:serve-ssr",
|
||||
"dev:ssr": "npm run generate-config && ng run mempool:serve-ssr",
|
||||
"serve:ssr": "node dist/mempool/server/main.js",
|
||||
"build:ssr": "npm run build && ng run mempool:server:production",
|
||||
"prerender": "ng run mempool:prerender"
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'zone.js/dist/zone-node';
|
||||
import './generated-config';
|
||||
|
||||
import { ngExpressEngine } from '@nguniversal/express-engine';
|
||||
import * as express from 'express';
|
||||
@ -16,6 +17,9 @@ const template = fs.readFileSync(path.join(__dirname, '../../mempool/browser/',
|
||||
|
||||
const win = domino.createWindow(template);
|
||||
|
||||
// @ts-ignore
|
||||
win.__env = global.__env;
|
||||
|
||||
// @ts-ignore
|
||||
win.matchMedia = () => {
|
||||
return {
|
||||
@ -41,7 +45,6 @@ global['localStorage'] = {
|
||||
key: () => '',
|
||||
};
|
||||
|
||||
|
||||
// The Express app is exported so that it can be used by serverless Functions.
|
||||
export function app(): express.Express {
|
||||
const server = express();
|
||||
@ -70,7 +73,8 @@ export function app(): express.Express {
|
||||
));
|
||||
|
||||
server.get('/api/**', createProxyMiddleware({
|
||||
target: 'http://localhost:50001',
|
||||
// @ts-ignore
|
||||
target: win.__env.ELECTRS_ABSOLUTE_URL_SERVER,
|
||||
changeOrigin: true,
|
||||
pathRewrite: {'^/api' : '/'}
|
||||
},
|
||||
@ -90,7 +94,7 @@ function run(): void {
|
||||
// Start up the Node server
|
||||
const server = app();
|
||||
server.listen(port, () => {
|
||||
console.log(`Node Express server listening on http://localhost:${port}`);
|
||||
console.log(`Node Express server listening on port ${port}`);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -33,28 +33,3 @@ export const mempoolFeeColors = [
|
||||
|
||||
export const feeLevels = [1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100, 125, 150, 175, 200,
|
||||
250, 300, 350, 400, 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000];
|
||||
|
||||
interface Env {
|
||||
TESTNET_ENABLED: boolean;
|
||||
LIQUID_ENABLED: boolean;
|
||||
BISQ_ENABLED: boolean;
|
||||
BISQ_SEPARATE_BACKEND: boolean;
|
||||
SPONSORS_ENABLED: boolean;
|
||||
ELCTRS_ITEMS_PER_PAGE: number;
|
||||
KEEP_BLOCKS_AMOUNT: number;
|
||||
}
|
||||
|
||||
const defaultEnv: Env = {
|
||||
'TESTNET_ENABLED': false,
|
||||
'LIQUID_ENABLED': false,
|
||||
'BISQ_ENABLED': false,
|
||||
'BISQ_SEPARATE_BACKEND': false,
|
||||
'SPONSORS_ENABLED': false,
|
||||
'ELCTRS_ITEMS_PER_PAGE': 25,
|
||||
'KEEP_BLOCKS_AMOUNT': 8
|
||||
};
|
||||
|
||||
const browserWindow = {};
|
||||
// @ts-ignore
|
||||
const browserWindowEnv = browserWindow.__env || {};
|
||||
export const env: Env = Object.assign(defaultEnv, browserWindowEnv);
|
||||
|
@ -5,7 +5,6 @@ import { StateService } from 'src/app/services/state.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { ApiService } from 'src/app/services/api.service';
|
||||
import { env } from '../../app.constants';
|
||||
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
@ -21,7 +20,7 @@ export class AboutComponent implements OnInit {
|
||||
donationStatus = 1;
|
||||
sponsors$: Observable<any>;
|
||||
donationObj: any;
|
||||
sponsorsEnabled = env.SPONSORS_ENABLED;
|
||||
sponsorsEnabled = this.stateService.env.SPONSORS_ENABLED;
|
||||
sponsors = null;
|
||||
|
||||
constructor(
|
||||
|
@ -7,7 +7,6 @@ import { Block, Transaction, Vout } from '../../interfaces/electrs.interface';
|
||||
import { of, Subscription } from 'rxjs';
|
||||
import { StateService } from '../../services/state.service';
|
||||
import { SeoService } from 'src/app/services/seo.service';
|
||||
import { env } from 'src/app/app.constants';
|
||||
import { WebsocketService } from 'src/app/services/websocket.service';
|
||||
|
||||
@Component({
|
||||
@ -31,7 +30,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
||||
paginationMaxSize: number;
|
||||
coinbaseTx: Transaction;
|
||||
page = 1;
|
||||
itemsPerPage = env.ELCTRS_ITEMS_PER_PAGE;
|
||||
itemsPerPage: number;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@ -47,6 +46,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
||||
this.websocketService.want(['blocks', 'mempool-blocks']);
|
||||
this.paginationMaxSize = window.matchMedia('(max-width: 700px)').matches ? 3 : 5;
|
||||
this.network = this.stateService.network;
|
||||
this.itemsPerPage = this.stateService.env.ELECTRS_ITEMS_PER_PAGE;
|
||||
|
||||
this.subscription = this.route.paramMap
|
||||
.pipe(
|
||||
|
@ -3,7 +3,6 @@ import { Subscription } from 'rxjs';
|
||||
import { Block } from 'src/app/interfaces/electrs.interface';
|
||||
import { StateService } from 'src/app/services/state.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { env } from 'src/app/app.constants';
|
||||
|
||||
@Component({
|
||||
selector: 'app-blockchain-blocks',
|
||||
@ -78,7 +77,7 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy {
|
||||
this.cd.markForCheck();
|
||||
}, 50);
|
||||
|
||||
if (this.blocks.length === env.KEEP_BLOCKS_AMOUNT) {
|
||||
if (this.blocks.length === this.stateService.env.KEEP_BLOCKS_AMOUNT) {
|
||||
this.blocksFilled = true;
|
||||
}
|
||||
this.cd.markForCheck();
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { StateService } from '../../services/state.service';
|
||||
import { env } from 'src/app/app.constants';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Env, StateService } from '../../services/state.service';
|
||||
import { Observable, merge, of } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
@ -9,7 +8,7 @@ import { Observable, merge, of } from 'rxjs';
|
||||
styleUrls: ['./master-page.component.scss'],
|
||||
})
|
||||
export class MasterPageComponent implements OnInit {
|
||||
env = env;
|
||||
env: Env;
|
||||
network$: Observable<string>;
|
||||
connectionState$: Observable<number>;
|
||||
navCollapsed = false;
|
||||
@ -20,6 +19,7 @@ export class MasterPageComponent implements OnInit {
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.env = this.stateService.env;
|
||||
this.connectionState$ = this.stateService.connectionState$;
|
||||
this.network$ = merge(of(''), this.stateService.networkChanged$);
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ import { switchMap, map, tap, filter } from 'rxjs/operators';
|
||||
import { MempoolBlock } from 'src/app/interfaces/websocket.interface';
|
||||
import { Observable, BehaviorSubject } from 'rxjs';
|
||||
import { SeoService } from 'src/app/services/seo.service';
|
||||
import { env } from 'src/app/app.constants';
|
||||
import { WebsocketService } from 'src/app/services/websocket.service';
|
||||
|
||||
@Component({
|
||||
@ -70,7 +69,7 @@ export class MempoolBlockComponent implements OnInit, OnDestroy {
|
||||
const blocksInBlock = Math.ceil(mempoolBlock.blockVSize / 1000000);
|
||||
if (this.mempoolBlockIndex === 0) {
|
||||
return 'Next block';
|
||||
} else if (this.mempoolBlockIndex === env.KEEP_BLOCKS_AMOUNT - 1 && blocksInBlock > 1 ) {
|
||||
} else if (this.mempoolBlockIndex === this.stateService.env.KEEP_BLOCKS_AMOUNT - 1 && blocksInBlock > 1 ) {
|
||||
return `Stack of ${blocksInBlock} blocks`;
|
||||
} else {
|
||||
const s = ['th', 'st', 'nd', 'rd'];
|
||||
|
@ -3,7 +3,6 @@ import { HttpClient, HttpParams } from '@angular/common/http';
|
||||
import { OptimizedMempoolStats } from '../interfaces/node-api.interface';
|
||||
import { Observable } from 'rxjs';
|
||||
import { StateService } from './state.service';
|
||||
import { env } from '../app.constants';
|
||||
import { WebsocketResponse } from '../interfaces/websocket.interface';
|
||||
|
||||
const API_BASE_URL = '{network}/api/v1';
|
||||
@ -19,18 +18,18 @@ export class ApiService {
|
||||
private stateService: StateService,
|
||||
) {
|
||||
this.stateService.networkChanged$.subscribe((network) => {
|
||||
if (network === 'bisq' && !env.BISQ_SEPARATE_BACKEND) {
|
||||
if (network === 'bisq' && !this.stateService.env.BISQ_SEPARATE_BACKEND) {
|
||||
network = '';
|
||||
}
|
||||
this.apiBaseUrl = API_BASE_URL.replace('{network}', network ? '/' + network : '');
|
||||
if (!stateService.isBrowser) {
|
||||
this.apiBaseUrl = 'http://localhost:8999' + this.apiBaseUrl;
|
||||
this.apiBaseUrl = this.stateService.env.BACKEND_ABSOLUTE_URL + this.apiBaseUrl;
|
||||
}
|
||||
});
|
||||
|
||||
this.apiBaseUrl = API_BASE_URL.replace('{network}', '');
|
||||
if (!stateService.isBrowser) {
|
||||
this.apiBaseUrl = 'http://localhost:8999' + this.apiBaseUrl;
|
||||
this.apiBaseUrl = this.stateService.env.BACKEND_ABSOLUTE_URL + this.apiBaseUrl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ export class AssetsService {
|
||||
) {
|
||||
let baseApiUrl = '';
|
||||
if (!this.stateService.isBrowser) {
|
||||
baseApiUrl = 'http://localhost:4200/';
|
||||
baseApiUrl = this.stateService.env.ELECTRS_ABSOLUTE_URL;
|
||||
}
|
||||
|
||||
this.getAssetsJson$ = this.httpClient.get(baseApiUrl + '/resources/assets.json').pipe(shareReplay());
|
||||
|
@ -17,7 +17,7 @@ export class ElectrsApiService {
|
||||
private stateService: StateService,
|
||||
) {
|
||||
if (!stateService.isBrowser) {
|
||||
API_BASE_URL = 'http://localhost:4200/api';
|
||||
API_BASE_URL = this.stateService.env.ELECTRS_ABSOLUTE_URL + '/api';
|
||||
}
|
||||
this.apiBaseUrl = API_BASE_URL.replace('{network}', '');
|
||||
this.stateService.networkChanged$.subscribe((network) => {
|
||||
|
@ -4,7 +4,6 @@ import { Block, Transaction } from '../interfaces/electrs.interface';
|
||||
import { MempoolBlock, MempoolInfo, TransactionStripped } from '../interfaces/websocket.interface';
|
||||
import { OptimizedMempoolStats } from '../interfaces/node-api.interface';
|
||||
import { Router, NavigationStart } from '@angular/router';
|
||||
import { env } from '../app.constants';
|
||||
import { isPlatformBrowser } from '@angular/common';
|
||||
import { map, shareReplay } from 'rxjs/operators';
|
||||
|
||||
@ -14,16 +13,39 @@ interface MarkBlockState {
|
||||
txFeePerVSize?: number;
|
||||
}
|
||||
|
||||
export interface Env {
|
||||
TESTNET_ENABLED: boolean;
|
||||
LIQUID_ENABLED: boolean;
|
||||
BISQ_ENABLED: boolean;
|
||||
BISQ_SEPARATE_BACKEND: boolean;
|
||||
SPONSORS_ENABLED: boolean;
|
||||
ELECTRS_ITEMS_PER_PAGE: number;
|
||||
KEEP_BLOCKS_AMOUNT: number;
|
||||
BACKEND_ABSOLUTE_URL?: string;
|
||||
ELECTRS_ABSOLUTE_URL?: string;
|
||||
}
|
||||
|
||||
const defaultEnv: Env = {
|
||||
'TESTNET_ENABLED': false,
|
||||
'LIQUID_ENABLED': false,
|
||||
'BISQ_ENABLED': false,
|
||||
'BISQ_SEPARATE_BACKEND': false,
|
||||
'SPONSORS_ENABLED': false,
|
||||
'ELECTRS_ITEMS_PER_PAGE': 25,
|
||||
'KEEP_BLOCKS_AMOUNT': 8,
|
||||
};
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class StateService {
|
||||
isBrowser: boolean = isPlatformBrowser(this.platformId);
|
||||
network = '';
|
||||
env: Env;
|
||||
latestBlockHeight = 0;
|
||||
|
||||
networkChanged$ = new ReplaySubject<string>(1);
|
||||
blocks$ = new ReplaySubject<[Block, boolean]>(env.KEEP_BLOCKS_AMOUNT);
|
||||
blocks$: ReplaySubject<[Block, boolean]>;
|
||||
transactions$ = new ReplaySubject<TransactionStripped>(6);
|
||||
conversions$ = new ReplaySubject<any>(1);
|
||||
bsqPrice$ = new ReplaySubject<number>(1);
|
||||
@ -64,6 +86,13 @@ export class StateService {
|
||||
this.setNetworkBasedonUrl('/');
|
||||
this.isTabHidden$ = new BehaviorSubject(false);
|
||||
}
|
||||
|
||||
const browserWindow = window || {};
|
||||
// @ts-ignore
|
||||
const browserWindowEnv = browserWindow.__env || {};
|
||||
this.env = Object.assign(defaultEnv, browserWindowEnv);
|
||||
|
||||
this.blocks$ = new ReplaySubject<[Block, boolean]>(this.env.KEEP_BLOCKS_AMOUNT);
|
||||
}
|
||||
|
||||
setNetworkBasedonUrl(url: string) {
|
||||
|
@ -4,12 +4,9 @@ import { WebsocketResponse } from '../interfaces/websocket.interface';
|
||||
import { StateService } from './state.service';
|
||||
import { Block, Transaction } from '../interfaces/electrs.interface';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { env } from '../app.constants';
|
||||
import { ApiService } from './api.service';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
const WEB_SOCKET_PROTOCOL = 'ws:';
|
||||
const WEB_SOCKET_URL = WEB_SOCKET_PROTOCOL + '//localhost:8999{network}/api/v1/ws';
|
||||
|
||||
const OFFLINE_RETRY_AFTER_MS = 10000;
|
||||
const OFFLINE_PING_CHECK_AFTER_MS = 30000;
|
||||
@ -19,6 +16,9 @@ const EXPECT_PING_RESPONSE_AFTER_MS = 4000;
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class WebsocketService {
|
||||
private webSocketProtocol = (document.location.protocol === 'https:') ? 'wss:' : 'ws:';
|
||||
private webSocketUrl = this.webSocketProtocol + '//' + document.location.hostname + ':' + document.location.port + '{network}/api/v1/ws';
|
||||
|
||||
private websocketSubject: WebSocketSubject<WebsocketResponse>;
|
||||
private goneOffline = false;
|
||||
private lastWant: string[] | null = null;
|
||||
@ -42,12 +42,12 @@ export class WebsocketService {
|
||||
.subscribe((response) => this.handleResponse(response));
|
||||
|
||||
} else {
|
||||
this.network = this.stateService.network === 'bisq' && !env.BISQ_SEPARATE_BACKEND ? '' : this.stateService.network;
|
||||
this.websocketSubject = webSocket<WebsocketResponse>(WEB_SOCKET_URL.replace('{network}', this.network ? '/' + this.network : ''));
|
||||
this.network = this.stateService.network === 'bisq' && !this.stateService.env.BISQ_SEPARATE_BACKEND ? '' : this.stateService.network;
|
||||
this.websocketSubject = webSocket<WebsocketResponse>(this.webSocketUrl.replace('{network}', this.network ? '/' + this.network : ''));
|
||||
this.startSubscription();
|
||||
|
||||
this.stateService.networkChanged$.subscribe((network) => {
|
||||
if (network === 'bisq' && !env.BISQ_SEPARATE_BACKEND) {
|
||||
if (network === 'bisq' && !this.stateService.env.BISQ_SEPARATE_BACKEND) {
|
||||
network = '';
|
||||
}
|
||||
if (network === this.network) {
|
||||
@ -61,7 +61,9 @@ export class WebsocketService {
|
||||
|
||||
this.websocketSubject.complete();
|
||||
this.subscription.unsubscribe();
|
||||
this.websocketSubject = webSocket<WebsocketResponse>(WEB_SOCKET_URL.replace('{network}', this.network ? '/' + this.network : ''));
|
||||
this.websocketSubject = webSocket<WebsocketResponse>(
|
||||
this.webSocketUrl.replace('{network}', this.network ? '/' + this.network : '')
|
||||
);
|
||||
|
||||
this.startSubscription();
|
||||
});
|
||||
|
@ -2,13 +2,6 @@
|
||||
* Load `$localize` onto the global scope - used if i18n tags appear in Angular templates.
|
||||
*/
|
||||
|
||||
import * as domino from 'domino';
|
||||
|
||||
const win = domino.createWindow();
|
||||
// @ts-ignore
|
||||
global['window'] = win;
|
||||
global['document'] = win.document;
|
||||
|
||||
import '@angular/localize/init';
|
||||
|
||||
import { enableProdMode } from '@angular/core';
|
||||
|
Loading…
x
Reference in New Issue
Block a user