@@ -1,2 +1,2 @@
|
||||
<span *ngIf="multisig" class="badge badge-pill badge-warning">multisig {{ multisigM }} of {{ multisigN }}</span>
|
||||
<span *ngIf="lnChannelClose" class="badge badge-pill badge-warning">Lightning Channel Force Close</span>
|
||||
<span *ngIf="secondLayerClose" class="badge badge-pill badge-warning">Layer2 Peg-out</span>
|
||||
|
||||
@@ -16,7 +16,7 @@ export class AddressLabelsComponent implements OnInit {
|
||||
multisigM: number;
|
||||
multisigN: number;
|
||||
|
||||
lnChannelClose = false;
|
||||
secondLayerClose = false;
|
||||
|
||||
constructor() { }
|
||||
|
||||
@@ -33,12 +33,16 @@ export class AddressLabelsComponent implements OnInit {
|
||||
if (this.vin.inner_witnessscript_asm.indexOf('OP_CHECKMULTISIG') > -1) {
|
||||
const matches = this.getMatches(this.vin.inner_witnessscript_asm, /OP_PUSHNUM_([0-9])/g, 1);
|
||||
this.multisig = true;
|
||||
this.multisigM = matches[0];
|
||||
this.multisigN = matches[1];
|
||||
this.multisigM = parseInt(matches[0], 10);
|
||||
this.multisigN = parseInt(matches[1], 10);
|
||||
|
||||
if (this.multisigM === 1 && this.multisigN === 1) {
|
||||
this.multisig = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (/OP_IF (.+) OP_ELSE (.+) OP_CSV OP_DROP/.test(this.vin.inner_witnessscript_asm)) {
|
||||
this.lnChannelClose = true;
|
||||
this.secondLayerClose = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="container-xl">
|
||||
<h1 style="float: left;">Address</h1>
|
||||
<a [routerLink]="['/address/', addressString]" style="line-height: 56px; margin-left: 10px;">
|
||||
<a [routerLink]="['/address/' | relativeUrl, addressString]" style="line-height: 56px; margin-left: 10px;">
|
||||
<span class="d-inline d-lg-none">{{ addressString | shortenString : 24 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ addressString }}</span>
|
||||
</a>
|
||||
|
||||
@@ -9,7 +9,6 @@ import { AudioService } from 'src/app/services/audio.service';
|
||||
import { ApiService } from 'src/app/services/api.service';
|
||||
import { of, merge, Subscription } from 'rxjs';
|
||||
import { SeoService } from 'src/app/services/seo.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-address',
|
||||
@@ -17,7 +16,7 @@ import { environment } from 'src/environments/environment';
|
||||
styleUrls: ['./address.component.scss']
|
||||
})
|
||||
export class AddressComponent implements OnInit, OnDestroy {
|
||||
network = environment.network;
|
||||
network = '';
|
||||
|
||||
address: Address;
|
||||
addressString: string;
|
||||
@@ -48,6 +47,7 @@ export class AddressComponent implements OnInit, OnDestroy {
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||
this.websocketService.want(['blocks', 'stats', 'mempool-blocks']);
|
||||
|
||||
this.mainSubscription = this.route.paramMap
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
Confidential
|
||||
</ng-template>
|
||||
<ng-template #default>
|
||||
{{ satoshis / 100000000 | number : '1.8-8' }} <ng-template [ngIf]="network === 'liquid'">L-</ng-template>BTC
|
||||
{{ satoshis / 100000000 | number : digitsInfo }} <ng-template [ngIf]="network === 'liquid'">L-BTC</ng-template>
|
||||
<ng-template [ngIf]="network === 'testnet'">tBTC</ng-template>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, OnInit, Input, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { StateService } from '../../services/state.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { environment } from '../../../environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-amount',
|
||||
@@ -12,9 +11,10 @@ import { environment } from '../../../environments/environment';
|
||||
export class AmountComponent implements OnInit {
|
||||
conversions$: Observable<any>;
|
||||
viewFiat$: Observable<boolean>;
|
||||
network = environment.network;
|
||||
network = '';
|
||||
|
||||
@Input() satoshis: number;
|
||||
@Input() digitsInfo = '1.8-8';
|
||||
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
@@ -23,6 +23,7 @@ export class AmountComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
this.viewFiat$ = this.stateService.viewFiat$.asObservable();
|
||||
this.conversions$ = this.stateService.conversions$.asObservable();
|
||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,41 +1,18 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, NavigationEnd } from '@angular/router';
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { WebsocketService } from '../../services/websocket.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
export class AppComponent implements OnInit {
|
||||
network = environment.network;
|
||||
export class AppComponent {
|
||||
network = '';
|
||||
link: HTMLLinkElement;
|
||||
|
||||
constructor(
|
||||
public router: Router,
|
||||
private websocketService: WebsocketService,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.router.events.subscribe((val) => {
|
||||
if (val instanceof NavigationEnd) {
|
||||
if (this.network === 'liquid' || this.network === 'testnet') {
|
||||
this.updateCanonicalUrlElement('https://' + this.network + '.mempool.ninja' + location.pathname);
|
||||
} else {
|
||||
this.updateCanonicalUrlElement('https://mempool.space' + location.pathname);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateCanonicalUrlElement(url) {
|
||||
if (!this.link) {
|
||||
this.link = window.document.createElement('link');
|
||||
this.link.setAttribute('rel', 'canonical');
|
||||
window.document.head.appendChild(this.link);
|
||||
}
|
||||
this.link.setAttribute('href', url);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="container-xl">
|
||||
<h1 style="float: left;">Asset</h1>
|
||||
<a [routerLink]="['/asset/', assetString]" style="line-height: 56px; margin-left: 10px;">
|
||||
<a [routerLink]="['/asset/' | relativeUrl, assetString]" style="line-height: 56px; margin-left: 10px;">
|
||||
<span class="d-inline d-lg-none">{{ assetString | shortenString : 24 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ assetString }}</span>
|
||||
</a>
|
||||
@@ -30,7 +30,7 @@
|
||||
</tr>
|
||||
<tr *ngIf="!isNativeAsset">
|
||||
<td>Issuance tx</td>
|
||||
<td><a [routerLink]="['/tx/', asset.issuance_txin.txid]">{{ asset.issuance_txin.txid | shortenString : 13 }}</a> <app-clipboard class="d-none d-sm-inline-block" [text]="asset.issuance_txin.txid"></app-clipboard></td>
|
||||
<td><a [routerLink]="['/tx/' | relativeUrl, asset.issuance_txin.txid]">{{ asset.issuance_txin.txid | shortenString : 13 }}</a> <app-clipboard class="d-none d-sm-inline-block" [text]="asset.issuance_txin.txid"></app-clipboard></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -18,7 +18,7 @@ import { AssetsService } from 'src/app/services/assets.service';
|
||||
styleUrls: ['./asset.component.scss']
|
||||
})
|
||||
export class AssetComponent implements OnInit, OnDestroy {
|
||||
network = environment.network;
|
||||
network = '';
|
||||
nativeAssetId = environment.nativeAssetId;
|
||||
|
||||
asset: Asset;
|
||||
@@ -54,6 +54,7 @@ export class AssetComponent implements OnInit, OnDestroy {
|
||||
|
||||
ngOnInit() {
|
||||
this.websocketService.want(['blocks', 'stats', 'mempool-blocks']);
|
||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||
|
||||
this.mainSubscription = this.route.paramMap
|
||||
.pipe(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="container-xl">
|
||||
|
||||
<div class="title-block">
|
||||
<h1>Block <ng-template [ngIf]="blockHeight"><a [routerLink]="['/block/', blockHash]">{{ blockHeight }}</a></ng-template></h1>
|
||||
<h1>Block <ng-template [ngIf]="blockHeight"><a [routerLink]="['/block/' | relativeUrl, blockHash]">{{ blockHeight }}</a></ng-template></h1>
|
||||
</div>
|
||||
|
||||
<ng-template [ngIf]="!isLoadingBlock && !error">
|
||||
@@ -40,7 +40,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-width">Hash</td>
|
||||
<td><a [routerLink]="['/block/', block.id]" title="{{ block.id }}">{{ block.id | shortenString : 13 }}</a> <app-clipboard class="d-none d-sm-inline-block" [text]="block.id"></app-clipboard></td>
|
||||
<td><a [routerLink]="['/block/' | relativeUrl, block.id]" title="{{ block.id }}">{{ block.id | shortenString : 13 }}</a> <app-clipboard class="d-none d-sm-inline-block" [text]="block.id"></app-clipboard></td>
|
||||
</tr>
|
||||
<tr *ngIf="block.medianFee !== undefined">
|
||||
<td>Median fee</td>
|
||||
@@ -49,12 +49,12 @@
|
||||
<ng-template [ngIf]="fees !== undefined" [ngIfElse]="loadingFees">
|
||||
<tr>
|
||||
<td>Total fees</td>
|
||||
<td><span title="{{ fees | number: '1.2-8' }} BTC">{{ fees | number: '1.2-2' }} <ng-template [ngIf]="network === 'liquid'">L-</ng-template>BTC</span> (<app-fiat [value]="fees * 100000000" digitsInfo="1.0-0"></app-fiat>)</td>
|
||||
<td><app-amount [satoshis]="fees * 100000000" digitsInfo="1.2-8"></app-amount> (<app-fiat [value]="fees * 100000000" digitsInfo="1.0-0"></app-fiat>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Reward + fees:</td>
|
||||
<td>
|
||||
<span title="{{ blockSubsidy + fees | number: '1.2-8' }} BTC">{{ blockSubsidy + fees | number: '1.2-2' }} <ng-template [ngIf]="network === 'liquid'">L-</ng-template>BTC</span> (<app-fiat [value]="(blockSubsidy + fees) * 100000000" digitsInfo="1.0-0"></app-fiat>)
|
||||
<app-amount [satoshis]="(blockSubsidy + fees) * 100000000" digitsInfo="1.2-8"></app-amount> (<app-fiat [value]="(blockSubsidy + fees) * 100000000" digitsInfo="1.0-0"></app-fiat>)
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
|
||||
@@ -6,7 +6,6 @@ import { Block, Transaction, Vout } from '../../interfaces/electrs.interface';
|
||||
import { of } from 'rxjs';
|
||||
import { StateService } from '../../services/state.service';
|
||||
import { SeoService } from 'src/app/services/seo.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-block',
|
||||
@@ -14,7 +13,7 @@ import { environment } from 'src/environments/environment';
|
||||
styleUrls: ['./block.component.scss']
|
||||
})
|
||||
export class BlockComponent implements OnInit, OnDestroy {
|
||||
network = environment.network;
|
||||
network = '';
|
||||
block: Block;
|
||||
blockHeight: number;
|
||||
blockHash: string;
|
||||
@@ -92,6 +91,9 @@ export class BlockComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.stateService.blocks$
|
||||
.subscribe((block) => this.latestBlock = block);
|
||||
|
||||
this.stateService.networkChanged$
|
||||
.subscribe((network) => this.network = network);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<div class="blocks-container" *ngIf="blocks.length">
|
||||
<div *ngFor="let block of blocks; let i = index; trackBy: trackByBlocksFn" >
|
||||
<div class="text-center bitcoin-block mined-block" [class.blink-bg]="block.height % 210000 === 0" id="bitcoin-block-{{ block.height }}" [ngStyle]="getStyleForBlock(block)">
|
||||
<a [routerLink]="['/block/', block.id]" [state]="{ data: { block: block } }" class="blockLink"> </a>
|
||||
<a [routerLink]="['/block/' | relativeUrl, block.id]" [state]="{ data: { block: block } }" class="blockLink"> </a>
|
||||
<div class="block-height">
|
||||
<a [routerLink]="['/block/', block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a>
|
||||
<a [routerLink]="['/block/' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a>
|
||||
</div>
|
||||
<div class="block-body">
|
||||
<div class="fees">
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<div class="text-center" class="blockchain-wrapper">
|
||||
<div class="position-container">
|
||||
<app-mempool-blocks></app-mempool-blocks>
|
||||
<app-blockchain-blocks></app-blockchain-blocks>
|
||||
|
||||
<div id="divider" *ngIf="!isLoading; else loadingTmpl"></div>
|
||||
<span [hidden]="isLoading">
|
||||
<app-mempool-blocks></app-mempool-blocks>
|
||||
<app-blockchain-blocks></app-blockchain-blocks>
|
||||
<div id="divider"></div>
|
||||
</span>
|
||||
|
||||
<ng-template #loadingTmpl>
|
||||
<ng-template [ngIf]="isLoading">
|
||||
<div class="loading-block">
|
||||
<h3>Waiting for blocks...</h3>
|
||||
<br>
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { StateService } from 'src/app/services/state.service';
|
||||
|
||||
@Component({
|
||||
@@ -8,9 +6,7 @@ import { StateService } from 'src/app/services/state.service';
|
||||
templateUrl: './blockchain.component.html',
|
||||
styleUrls: ['./blockchain.component.scss']
|
||||
})
|
||||
export class BlockchainComponent implements OnInit, OnDestroy {
|
||||
blocksSubscription: Subscription;
|
||||
|
||||
export class BlockchainComponent implements OnInit {
|
||||
txTrackingLoading = false;
|
||||
txShowTxNotFound = false;
|
||||
isLoading = true;
|
||||
@@ -20,14 +16,7 @@ export class BlockchainComponent implements OnInit, OnDestroy {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.blocksSubscription = this.stateService.blocks$
|
||||
.pipe(
|
||||
take(1)
|
||||
)
|
||||
.subscribe(() => this.isLoading = false);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.blocksSubscription.unsubscribe();
|
||||
this.stateService.blocks$.subscribe(() => this.isLoading = false);
|
||||
this.stateService.networkChanged$.subscribe(() => this.isLoading = true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
<div class="text-center pb-1" *ngIf="network === 'mempool' && latestBlockHeight && latestBlockHeight < 630000">
|
||||
<div class="text-center pb-1" *ngIf="network === '' && latestBlockHeight && latestBlockHeight < 630000">
|
||||
<h3>Quantitative Hardening in {{ 630000 - latestBlockHeight }} blocks (~<app-timespan [time]="(630000 - latestBlockHeight) * 10 * 60"></app-timespan>)</h3>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock">
|
||||
<td><a [routerLink]="['/block', block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a></td>
|
||||
<td><a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a></td>
|
||||
<td class="d-none d-md-block">{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }}</td>
|
||||
<td><app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since> ago</td>
|
||||
<td class="d-none d-lg-block">{{ block.tx_count | number }}</td>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { StateService } from '../../services/state.service';
|
||||
import { Block } from '../../interfaces/electrs.interface';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { SeoService } from 'src/app/services/seo.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-latest-blocks',
|
||||
@@ -12,7 +11,7 @@ import { environment } from 'src/environments/environment';
|
||||
styleUrls: ['./latest-blocks.component.scss'],
|
||||
})
|
||||
export class LatestBlocksComponent implements OnInit, OnDestroy {
|
||||
network = environment.network;
|
||||
network = '';
|
||||
|
||||
blocks: any[] = [];
|
||||
blockSubscription: Subscription;
|
||||
@@ -32,6 +31,7 @@ export class LatestBlocksComponent implements OnInit, OnDestroy {
|
||||
|
||||
ngOnInit() {
|
||||
this.seoService.resetTitle();
|
||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||
|
||||
this.blockSubscription = this.stateService.blocks$
|
||||
.subscribe((block) => {
|
||||
|
||||
@@ -5,27 +5,38 @@
|
||||
<div class="badge badge-warning connection-badge" *ngIf="connectionState === 0">Offline</div>
|
||||
<div class="badge badge-warning connection-badge" style="left: 30px;" *ngIf="connectionState === 1">Reconnecting...</div>
|
||||
</a>
|
||||
|
||||
|
||||
<div class="btn-group" style="margin-right: 16px;">
|
||||
<button type="button" (click)="networkDropdownHidden = !networkDropdownHidden" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</button>
|
||||
<div class="dropdown-menu" [class.d-block]="!networkDropdownHidden">
|
||||
<a class="dropdown-item" routerLink="/">Mainnet</a>
|
||||
<a class="dropdown-item" routerLink="/liquid">Liquid</a>
|
||||
<a class="dropdown-item" routerLink="/testnet">Testnet</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="navbar-toggler" type="button" (click)="collapse()" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="navbar-collapse collapse" id="navbarCollapse" [ngClass]="{'show': navCollapsed}">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<ul class="navbar-nav mr-auto {{ network }}">
|
||||
<li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">
|
||||
<a class="nav-link" routerLink="/" (click)="collapse()">Blockchain</a>
|
||||
<a class="nav-link" [routerLink]="['/' | relativeUrl]" (click)="collapse()">Blockchain</a>
|
||||
</li>
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" routerLink="/graphs" (click)="collapse()">Graphs</a>
|
||||
<a class="nav-link" [routerLink]="['/graphs' | relativeUrl]" (click)="collapse()">Graphs</a>
|
||||
</li>
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" routerLink="/tv" (click)="collapse()">TV view <img src="./resources/expand.png" width="15"/></a>
|
||||
<a class="nav-link" [routerLink]="[tvViewRoute]" (click)="collapse()">TV view <img src="./resources/expand.png" width="15"/></a>
|
||||
</li>
|
||||
<li *ngIf="network === 'liquid'" class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" routerLink="/assets" (click)="collapse()">Assets</a>
|
||||
<a class="nav-link" [routerLink]="['/assets' | relativeUrl]" (click)="collapse()">Assets</a>
|
||||
</li>
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" routerLink="/contributors" (click)="collapse()">Contributors</a>
|
||||
<a class="nav-link" [routerLink]="['/contributors' | relativeUrl]" (click)="collapse()">Contributors</a>
|
||||
</li>
|
||||
</ul>
|
||||
<app-search-form location="top" (searchTriggered)="collapse()"></app-search-form>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, OnInit, HostListener } from '@angular/core';
|
||||
import { StateService } from '../../services/state.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-master-page',
|
||||
@@ -8,20 +7,43 @@ import { environment } from 'src/environments/environment';
|
||||
styleUrls: ['./master-page.component.scss']
|
||||
})
|
||||
export class MasterPageComponent implements OnInit {
|
||||
network = environment.network;
|
||||
network = '';
|
||||
tvViewRoute = '/tv';
|
||||
|
||||
navCollapsed = false;
|
||||
connectionState = 2;
|
||||
|
||||
networkDropdownHidden = true;
|
||||
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
) { }
|
||||
|
||||
@HostListener('document:click', ['$event'])
|
||||
documentClick(event: any): void {
|
||||
if (!event.target.classList.contains('dropdown-toggle')) {
|
||||
this.networkDropdownHidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.stateService.connectionState$
|
||||
.subscribe((state) => {
|
||||
this.connectionState = state;
|
||||
});
|
||||
|
||||
this.stateService.networkChanged$
|
||||
.subscribe((network) => {
|
||||
this.network = network;
|
||||
|
||||
if (network === 'testnet') {
|
||||
this.tvViewRoute = '/testnet-tv';
|
||||
} else if (network === 'liquid') {
|
||||
this.tvViewRoute = '/liquid-tv';
|
||||
} else {
|
||||
this.tvViewRoute = '/tv';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
collapse(): void {
|
||||
|
||||
@@ -5,7 +5,6 @@ import { switchMap, map, tap } from 'rxjs/operators';
|
||||
import { MempoolBlock } from 'src/app/interfaces/websocket.interface';
|
||||
import { Observable } from 'rxjs';
|
||||
import { SeoService } from 'src/app/services/seo.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-mempool-block',
|
||||
@@ -13,7 +12,7 @@ import { environment } from 'src/environments/environment';
|
||||
styleUrls: ['./mempool-block.component.scss']
|
||||
})
|
||||
export class MempoolBlockComponent implements OnInit, OnDestroy {
|
||||
network = environment.network;
|
||||
network = '';
|
||||
mempoolBlockIndex: number;
|
||||
mempoolBlock$: Observable<MempoolBlock>;
|
||||
|
||||
@@ -43,6 +42,9 @@ export class MempoolBlockComponent implements OnInit, OnDestroy {
|
||||
this.stateService.markBlock$.next({ mempoolBlockIndex: this.mempoolBlockIndex });
|
||||
})
|
||||
);
|
||||
|
||||
this.stateService.networkChanged$
|
||||
.subscribe((network) => this.network = network);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="flashing">
|
||||
<div *ngFor="let projectedBlock of mempoolBlocks; let i = index; trackBy: trackByFn">
|
||||
<div class="bitcoin-block text-center mempool-block" id="mempool-block-{{ i }}" [ngStyle]="getStyleForMempoolBlockAtIndex(i)">
|
||||
<a [routerLink]="['/mempool-block/', i]" class="blockLink"> </a>
|
||||
<a [routerLink]="['/mempool-block/' | relativeUrl, i]" class="blockLink"> </a>
|
||||
<div class="block-body" *ngIf="mempoolBlocks?.length">
|
||||
<div class="fees">
|
||||
<span class="yellow-color">~{{ projectedBlock.medianFee | number:'1.0-0' }} sat/vB</span>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { MempoolBlock } from 'src/app/interfaces/websocket.interface';
|
||||
import { StateService } from 'src/app/services/state.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { environment } from '../../../environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-mempool-blocks',
|
||||
templateUrl: './mempool-blocks.component.html',
|
||||
@@ -14,7 +14,7 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
||||
mempoolBlocks: MempoolBlock[];
|
||||
mempoolBlocksFull: MempoolBlock[];
|
||||
mempoolBlocksSubscription: Subscription;
|
||||
network = environment.network;
|
||||
network = '';
|
||||
|
||||
blockWidth = 125;
|
||||
blockPadding = 30;
|
||||
@@ -54,6 +54,9 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
this.calculateTransactionPosition();
|
||||
});
|
||||
|
||||
this.stateService.networkChanged$
|
||||
.subscribe((network) => this.network = network);
|
||||
}
|
||||
|
||||
@HostListener('window:resize', ['$event'])
|
||||
|
||||
@@ -2,8 +2,8 @@ import { Component, OnInit, Input, Inject, LOCALE_ID, ChangeDetectionStrategy, O
|
||||
import { formatDate } from '@angular/common';
|
||||
import { VbytesPipe } from 'src/app/pipes/bytes-pipe/vbytes.pipe';
|
||||
import * as Chartist from 'chartist';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { OptimizedMempoolStats } from 'src/app/interfaces/node-api.interface';
|
||||
import { StateService } from 'src/app/services/state.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-mempool-graph',
|
||||
@@ -13,16 +13,18 @@ import { OptimizedMempoolStats } from 'src/app/interfaces/node-api.interface';
|
||||
export class MempoolGraphComponent implements OnInit, OnChanges {
|
||||
@Input() data;
|
||||
|
||||
network = environment.network;
|
||||
network = '';
|
||||
mempoolVsizeFeesOptions: any;
|
||||
mempoolVsizeFeesData: any;
|
||||
|
||||
constructor(
|
||||
private vbytesPipe: VbytesPipe,
|
||||
private stateService: StateService,
|
||||
@Inject(LOCALE_ID) private locale: string,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||
const labelInterpolationFnc = (value: any, index: any) => {
|
||||
return index % 6 === 0 ? formatDate(value, 'HH:mm', this.locale) : null;
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { AssetsService } from 'src/app/services/assets.service';
|
||||
import { StateService } from 'src/app/services/state.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-search-form',
|
||||
@@ -11,7 +11,7 @@ import { AssetsService } from 'src/app/services/assets.service';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class SearchFormComponent implements OnInit {
|
||||
network = environment.network;
|
||||
network = '';
|
||||
assets: object;
|
||||
|
||||
searchForm: FormGroup;
|
||||
@@ -25,9 +25,12 @@ export class SearchFormComponent implements OnInit {
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router,
|
||||
private assetsService: AssetsService,
|
||||
private stateService: StateService,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||
|
||||
this.searchForm = this.formBuilder.group({
|
||||
searchText: ['', Validators.required],
|
||||
});
|
||||
@@ -43,16 +46,16 @@ export class SearchFormComponent implements OnInit {
|
||||
const searchText = this.searchForm.value.searchText.trim();
|
||||
if (searchText) {
|
||||
if (this.regexAddress.test(searchText)) {
|
||||
this.router.navigate(['/address/', searchText]);
|
||||
this.router.navigate([(this.network ? '/' + this.network : '') + '/address/', searchText]);
|
||||
this.searchTriggered.emit();
|
||||
} else if (this.regexBlockhash.test(searchText)) {
|
||||
this.router.navigate(['/block/', searchText]);
|
||||
this.router.navigate([(this.network ? '/' + this.network : '') + '/block/', searchText]);
|
||||
this.searchTriggered.emit();
|
||||
} else if (this.regexTransaction.test(searchText)) {
|
||||
if (this.network === 'liquid' && this.assets[searchText]) {
|
||||
this.router.navigate(['/asset/', searchText]);
|
||||
this.router.navigate([(this.network ? '/' + this.network : '') + '/asset/', searchText]);
|
||||
} else {
|
||||
this.router.navigate(['/tx/', searchText]);
|
||||
this.router.navigate([(this.network ? '/' + this.network : '') + '/tx/', searchText]);
|
||||
}
|
||||
this.searchTriggered.emit();
|
||||
} else {
|
||||
|
||||
@@ -19,25 +19,25 @@
|
||||
<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">
|
||||
<input ngbButton type="radio" [value]="'2h'" [routerLink]="['/graphs']" fragment="2h"> 2H (LIVE)
|
||||
<input ngbButton type="radio" [value]="'2h'" [routerLink]="['/graphs' | relativeUrl]" fragment="2h"> 2H (LIVE)
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'24h'" [routerLink]="['/graphs']" fragment="24h"> 24H
|
||||
<input ngbButton type="radio" [value]="'24h'" [routerLink]="['/graphs' | relativeUrl]" fragment="24h"> 24H
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'1w'" [routerLink]="['/graphs']" fragment="1w"> 1W
|
||||
<input ngbButton type="radio" [value]="'1w'" [routerLink]="['/graphs' | relativeUrl]" fragment="1w"> 1W
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'1m'" [routerLink]="['/graphs']" fragment="1m"> 1M
|
||||
<input ngbButton type="radio" [value]="'1m'" [routerLink]="['/graphs' | relativeUrl]" fragment="1m"> 1M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'3m'" [routerLink]="['/graphs']" fragment="3m"> 3M
|
||||
<input ngbButton type="radio" [value]="'3m'" [routerLink]="['/graphs' | relativeUrl]" fragment="3m"> 3M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'6m'" [routerLink]="['/graphs']" fragment="6m"> 6M
|
||||
<input ngbButton type="radio" [value]="'6m'" [routerLink]="['/graphs' | relativeUrl]" fragment="6m"> 6M
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'1y'" [routerLink]="['/graphs']" fragment="1y"> 1Y
|
||||
<input ngbButton type="radio" [value]="'1y'" [routerLink]="['/graphs' | relativeUrl]" fragment="1y"> 1Y
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -12,7 +12,6 @@ import { ApiService } from '../../services/api.service';
|
||||
import * as Chartist from 'chartist';
|
||||
import { StateService } from 'src/app/services/state.service';
|
||||
import { SeoService } from 'src/app/services/seo.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-statistics',
|
||||
@@ -20,7 +19,7 @@ import { environment } from 'src/environments/environment';
|
||||
styleUrls: ['./statistics.component.scss']
|
||||
})
|
||||
export class StatisticsComponent implements OnInit {
|
||||
network = environment.network;
|
||||
network = '';
|
||||
|
||||
loading = true;
|
||||
spinnerLoading = false;
|
||||
@@ -52,6 +51,8 @@ export class StatisticsComponent implements OnInit {
|
||||
|
||||
ngOnInit() {
|
||||
this.seoService.setTitle('Graphs');
|
||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||
|
||||
const labelInterpolationFnc = (value: any, index: any) => {
|
||||
const nr = 6;
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import { OptimizedMempoolStats } from '../../interfaces/node-api.interface';
|
||||
import { StateService } from 'src/app/services/state.service';
|
||||
import { ApiService } from 'src/app/services/api.service';
|
||||
import { SeoService } from 'src/app/services/seo.service';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-television',
|
||||
@@ -13,7 +12,6 @@ import { environment } from 'src/environments/environment';
|
||||
})
|
||||
export class TelevisionComponent implements OnInit {
|
||||
loading = true;
|
||||
network = environment.network;
|
||||
|
||||
mempoolStats: OptimizedMempoolStats[] = [];
|
||||
mempoolVsizeFeesData: any;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</ng-template>
|
||||
|
||||
<div>
|
||||
<a [routerLink]="['/tx/', txId]" style="line-height: 56px;">
|
||||
<a [routerLink]="['/tx/' | relativeUrl, txId]" style="line-height: 56px;">
|
||||
<span class="d-inline d-lg-none">{{ txId | shortenString : 24 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ txId }}</span>
|
||||
</a>
|
||||
@@ -33,7 +33,7 @@
|
||||
<tr>
|
||||
<td class="td-width">Included in block</td>
|
||||
<td>
|
||||
<a [routerLink]="['/block/', tx.status.block_hash]" [state]="{ data: { blockHeight: tx.status.block_height } }">{{ tx.status.block_height }}</a>
|
||||
<a [routerLink]="['/block/' | relativeUrl, tx.status.block_hash]" [state]="{ data: { blockHeight: tx.status.block_height } }">{{ tx.status.block_height }}</a>
|
||||
<i> (<app-time-since [time]="tx.status.block_time" [fastRender]="true"></app-time-since> ago)</i>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -9,7 +9,6 @@ import { WebsocketService } from '../../services/websocket.service';
|
||||
import { AudioService } from 'src/app/services/audio.service';
|
||||
import { ApiService } from 'src/app/services/api.service';
|
||||
import { SeoService } from 'src/app/services/seo.service';
|
||||
import { environment } from '../../../environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'app-transaction',
|
||||
@@ -17,7 +16,7 @@ import { environment } from '../../../environments/environment';
|
||||
styleUrls: ['./transaction.component.scss']
|
||||
})
|
||||
export class TransactionComponent implements OnInit, OnDestroy {
|
||||
network = environment.network;
|
||||
network = '';
|
||||
tx: Transaction;
|
||||
txId: string;
|
||||
feeRating: number;
|
||||
@@ -44,6 +43,8 @@ export class TransactionComponent implements OnInit, OnDestroy {
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||
|
||||
this.subscription = this.route.paramMap.pipe(
|
||||
switchMap((params: ParamMap) => {
|
||||
this.txId = params.get('id') || '';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<ng-container *ngFor="let tx of transactions; let i = index; trackBy: trackByFn">
|
||||
<div *ngIf="!transactionPage" class="header-bg box" style="padding: 10px; margin-bottom: 10px;">
|
||||
<a [routerLink]="['/tx/', tx.txid]" [state]="{ data: tx }">
|
||||
<a [routerLink]="['/tx/' | relativeUrl, tx.txid]" [state]="{ data: tx }">
|
||||
<span style="float: left;" class="d-block d-md-none">{{ tx.txid | shortenString : 16 }}</span>
|
||||
<span style="float: left;" class="d-none d-md-block">{{ tx.txid }}</span>
|
||||
</a>
|
||||
@@ -18,21 +18,28 @@
|
||||
<tbody>
|
||||
<tr *ngFor="let vin of getFilteredTxVin(tx)">
|
||||
<td class="arrow-td">
|
||||
<ng-template [ngIf]="vin.prevout === null" [ngIfElse]="hasPrevout">
|
||||
<ng-template [ngIf]="vin.prevout === null && !vin.is_pegin" [ngIfElse]="hasPrevout">
|
||||
<i class="arrow grey"></i>
|
||||
</ng-template>
|
||||
<ng-template #hasPrevout>
|
||||
<a [routerLink]="['/tx/', vin.txid]">
|
||||
<a *ngIf="vin.is_pegin; else defaultPrevout" [routerLink]="['/tx/', vin.txid]">
|
||||
<i class="arrow red"></i>
|
||||
</a>
|
||||
<ng-template #defaultPrevout>
|
||||
<a [routerLink]="['/tx/' | relativeUrl, vin.txid]">
|
||||
<i class="arrow red"></i>
|
||||
</a>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</td>
|
||||
<td>
|
||||
<div [ngSwitch]="true">
|
||||
<ng-container *ngSwitchCase="vin.is_coinbase">Coinbase<ng-template [ngIf]="network !== 'liquid'"> (Newly Generated Coins)</ng-template></ng-container>
|
||||
<ng-container *ngSwitchCase="vin.is_pegin">PEG IN</ng-container>
|
||||
<ng-container *ngSwitchCase="vin.is_pegin">
|
||||
Peg-in
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchDefault>
|
||||
<a [routerLink]="['/address/', vin.prevout.scriptpubkey_address]" title="{{ vin.prevout.scriptpubkey_address }}">
|
||||
<a [routerLink]="['/address/' | relativeUrl, vin.prevout.scriptpubkey_address]" title="{{ vin.prevout.scriptpubkey_address }}">
|
||||
<span class="d-block d-lg-none">{{ vin.prevout.scriptpubkey_address | shortenString : 16 }}</span>
|
||||
<span class="d-none d-lg-block">{{ vin.prevout.scriptpubkey_address | shortenString : 42 }}</span>
|
||||
</a>
|
||||
@@ -60,13 +67,16 @@
|
||||
<tbody>
|
||||
<tr *ngFor="let vout of getFilteredTxVout(tx); let vindex = index;">
|
||||
<td>
|
||||
<a *ngIf="vout.scriptpubkey_address; else scriptpubkey_type" [routerLink]="['/address/', vout.scriptpubkey_address]" title="{{ vout.scriptpubkey_address }}">
|
||||
<a *ngIf="vout.scriptpubkey_address; else scriptpubkey_type" [routerLink]="['/address/' | relativeUrl, vout.scriptpubkey_address]" title="{{ vout.scriptpubkey_address }}">
|
||||
<span class="d-block d-lg-none">{{ vout.scriptpubkey_address | shortenString : 16 }}</span>
|
||||
<span class="d-none d-lg-block">{{ vout.scriptpubkey_address | shortenString : 42 }}</span>
|
||||
</a>
|
||||
<ng-template #scriptpubkey_type>
|
||||
<ng-template [ngIf]="vout.pegout" [ngIfElse]="defaultscriptpubkey_type">
|
||||
PEG OUT
|
||||
Peg-out to <a [routerLink]="['/address/', vout.pegout.scriptpubkey_address]" title="{{ vout.pegout.scriptpubkey_address }}">
|
||||
<span class="d-block d-lg-none">{{ vout.pegout.scriptpubkey_address | shortenString : 16 }}</span>
|
||||
<span class="d-none d-lg-block">{{ vout.pegout.scriptpubkey_address | shortenString : 42 }}</span>
|
||||
</a>
|
||||
</ng-template>
|
||||
<ng-template #defaultscriptpubkey_type>
|
||||
{{ vout.scriptpubkey_type | scriptpubkeyType }}
|
||||
@@ -80,7 +90,7 @@
|
||||
<br>
|
||||
{{ assetsMinimal[vout.asset][0] }}
|
||||
<br>
|
||||
<a [routerLink]="['/asset/', vout.asset]">{{ vout.asset | shortenString : 13 }}</a>
|
||||
<a [routerLink]="['/asset/' | relativeUrl, vout.asset]">{{ vout.asset | shortenString : 13 }}</a>
|
||||
<br><br>
|
||||
</div>
|
||||
</ng-template>
|
||||
@@ -93,7 +103,7 @@
|
||||
<ng-template #outspend>
|
||||
<i *ngIf="!outspends[i][vindex] || !outspends[i][vindex].spent; else spent" class="arrow green"></i>
|
||||
<ng-template #spent>
|
||||
<a [routerLink]="['/tx/', outspends[i][vindex].txid]"><i class="arrow red"></i></a>
|
||||
<a [routerLink]="['/tx/' | relativeUrl, outspends[i][vindex].txid]"><i class="arrow red"></i></a>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</td>
|
||||
|
||||
@@ -13,7 +13,7 @@ import { AssetsService } from 'src/app/services/assets.service';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
network = environment.network;
|
||||
network = '';
|
||||
nativeAssetId = environment.nativeAssetId;
|
||||
|
||||
@Input() transactions: Transaction[];
|
||||
@@ -35,6 +35,8 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
||||
|
||||
ngOnInit() {
|
||||
this.latestBlock$ = this.stateService.blocks$;
|
||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||
|
||||
if (this.network === 'liquid') {
|
||||
this.assetsService.getAssetsMinimalJson$.subscribe((assets) => {
|
||||
this.assetsMinimal = assets;
|
||||
|
||||
Reference in New Issue
Block a user