Merge pull request #4744 from mempool/mononaut/send-nodes
More status page polish
This commit is contained in:
		
						commit
						1d877a746f
					
				@ -49,4 +49,5 @@ export interface HealthCheckHost {
 | 
				
			|||||||
  outOfSync: boolean;
 | 
					  outOfSync: boolean;
 | 
				
			||||||
  unreachable: boolean;
 | 
					  unreachable: boolean;
 | 
				
			||||||
  checked: boolean;
 | 
					  checked: boolean;
 | 
				
			||||||
 | 
					  lastChecked: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,7 @@ interface FailoverHost {
 | 
				
			|||||||
  unreachable?: boolean,
 | 
					  unreachable?: boolean,
 | 
				
			||||||
  preferred?: boolean,
 | 
					  preferred?: boolean,
 | 
				
			||||||
  checked: boolean,
 | 
					  checked: boolean,
 | 
				
			||||||
 | 
					  lastChecked?: number,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class FailoverRouter {
 | 
					class FailoverRouter {
 | 
				
			||||||
@ -122,7 +123,7 @@ class FailoverRouter {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      host.checked = true;
 | 
					      host.checked = true;
 | 
				
			||||||
      
 | 
					      host.lastChecked = Date.now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // switch if the current host is out of sync or significantly slower than the next best alternative
 | 
					      // switch if the current host is out of sync or significantly slower than the next best alternative
 | 
				
			||||||
      const rankOrder = this.sortHosts();
 | 
					      const rankOrder = this.sortHosts();
 | 
				
			||||||
@ -361,6 +362,7 @@ class ElectrsApi implements AbstractBitcoinApi {
 | 
				
			|||||||
        outOfSync: !!host.outOfSync,
 | 
					        outOfSync: !!host.outOfSync,
 | 
				
			||||||
        unreachable: !!host.unreachable,
 | 
					        unreachable: !!host.unreachable,
 | 
				
			||||||
        checked: !!host.checked,
 | 
					        checked: !!host.checked,
 | 
				
			||||||
 | 
					        lastChecked: host.lastChecked || 0,
 | 
				
			||||||
      }));
 | 
					      }));
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      return [];
 | 
					      return [];
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
<footer class="footer">
 | 
					<footer class="footer" [class.inline-footer]="inline">
 | 
				
			||||||
  <div class="container-xl">
 | 
					  <div class="container-xl">
 | 
				
			||||||
    <div class="row text-center" *ngIf="mempoolInfoData$ | async as mempoolInfoData">
 | 
					    <div class="row text-center" *ngIf="mempoolInfoData$ | async as mempoolInfoData">
 | 
				
			||||||
      <div class="col d-none d-sm-block">
 | 
					      <div class="col d-none d-sm-block">
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,12 @@
 | 
				
			|||||||
  background-color: #1d1f31;
 | 
					  background-color: #1d1f31;
 | 
				
			||||||
  box-shadow: 15px 15px 15px 15px #000;
 | 
					  box-shadow: 15px 15px 15px 15px #000;
 | 
				
			||||||
  z-index: 10;
 | 
					  z-index: 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  &.inline-footer {
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    bottom: unset;
 | 
				
			||||||
 | 
					    top: -44px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.sub-text {
 | 
					.sub-text {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
 | 
					import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core';
 | 
				
			||||||
import { StateService } from '../../services/state.service';
 | 
					import { StateService } from '../../services/state.service';
 | 
				
			||||||
import { Observable, combineLatest } from 'rxjs';
 | 
					import { Observable, combineLatest } from 'rxjs';
 | 
				
			||||||
import { map } from 'rxjs/operators';
 | 
					import { map } from 'rxjs/operators';
 | 
				
			||||||
@ -23,6 +23,8 @@ interface MempoolInfoData {
 | 
				
			|||||||
  changeDetection: ChangeDetectionStrategy.OnPush,
 | 
					  changeDetection: ChangeDetectionStrategy.OnPush,
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class FooterComponent implements OnInit {
 | 
					export class FooterComponent implements OnInit {
 | 
				
			||||||
 | 
					  @Input() inline = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  mempoolBlocksData$: Observable<MempoolBlocksData>;
 | 
					  mempoolBlocksData$: Observable<MempoolBlocksData>;
 | 
				
			||||||
  mempoolInfoData$: Observable<MempoolInfoData>;
 | 
					  mempoolInfoData$: Observable<MempoolInfoData>;
 | 
				
			||||||
  vBytesPerSecondLimit = 1667;
 | 
					  vBytesPerSecondLimit = 1667;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,11 @@
 | 
				
			|||||||
<div class="tomahawk container-xl dashboard-container">
 | 
					<div class="tomahawk">
 | 
				
			||||||
  <div class="links">
 | 
					  <div class="links">
 | 
				
			||||||
    <span>Status</span>
 | 
					    <span>Monitoring</span>
 | 
				
			||||||
    <a [routerLink]='"/network"'>Live</a>
 | 
					    <a [routerLink]='"/nodes"'>Nodes</a>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
  <h1 class="dashboard-title">Node Status</h1>
 | 
					
 | 
				
			||||||
 | 
					  <app-start [showLoadingIndicator]="true"></app-start>
 | 
				
			||||||
 | 
					  <app-footer [inline]="true"></app-footer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <ng-container *ngIf="(hosts$ | async) as hosts">
 | 
					  <ng-container *ngIf="(hosts$ | async) as hosts">
 | 
				
			||||||
    <div class="status-panel">
 | 
					    <div class="status-panel">
 | 
				
			||||||
@ -13,6 +15,7 @@
 | 
				
			|||||||
            <th class="rank"></th>
 | 
					            <th class="rank"></th>
 | 
				
			||||||
            <th class="flag"></th>
 | 
					            <th class="flag"></th>
 | 
				
			||||||
            <th class="host">Host</th>
 | 
					            <th class="host">Host</th>
 | 
				
			||||||
 | 
					            <th class="updated">Last checked</th>
 | 
				
			||||||
            <th class="rtt only-small">RTT</th>
 | 
					            <th class="rtt only-small">RTT</th>
 | 
				
			||||||
            <th class="rtt only-large">RTT</th>
 | 
					            <th class="rtt only-large">RTT</th>
 | 
				
			||||||
            <th class="height">Height</th>
 | 
					            <th class="height">Height</th>
 | 
				
			||||||
@ -21,6 +24,7 @@
 | 
				
			|||||||
            <td class="rank">{{ i + 1 }}</td>
 | 
					            <td class="rank">{{ i + 1 }}</td>
 | 
				
			||||||
            <td class="flag">{{ host.active ? '⭐️' : host.flag }}</td>
 | 
					            <td class="flag">{{ host.active ? '⭐️' : host.flag }}</td>
 | 
				
			||||||
            <td class="host">{{ host.link }}</td>
 | 
					            <td class="host">{{ host.link }}</td>
 | 
				
			||||||
 | 
					            <td class="updated">{{ getLastUpdateSeconds(host) }}</td>
 | 
				
			||||||
            <td class="rtt only-small">{{ (host.rtt / 1000) | number : '1.1-1' }} {{ host.rtt == null ? '' : 's'}} {{ !host.checked ? '⏳' : (host.unreachable ? '🔥' : '✅') }}</td>
 | 
					            <td class="rtt only-small">{{ (host.rtt / 1000) | number : '1.1-1' }} {{ host.rtt == null ? '' : 's'}} {{ !host.checked ? '⏳' : (host.unreachable ? '🔥' : '✅') }}</td>
 | 
				
			||||||
            <td class="rtt only-large">{{ host.rtt | number : '1.0-0' }} {{ host.rtt == null ? '' : 'ms'}} {{ !host.checked ? '⏳' : (host.unreachable ? '🔥' : '✅') }}</td>
 | 
					            <td class="rtt only-large">{{ host.rtt | number : '1.0-0' }} {{ host.rtt == null ? '' : 'ms'}} {{ !host.checked ? '⏳' : (host.unreachable ? '🔥' : '✅') }}</td>
 | 
				
			||||||
            <td class="height">{{ host.latestHeight }} {{ !host.checked ? '⏳' : (host.outOfSync ? '🚫' : (host.latestHeight && host.latestHeight < tip ? '🟧' : '✅')) }}</td>
 | 
					            <td class="height">{{ host.latestHeight }} {{ !host.checked ? '⏳' : (host.outOfSync ? '🚫' : (host.latestHeight && host.latestHeight < tip ? '🟧' : '✅')) }}</td>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,22 +1,16 @@
 | 
				
			|||||||
.tomahawk {
 | 
					.tomahawk {
 | 
				
			||||||
  .links {
 | 
					  .links {
 | 
				
			||||||
    float: right;
 | 
					 | 
				
			||||||
    text-align: right;
 | 
					    text-align: right;
 | 
				
			||||||
    margin-top: 1em;
 | 
					    margin-inline-end: 1em;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    a, span {
 | 
					    a, span {
 | 
				
			||||||
      margin-left: 1em;
 | 
					      margin-left: 1em;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .dashboard-title {
 | 
					 | 
				
			||||||
    text-align: left;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  .status-panel {
 | 
					  .status-panel {
 | 
				
			||||||
    max-width: 720px;
 | 
					    max-width: 720px;
 | 
				
			||||||
    margin: auto;
 | 
					    margin: auto;
 | 
				
			||||||
    margin-top: 2em;
 | 
					 | 
				
			||||||
    padding: 1em;
 | 
					    padding: 1em;
 | 
				
			||||||
    background: #24273e;
 | 
					    background: #24273e;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -31,6 +25,12 @@
 | 
				
			|||||||
        width: 28px;
 | 
					        width: 28px;
 | 
				
			||||||
        text-align: right;
 | 
					        text-align: right;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      &.updated {
 | 
				
			||||||
 | 
					        display: none;
 | 
				
			||||||
 | 
					        width: 130px;
 | 
				
			||||||
 | 
					        text-align: right;
 | 
				
			||||||
 | 
					        white-space: pre-wrap;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      &.rtt, &.height {
 | 
					      &.rtt, &.height {
 | 
				
			||||||
        width: 92px;
 | 
					        width: 92px;
 | 
				
			||||||
        text-align: right;
 | 
					        text-align: right;
 | 
				
			||||||
@ -57,6 +57,9 @@
 | 
				
			|||||||
        &.rank, &.flag {
 | 
					        &.rank, &.flag {
 | 
				
			||||||
          width: 32px;
 | 
					          width: 32px;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        &.updated {
 | 
				
			||||||
 | 
					          display: table-cell;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        &.rtt, &.height {
 | 
					        &.rtt, &.height {
 | 
				
			||||||
          width: 96px;
 | 
					          width: 96px;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import { Component, OnInit, ChangeDetectionStrategy, SecurityContext } from '@angular/core';
 | 
					import { Component, OnInit, ChangeDetectionStrategy, SecurityContext, ChangeDetectorRef } from '@angular/core';
 | 
				
			||||||
import { WebsocketService } from '../../services/websocket.service';
 | 
					import { WebsocketService } from '../../services/websocket.service';
 | 
				
			||||||
import { Observable, Subject, map } from 'rxjs';
 | 
					import { Observable, Subject, map } from 'rxjs';
 | 
				
			||||||
import { StateService } from '../../services/state.service';
 | 
					import { StateService } from '../../services/state.service';
 | 
				
			||||||
@ -14,17 +14,20 @@ import { DomSanitizer } from '@angular/platform-browser';
 | 
				
			|||||||
export class ServerHealthComponent implements OnInit {
 | 
					export class ServerHealthComponent implements OnInit {
 | 
				
			||||||
  hosts$: Observable<HealthCheckHost[]>;
 | 
					  hosts$: Observable<HealthCheckHost[]>;
 | 
				
			||||||
  tip$: Subject<number>;
 | 
					  tip$: Subject<number>;
 | 
				
			||||||
 | 
					  interval: number;
 | 
				
			||||||
 | 
					  now: number = Date.now();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
    private websocketService: WebsocketService,
 | 
					    private websocketService: WebsocketService,
 | 
				
			||||||
    private stateService: StateService,
 | 
					    private stateService: StateService,
 | 
				
			||||||
 | 
					    private cd: ChangeDetectorRef,
 | 
				
			||||||
    public sanitizer: DomSanitizer,
 | 
					    public sanitizer: DomSanitizer,
 | 
				
			||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ngOnInit(): void {
 | 
					  ngOnInit(): void {
 | 
				
			||||||
    this.hosts$ = this.stateService.serverHealth$.pipe(
 | 
					    this.hosts$ = this.stateService.serverHealth$.pipe(
 | 
				
			||||||
      map((hosts) => {
 | 
					      map((hosts) => {
 | 
				
			||||||
        const subpath = window.location.pathname.slice(0, -6);
 | 
					        const subpath = window.location.pathname.slice(0, -11);
 | 
				
			||||||
        for (const host of hosts) {
 | 
					        for (const host of hosts) {
 | 
				
			||||||
          let statusUrl = '';
 | 
					          let statusUrl = '';
 | 
				
			||||||
          let linkHost = '';
 | 
					          let linkHost = '';
 | 
				
			||||||
@ -44,13 +47,27 @@ export class ServerHealthComponent implements OnInit {
 | 
				
			|||||||
      })
 | 
					      })
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    this.tip$ = this.stateService.chainTip$;
 | 
					    this.tip$ = this.stateService.chainTip$;
 | 
				
			||||||
    this.websocketService.want(['blocks', 'tomahawk']);
 | 
					    this.websocketService.want(['mempool-blocks', 'stats', 'blocks', 'tomahawk']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.interval = window.setInterval(() => {
 | 
				
			||||||
 | 
					      this.now = Date.now();
 | 
				
			||||||
 | 
					      this.cd.markForCheck();
 | 
				
			||||||
 | 
					    }, 1000);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  trackByFn(index: number, host: HealthCheckHost): string {
 | 
					  trackByFn(index: number, host: HealthCheckHost): string {
 | 
				
			||||||
    return host.host;
 | 
					    return host.host;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getLastUpdateSeconds(host: HealthCheckHost): string {
 | 
				
			||||||
 | 
					    if (host.lastChecked) {
 | 
				
			||||||
 | 
					      const seconds = Math.ceil((this.now - host.lastChecked) / 1000);
 | 
				
			||||||
 | 
					      return `${seconds} second${seconds > 1 ? 's' : '  '} ago`;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      return '~';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private parseFlag(host: string): string {
 | 
					  private parseFlag(host: string): string {
 | 
				
			||||||
    if (host.includes('.fra.')) {
 | 
					    if (host.includes('.fra.')) {
 | 
				
			||||||
      return '🇩🇪';
 | 
					      return '🇩🇪';
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,12 @@
 | 
				
			|||||||
<div class="tomahawk">
 | 
					<div class="tomahawk">
 | 
				
			||||||
  <div class="container-xl dashboard-container">
 | 
					  <div class="links">
 | 
				
			||||||
    <div class="links">
 | 
					    <a [routerLink]='"/monitoring"'>Monitoring</a>
 | 
				
			||||||
      <a [routerLink]='"/nodes"'>Status</a>
 | 
					    <span>Nodes</span>
 | 
				
			||||||
      <span>Live</span>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
    <h1 class="dashboard-title">Live Network</h1>
 | 
					 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <app-start [showLoadingIndicator]="true"></app-start>
 | 
				
			||||||
 | 
					  <app-footer [inline]="true"></app-footer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <ng-container *ngFor="let host of hosts; trackBy: trackByFn">
 | 
					  <ng-container *ngFor="let host of hosts; trackBy: trackByFn">
 | 
				
			||||||
    <h5 [id]="host.host" class="hostLink">
 | 
					    <h5 [id]="host.host" class="hostLink">
 | 
				
			||||||
      <a [href]="'https://' + host.link">{{ host.link }}</a>
 | 
					      <a [href]="'https://' + host.link">{{ host.link }}</a>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,21 +1,17 @@
 | 
				
			|||||||
.tomahawk {
 | 
					.tomahawk {
 | 
				
			||||||
  .links {
 | 
					  .links {
 | 
				
			||||||
    float: right;
 | 
					 | 
				
			||||||
    text-align: right;
 | 
					    text-align: right;
 | 
				
			||||||
    margin-top: 1em;
 | 
					    margin-inline-end: 1em;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    a, span {
 | 
					    a, span {
 | 
				
			||||||
      margin-left: 1em;
 | 
					      margin-left: 1em;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .dashboard-title {
 | 
					 | 
				
			||||||
    text-align: left;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  .mempoolStatus {
 | 
					  .mempoolStatus {
 | 
				
			||||||
    width: 100%;
 | 
					    width: 100%;
 | 
				
			||||||
    height: 270px;
 | 
					    height: 270px;
 | 
				
			||||||
 | 
					    border: none;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .hostLink {
 | 
					  .hostLink {
 | 
				
			||||||
 | 
				
			|||||||
@ -26,7 +26,7 @@ export class ServerStatusComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
  ngOnInit(): void {
 | 
					  ngOnInit(): void {
 | 
				
			||||||
    this.hostSubscription = this.stateService.serverHealth$.pipe(
 | 
					    this.hostSubscription = this.stateService.serverHealth$.pipe(
 | 
				
			||||||
      map((hosts) => {
 | 
					      map((hosts) => {
 | 
				
			||||||
        const subpath = window.location.pathname.slice(0, -8);
 | 
					        const subpath = window.location.pathname.slice(0, -6);
 | 
				
			||||||
        for (const host of hosts) {
 | 
					        for (const host of hosts) {
 | 
				
			||||||
          let statusUrl = '';
 | 
					          let statusUrl = '';
 | 
				
			||||||
          let linkHost = '';
 | 
					          let linkHost = '';
 | 
				
			||||||
@ -66,7 +66,7 @@ export class ServerStatusComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
      })
 | 
					      })
 | 
				
			||||||
    ).subscribe();
 | 
					    ).subscribe();
 | 
				
			||||||
    this.tip$ = this.stateService.chainTip$;
 | 
					    this.tip$ = this.stateService.chainTip$;
 | 
				
			||||||
    this.websocketService.want(['blocks', 'tomahawk']);
 | 
					    this.websocketService.want(['mempool-blocks', 'stats', 'blocks', 'tomahawk']);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  trackByFn(index: number, host: HealthCheckHost): string {
 | 
					  trackByFn(index: number, host: HealthCheckHost): string {
 | 
				
			||||||
 | 
				
			|||||||
@ -132,6 +132,7 @@ export interface HealthCheckHost {
 | 
				
			|||||||
  outOfSync: boolean;
 | 
					  outOfSync: boolean;
 | 
				
			||||||
  unreachable: boolean;
 | 
					  unreachable: boolean;
 | 
				
			||||||
  checked: boolean;
 | 
					  checked: boolean;
 | 
				
			||||||
 | 
					  lastChecked: number;
 | 
				
			||||||
  link?: string;
 | 
					  link?: string;
 | 
				
			||||||
  statusPage?: SafeResourceUrl;
 | 
					  statusPage?: SafeResourceUrl;
 | 
				
			||||||
  flag?: string;
 | 
					  flag?: string;
 | 
				
			||||||
 | 
				
			|||||||
@ -101,12 +101,12 @@ const routes: Routes = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
if (window['__env']?.OFFICIAL_MEMPOOL_SPACE) {
 | 
					if (window['__env']?.OFFICIAL_MEMPOOL_SPACE) {
 | 
				
			||||||
  routes[0].children.push({
 | 
					  routes[0].children.push({
 | 
				
			||||||
    path: 'nodes',
 | 
					    path: 'monitoring',
 | 
				
			||||||
    data: { networks: ['bitcoin', 'liquid'] },
 | 
					    data: { networks: ['bitcoin', 'liquid'] },
 | 
				
			||||||
    component: ServerHealthComponent
 | 
					    component: ServerHealthComponent
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  routes[0].children.push({
 | 
					  routes[0].children.push({
 | 
				
			||||||
    path: 'network',
 | 
					    path: 'nodes',
 | 
				
			||||||
    data: { networks: ['bitcoin', 'liquid'] },
 | 
					    data: { networks: ['bitcoin', 'liquid'] },
 | 
				
			||||||
    component: ServerStatusComponent
 | 
					    component: ServerStatusComponent
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user