Refactord blockchain is rendering, block arrow location propagation and keynavigation.
This commit is contained in:
		
							parent
							
								
									69827843c9
								
							
						
					
					
						commit
						78e41fc3d3
					
				@ -9,6 +9,7 @@ import { AboutComponent } from './components/about/about.component';
 | 
			
		||||
import { TelevisionComponent } from './components/television/television.component';
 | 
			
		||||
import { StatisticsComponent } from './components/statistics/statistics.component';
 | 
			
		||||
import { MempoolBlockComponent } from './components/mempool-block/mempool-block.component';
 | 
			
		||||
import { LatestBlocksComponent } from './components/latest-blocks/latest-blocks.component';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
  {
 | 
			
		||||
@ -18,6 +19,24 @@ const routes: Routes = [
 | 
			
		||||
      {
 | 
			
		||||
        path: '',
 | 
			
		||||
        component: StartComponent,
 | 
			
		||||
        children: [
 | 
			
		||||
          {
 | 
			
		||||
            path: '',
 | 
			
		||||
            component: LatestBlocksComponent
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            path: 'tx/:id',
 | 
			
		||||
            component: TransactionComponent
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            path: 'block/:id',
 | 
			
		||||
            component: BlockComponent
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            path: 'mempool-block/:id',
 | 
			
		||||
            component: MempoolBlockComponent
 | 
			
		||||
          },
 | 
			
		||||
        ],
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: 'graphs',
 | 
			
		||||
@ -27,21 +46,6 @@ const routes: Routes = [
 | 
			
		||||
        path: 'contributors',
 | 
			
		||||
        component: AboutComponent,
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: 'tx/:id',
 | 
			
		||||
        children: [],
 | 
			
		||||
        component: TransactionComponent
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: 'block/:id',
 | 
			
		||||
        children: [],
 | 
			
		||||
        component: BlockComponent
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: 'mempool-block/:id',
 | 
			
		||||
        children: [],
 | 
			
		||||
        component: MempoolBlockComponent
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: 'address/:id',
 | 
			
		||||
        children: [],
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,5 @@
 | 
			
		||||
<div class="container-xl">
 | 
			
		||||
 | 
			
		||||
  <div style="position: relative;">
 | 
			
		||||
    <app-blockchain position="top" [markHeight]="blockHeight"></app-blockchain>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <div class="title-block">
 | 
			
		||||
    <h1>Block <ng-template [ngIf]="blockHeight"><a [routerLink]="['/block/', blockHash]">{{ blockHeight }}</a></ng-template></h1>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,9 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core';
 | 
			
		||||
import { Component, OnInit, OnDestroy } from '@angular/core';
 | 
			
		||||
import { ActivatedRoute, ParamMap } from '@angular/router';
 | 
			
		||||
import { ElectrsApiService } from '../../services/electrs-api.service';
 | 
			
		||||
import { switchMap } from 'rxjs/operators';
 | 
			
		||||
import { switchMap, tap, debounceTime } from 'rxjs/operators';
 | 
			
		||||
import { Block, Transaction, Vout } from '../../interfaces/electrs.interface';
 | 
			
		||||
import { of } from 'rxjs';
 | 
			
		||||
import { of, Observable } from 'rxjs';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { WebsocketService } from 'src/app/services/websocket.service';
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,7 @@ import { WebsocketService } from 'src/app/services/websocket.service';
 | 
			
		||||
  templateUrl: './block.component.html',
 | 
			
		||||
  styleUrls: ['./block.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class BlockComponent implements OnInit {
 | 
			
		||||
export class BlockComponent implements OnInit, OnDestroy {
 | 
			
		||||
  block: Block;
 | 
			
		||||
  blockHeight: number;
 | 
			
		||||
  blockHash: string;
 | 
			
		||||
@ -34,7 +34,8 @@ export class BlockComponent implements OnInit {
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.websocketService.want(['blocks', 'stats', 'mempool-blocks']);
 | 
			
		||||
 | 
			
		||||
    this.route.paramMap.pipe(
 | 
			
		||||
    this.route.paramMap
 | 
			
		||||
    .pipe(
 | 
			
		||||
      switchMap((params: ParamMap) => {
 | 
			
		||||
        const blockHash: string = params.get('id') || '';
 | 
			
		||||
        this.error = undefined;
 | 
			
		||||
@ -54,17 +55,28 @@ export class BlockComponent implements OnInit {
 | 
			
		||||
          this.isLoadingBlock = true;
 | 
			
		||||
          return this.electrsApiService.getBlock$(blockHash);
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      }),
 | 
			
		||||
      tap((block: Block) => {
 | 
			
		||||
        this.block = block;
 | 
			
		||||
        this.blockHeight = block.height;
 | 
			
		||||
        this.isLoadingBlock = false;
 | 
			
		||||
        this.setBlockSubsidy();
 | 
			
		||||
        if (block.reward) {
 | 
			
		||||
          this.fees = block.reward / 100000000 - this.blockSubsidy;
 | 
			
		||||
        }
 | 
			
		||||
        this.stateService.markBlock$.next({ blockHeight: this.blockHeight });
 | 
			
		||||
        this.isLoadingTransactions = true;
 | 
			
		||||
        this.transactions = null;
 | 
			
		||||
      }),
 | 
			
		||||
      debounceTime(250),
 | 
			
		||||
      switchMap((block) => this.electrsApiService.getBlockTransactions$(block.id))
 | 
			
		||||
    )
 | 
			
		||||
    .subscribe((block: Block) => {
 | 
			
		||||
      this.block = block;
 | 
			
		||||
      this.blockHeight = block.height;
 | 
			
		||||
      this.isLoadingBlock = false;
 | 
			
		||||
      this.setBlockSubsidy();
 | 
			
		||||
      if (block.reward) {
 | 
			
		||||
        this.fees = block.reward / 100000000 - this.blockSubsidy;
 | 
			
		||||
    .subscribe((transactions: Transaction[]) => {
 | 
			
		||||
      if (this.fees === undefined) {
 | 
			
		||||
        this.fees = transactions[0].vout.reduce((acc: number, curr: Vout) => acc + curr.value, 0) / 100000000 - this.blockSubsidy;
 | 
			
		||||
      }
 | 
			
		||||
      this.getBlockTransactions(block.id);
 | 
			
		||||
      this.transactions = transactions;
 | 
			
		||||
      this.isLoadingTransactions = false;
 | 
			
		||||
    },
 | 
			
		||||
    (error) => {
 | 
			
		||||
      this.error = error;
 | 
			
		||||
@ -75,6 +87,10 @@ export class BlockComponent implements OnInit {
 | 
			
		||||
      .subscribe((block) => this.latestBlock = block);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    this.stateService.markBlock$.next({});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setBlockSubsidy() {
 | 
			
		||||
    this.blockSubsidy = 50;
 | 
			
		||||
    let halvenings = Math.floor(this.block.height / 210000);
 | 
			
		||||
@ -84,19 +100,6 @@ export class BlockComponent implements OnInit {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getBlockTransactions(hash: string) {
 | 
			
		||||
    this.isLoadingTransactions = true;
 | 
			
		||||
    this.transactions = null;
 | 
			
		||||
    this.electrsApiService.getBlockTransactions$(hash)
 | 
			
		||||
      .subscribe((transactions: any) => {
 | 
			
		||||
        if (this.fees === undefined) {
 | 
			
		||||
          this.fees = transactions[0].vout.reduce((acc: number, curr: Vout) => acc + curr.value, 0) / 100000000 - this.blockSubsidy;
 | 
			
		||||
        }
 | 
			
		||||
        this.transactions = transactions;
 | 
			
		||||
        this.isLoadingTransactions = false;
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  loadMore() {
 | 
			
		||||
    if (this.isLoadingTransactions || !this.transactions.length || this.transactions.length === this.block.tx_count) {
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, Input, OnChanges, HostListener } from '@angular/core';
 | 
			
		||||
import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
import { Block } from 'src/app/interfaces/electrs.interface';
 | 
			
		||||
import { StateService } from 'src/app/services/state.service';
 | 
			
		||||
@ -9,10 +9,9 @@ import { Router } from '@angular/router';
 | 
			
		||||
  templateUrl: './blockchain-blocks.component.html',
 | 
			
		||||
  styleUrls: ['./blockchain-blocks.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  @Input() markHeight = 0;
 | 
			
		||||
 | 
			
		||||
export class BlockchainBlocksComponent implements OnInit, OnDestroy {
 | 
			
		||||
  blocks: Block[] = [];
 | 
			
		||||
  markHeight: number;
 | 
			
		||||
  blocksSubscription: Subscription;
 | 
			
		||||
  interval: any;
 | 
			
		||||
 | 
			
		||||
@ -37,10 +36,15 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
 | 
			
		||||
        this.moveArrowToPosition(true);
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnChanges() {
 | 
			
		||||
    this.moveArrowToPosition(false);
 | 
			
		||||
    this.stateService.markBlock$
 | 
			
		||||
      .subscribe((state) => {
 | 
			
		||||
        this.markHeight = undefined;
 | 
			
		||||
        if (state.blockHeight) {
 | 
			
		||||
          this.markHeight = state.blockHeight;
 | 
			
		||||
        }
 | 
			
		||||
        this.moveArrowToPosition(false);
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
<div class="text-center" class="blockchain-wrapper">
 | 
			
		||||
  <div class="position-container">
 | 
			
		||||
    <app-mempool-blocks [markIndex]="markMempoolBlockIndex" [txFeePerVSize]="markHeight ? 0 : txFeePerVSize"></app-mempool-blocks>
 | 
			
		||||
    <app-blockchain-blocks [markHeight]="markHeight"></app-blockchain-blocks>
 | 
			
		||||
    <app-mempool-blocks></app-mempool-blocks>
 | 
			
		||||
    <app-blockchain-blocks></app-blockchain-blocks>
 | 
			
		||||
 | 
			
		||||
    <div id="divider" *ngIf="!isLoading; else loadingTmpl"></div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,7 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
 | 
			
		||||
import { Component, OnInit, OnDestroy } from '@angular/core';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
import { take } from 'rxjs/operators';
 | 
			
		||||
import { StateService } from 'src/app/services/state.service';
 | 
			
		||||
import { Router } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-blockchain',
 | 
			
		||||
@ -10,12 +9,6 @@ import { Router } from '@angular/router';
 | 
			
		||||
  styleUrls: ['./blockchain.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class BlockchainComponent implements OnInit, OnDestroy {
 | 
			
		||||
  @Input() position: 'middle' | 'top' = 'middle';
 | 
			
		||||
  @Input() markHeight: number;
 | 
			
		||||
  @Input() txFeePerVSize: number;
 | 
			
		||||
  @Input() markMempoolBlockIndex = -1;
 | 
			
		||||
 | 
			
		||||
  txTrackingSubscription: Subscription;
 | 
			
		||||
  blocksSubscription: Subscription;
 | 
			
		||||
 | 
			
		||||
  txTrackingLoading = false;
 | 
			
		||||
@ -24,7 +17,6 @@ export class BlockchainComponent implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private stateService: StateService,
 | 
			
		||||
    private router: Router,
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1,7 @@
 | 
			
		||||
<div class="container-xl">
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
<table class="table table-borderless" [alwaysCallback]="true" [fromRoot]="true" [infiniteScrollContainer]="'body'" infiniteScroll [infiniteScrollDistance]="1.5" [infiniteScrollUpDistance]="1.5" [infiniteScrollThrottle]="50" (scrolled)="loadMore()">
 | 
			
		||||
  <thead>
 | 
			
		||||
    <th style="width: 15%;">Height</th>
 | 
			
		||||
@ -30,3 +34,5 @@
 | 
			
		||||
    </ng-template>
 | 
			
		||||
  </tbody>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
@ -1,9 +1,5 @@
 | 
			
		||||
<div class="container-xl" *ngIf="mempoolBlock">
 | 
			
		||||
 | 
			
		||||
  <div style="position: relative;">
 | 
			
		||||
    <app-blockchain position="top" [markMempoolBlockIndex]="mempoolBlockIndex"></app-blockchain>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <div class="title-block">
 | 
			
		||||
    <h1>Mempool block</h1>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core';
 | 
			
		||||
import { Component, OnInit, OnDestroy } from '@angular/core';
 | 
			
		||||
import { StateService } from 'src/app/services/state.service';
 | 
			
		||||
import { ActivatedRoute, ParamMap } from '@angular/router';
 | 
			
		||||
import { switchMap, map } from 'rxjs/operators';
 | 
			
		||||
@ -10,7 +10,7 @@ import { WebsocketService } from 'src/app/services/websocket.service';
 | 
			
		||||
  templateUrl: './mempool-block.component.html',
 | 
			
		||||
  styleUrls: ['./mempool-block.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class MempoolBlockComponent implements OnInit {
 | 
			
		||||
export class MempoolBlockComponent implements OnInit, OnDestroy {
 | 
			
		||||
  mempoolBlockIndex: number;
 | 
			
		||||
  mempoolBlock: MempoolBlock;
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,7 @@ export class MempoolBlockComponent implements OnInit {
 | 
			
		||||
    this.route.paramMap.pipe(
 | 
			
		||||
      switchMap((params: ParamMap) => {
 | 
			
		||||
        this.mempoolBlockIndex = parseInt(params.get('id'), 10) || 0;
 | 
			
		||||
        this.stateService.markBlock$.next({ mempoolBlockIndex: this.mempoolBlockIndex });
 | 
			
		||||
        return this.stateService.mempoolBlocks$
 | 
			
		||||
          .pipe(
 | 
			
		||||
            map((mempoolBlocks) => mempoolBlocks[this.mempoolBlockIndex])
 | 
			
		||||
@ -37,4 +38,8 @@ export class MempoolBlockComponent implements OnInit {
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy(): void {
 | 
			
		||||
    this.stateService.markBlock$.next({});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, Input, OnChanges, HostListener } from '@angular/core';
 | 
			
		||||
import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
import { MempoolBlock } from 'src/app/interfaces/websocket.interface';
 | 
			
		||||
import { StateService } from 'src/app/services/state.service';
 | 
			
		||||
@ -9,7 +9,7 @@ import { Router } from '@angular/router';
 | 
			
		||||
  templateUrl: './mempool-blocks.component.html',
 | 
			
		||||
  styleUrls: ['./mempool-blocks.component.scss']
 | 
			
		||||
})
 | 
			
		||||
export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
export class MempoolBlocksComponent implements OnInit, OnDestroy {
 | 
			
		||||
  mempoolBlocks: MempoolBlock[];
 | 
			
		||||
  mempoolBlocksFull: MempoolBlock[];
 | 
			
		||||
  mempoolBlocksSubscription: Subscription;
 | 
			
		||||
@ -21,8 +21,8 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  rightPosition = 0;
 | 
			
		||||
  transition = '1s';
 | 
			
		||||
 | 
			
		||||
  @Input() txFeePerVSize: number;
 | 
			
		||||
  @Input() markIndex: number;
 | 
			
		||||
  markIndex: number;
 | 
			
		||||
  txFeePerVSize: number;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private router: Router,
 | 
			
		||||
@ -36,11 +36,23 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
        this.mempoolBlocks = this.reduceMempoolBlocksToFitScreen(blocks);
 | 
			
		||||
        this.calculateTransactionPosition();
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
    this.stateService.markBlock$
 | 
			
		||||
      .subscribe((state) => {
 | 
			
		||||
        this.markIndex = undefined;
 | 
			
		||||
        this.txFeePerVSize = undefined;
 | 
			
		||||
        if (state.mempoolBlockIndex !== undefined) {
 | 
			
		||||
          this.markIndex = state.mempoolBlockIndex;
 | 
			
		||||
        }
 | 
			
		||||
        if (state.txFeePerVSize) {
 | 
			
		||||
          this.txFeePerVSize = state.txFeePerVSize;
 | 
			
		||||
        }
 | 
			
		||||
        this.calculateTransactionPosition();
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @HostListener('window:resize', ['$event'])
 | 
			
		||||
  onResize() {
 | 
			
		||||
    console.log('onResize');
 | 
			
		||||
    if (this.mempoolBlocks.length) {
 | 
			
		||||
      this.mempoolBlocks = this.reduceMempoolBlocksToFitScreen(JSON.parse(JSON.stringify(this.mempoolBlocksFull)));
 | 
			
		||||
    }
 | 
			
		||||
@ -48,29 +60,27 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  @HostListener('document:keydown', ['$event'])
 | 
			
		||||
  handleKeyboardEvents(event: KeyboardEvent) {
 | 
			
		||||
    if (this.markIndex === -1) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    if (event.key === 'ArrowRight') {
 | 
			
		||||
      if (this.mempoolBlocks[this.markIndex - 1]) {
 | 
			
		||||
        this.router.navigate(['/mempool-block/', this.markIndex - 1]);
 | 
			
		||||
      } else {
 | 
			
		||||
        this.stateService.blocks$
 | 
			
		||||
          .subscribe((block) => {
 | 
			
		||||
            if (this.stateService.latestBlockHeight === block.height) {
 | 
			
		||||
              this.router.navigate(['/block/', block.id], { state: { data: { block } }});
 | 
			
		||||
            }
 | 
			
		||||
          });
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
      if (this.markIndex === undefined) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
    } else if (event.key === 'ArrowLeft') {
 | 
			
		||||
      if (this.mempoolBlocks[this.markIndex + 1]) {
 | 
			
		||||
        this.router.navigate(['/mempool-block/', this.markIndex + 1]);
 | 
			
		||||
      if (event.key === 'ArrowRight') {
 | 
			
		||||
        if (this.mempoolBlocks[this.markIndex - 1]) {
 | 
			
		||||
          this.router.navigate(['/mempool-block/', this.markIndex - 1]);
 | 
			
		||||
        } else {
 | 
			
		||||
          this.stateService.blocks$
 | 
			
		||||
            .subscribe((block) => {
 | 
			
		||||
              if (this.stateService.latestBlockHeight === block.height) {
 | 
			
		||||
                this.router.navigate(['/block/', block.id], { state: { data: { block } }});
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
      } else if (event.key === 'ArrowLeft') {
 | 
			
		||||
        if (this.mempoolBlocks[this.markIndex + 1]) {
 | 
			
		||||
          this.router.navigate(['/mempool-block/', this.markIndex + 1]);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnChanges() {
 | 
			
		||||
    this.calculateTransactionPosition();
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,5 @@
 | 
			
		||||
<div class="container-xl">
 | 
			
		||||
  <div style="position: relative;">
 | 
			
		||||
    <app-blockchain></app-blockchain>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <hr>
 | 
			
		||||
  <app-latest-blocks></app-latest-blocks>
 | 
			
		||||
 | 
			
		||||
<div style="position: relative;">
 | 
			
		||||
  <app-blockchain></app-blockchain>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<router-outlet></router-outlet>
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,5 @@
 | 
			
		||||
<div class="container-xl">
 | 
			
		||||
 | 
			
		||||
  <div style="position: relative;">
 | 
			
		||||
    <app-blockchain position="top" [txFeePerVSize]="tx?.fee / (tx?.weight / 4)" [markHeight]="tx?.status?.block_height"></app-blockchain>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <div class="transaction-content">
 | 
			
		||||
 | 
			
		||||
  <div class="title-block">
 | 
			
		||||
    <h1 class="float-md-left">Transaction</h1>
 | 
			
		||||
 | 
			
		||||
@ -181,6 +175,5 @@
 | 
			
		||||
  </ng-template>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<br>
 | 
			
		||||
 | 
			
		||||
@ -65,6 +65,11 @@ export class TransactionComponent implements OnInit, OnDestroy {
 | 
			
		||||
      } else {
 | 
			
		||||
        this.findBlockAndSetFeeRating();
 | 
			
		||||
      }
 | 
			
		||||
      if (this.tx.status.confirmed) {
 | 
			
		||||
        this.stateService.markBlock$.next({ blockHeight: tx.status.block_height });
 | 
			
		||||
      } else {
 | 
			
		||||
        this.stateService.markBlock$.next({ txFeePerVSize: tx.fee / (tx.weight / 4) });
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    (error) => {
 | 
			
		||||
      this.error = error;
 | 
			
		||||
@ -82,6 +87,7 @@ export class TransactionComponent implements OnInit, OnDestroy {
 | 
			
		||||
          block_hash: block.id,
 | 
			
		||||
          block_time: block.timestamp,
 | 
			
		||||
        };
 | 
			
		||||
        this.stateService.markBlock$.next({ blockHeight: block.height });
 | 
			
		||||
        this.audioService.playSound('magic');
 | 
			
		||||
        this.findBlockAndSetFeeRating();
 | 
			
		||||
      });
 | 
			
		||||
@ -121,5 +127,6 @@ export class TransactionComponent implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    this.websocketService.startTrackTransaction('stop');
 | 
			
		||||
    this.stateService.markBlock$.next({});
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,3 @@
 | 
			
		||||
 | 
			
		||||
export interface BlockTransaction {
 | 
			
		||||
  f: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface OptimizedMempoolStats {
 | 
			
		||||
  id: number;
 | 
			
		||||
  added: string;
 | 
			
		||||
@ -13,7 +8,3 @@ export interface OptimizedMempoolStats {
 | 
			
		||||
  mempool_byte_weight: number;
 | 
			
		||||
  vsizes: number[] | string[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface FeeData {
 | 
			
		||||
  vsize: { [ fee: string ]: number };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,12 @@ import { Block, Transaction } from '../interfaces/electrs.interface';
 | 
			
		||||
import { MempoolBlock, MemPoolState } from '../interfaces/websocket.interface';
 | 
			
		||||
import { OptimizedMempoolStats } from '../interfaces/node-api.interface';
 | 
			
		||||
 | 
			
		||||
interface MarkBlockState {
 | 
			
		||||
  blockHeight?: number;
 | 
			
		||||
  mempoolBlockIndex?: number;
 | 
			
		||||
  txFeePerVSize?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
  providedIn: 'root'
 | 
			
		||||
})
 | 
			
		||||
@ -21,4 +27,6 @@ export class StateService {
 | 
			
		||||
 | 
			
		||||
  viewFiat$ = new BehaviorSubject<boolean>(false);
 | 
			
		||||
  connectionState$ = new BehaviorSubject<0 | 1 | 2>(2);
 | 
			
		||||
 | 
			
		||||
  markBlock$ = new Subject<MarkBlockState>();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user