Responsive mempool blocks.
This commit is contained in:
		
							parent
							
								
									ff685e836a
								
							
						
					
					
						commit
						35569d5c45
					
				@ -40,7 +40,7 @@ ENV CHAT_SSL_ENABLED false
 | 
			
		||||
#ENV CHAT_SSL_CHAIN
 | 
			
		||||
ENV MEMPOOL_REFRESH_RATE_MS 500
 | 
			
		||||
ENV INITIAL_BLOCK_AMOUNT 8
 | 
			
		||||
ENV DEFAULT_PROJECTED_BLOCKS_AMOUNT 3
 | 
			
		||||
ENV DEFAULT_PROJECTED_BLOCKS_AMOUNT 8
 | 
			
		||||
ENV KEEP_BLOCK_AMOUNT 24
 | 
			
		||||
ENV BITCOIN_NODE_HOST bitcoinhost
 | 
			
		||||
ENV BITCOIN_NODE_PORT 8332
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@
 | 
			
		||||
  "API_ENDPOINT": "/api/v1/",
 | 
			
		||||
  "ELECTRS_POLL_RATE_MS": 2000,
 | 
			
		||||
  "MEMPOOL_REFRESH_RATE_MS": 2000,
 | 
			
		||||
  "DEFAULT_PROJECTED_BLOCKS_AMOUNT": 3,
 | 
			
		||||
  "DEFAULT_PROJECTED_BLOCKS_AMOUNT": 8,
 | 
			
		||||
  "KEEP_BLOCK_AMOUNT": 24,
 | 
			
		||||
  "INITIAL_BLOCK_AMOUNT": 8,
 | 
			
		||||
  "TX_PER_SECOND_SPAN_SECONDS": 150,
 | 
			
		||||
 | 
			
		||||
@ -73,8 +73,8 @@ class Blocks {
 | 
			
		||||
 | 
			
		||||
        block.reward = transactions[0].vout.reduce((acc, curr) => acc + curr.value, 0);
 | 
			
		||||
        transactions.sort((a, b) => b.feePerVsize - a.feePerVsize);
 | 
			
		||||
        block.medianFee = transactions.length ? this.median(transactions.map((tx) => tx.feePerVsize)) : 0;
 | 
			
		||||
        block.feeRange = transactions.length ? this.getFeesInRange(transactions, 8) : [0, 0];
 | 
			
		||||
        block.medianFee = transactions.length > 1 ? this.median(transactions.map((tx) => tx.feePerVsize)) : 0;
 | 
			
		||||
        block.feeRange = transactions.length > 1 ? this.getFeesInRange(transactions, 8) : [0, 0];
 | 
			
		||||
 | 
			
		||||
        this.blocks.push(block);
 | 
			
		||||
        if (this.blocks.length > config.KEEP_BLOCK_AMOUNT) {
 | 
			
		||||
@ -111,7 +111,7 @@ class Blocks {
 | 
			
		||||
      itemsToAdd--;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    arr.push(transactions[0].feePerVsize);
 | 
			
		||||
    arr.push(transactions[1].feePerVsize);
 | 
			
		||||
    return arr;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,7 @@ class MempoolBlocks {
 | 
			
		||||
    let blockSize = 0;
 | 
			
		||||
    let transactions: TransactionExtended[] = [];
 | 
			
		||||
    transactionsSorted.forEach((tx) => {
 | 
			
		||||
      if (blockWeight + tx.vsize < 1000000 || mempoolBlocks.length === config.DEFAULT_PROJECTED_BLOCKS_AMOUNT) {
 | 
			
		||||
      if (blockWeight + tx.vsize < 1000000 || mempoolBlocks.length === config.DEFAULT_PROJECTED_BLOCKS_AMOUNT - 1) {
 | 
			
		||||
        blockWeight += tx.vsize;
 | 
			
		||||
        blockSize += tx.size;
 | 
			
		||||
        transactions.push(tx);
 | 
			
		||||
 | 
			
		||||
@ -10,8 +10,8 @@
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="block-size">{{ projectedBlock.blockSize | bytes: 2 }}</div>
 | 
			
		||||
          <div class="transaction-count">{{ projectedBlock.nTx }} transactions</div>
 | 
			
		||||
          <div class="time-difference" *ngIf="i !== 3">In ~{{ 10 * i + 10 }} minutes</div>
 | 
			
		||||
          <ng-template [ngIf]="i === 3 && mempoolBlocks?.length >= 4 && (projectedBlock.blockVSize / 1000000 | ceil) > 1">
 | 
			
		||||
          <div class="time-difference" *ngIf="projectedBlock.blockVSize < 1000000">In ~{{ 10 * i + 10 }} minutes</div>
 | 
			
		||||
          <ng-template [ngIf]="i === mempoolBlocks.length - 1 && projectedBlock.blockVSize >= 1000000">
 | 
			
		||||
            <div class="time-difference">+{{ projectedBlock.blockVSize / 1000000 | ceil }} blocks</div>
 | 
			
		||||
          </ng-template>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, Input, EventEmitter, Output, OnChanges } from '@angular/core';
 | 
			
		||||
import { Component, OnInit, OnDestroy, Input, EventEmitter, Output, OnChanges, HostListener } from '@angular/core';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
import { MempoolBlock } from 'src/app/interfaces/websocket.interface';
 | 
			
		||||
import { StateService } from 'src/app/services/state.service';
 | 
			
		||||
@ -10,6 +10,7 @@ import { StateService } from 'src/app/services/state.service';
 | 
			
		||||
})
 | 
			
		||||
export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  mempoolBlocks: MempoolBlock[];
 | 
			
		||||
  mempoolBlocksFull: MempoolBlock[];
 | 
			
		||||
  mempoolBlocksSubscription: Subscription;
 | 
			
		||||
 | 
			
		||||
  blockWidth = 125;
 | 
			
		||||
@ -27,11 +28,21 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.mempoolBlocksSubscription = this.stateService.mempoolBlocks$
 | 
			
		||||
      .subscribe((blocks) => {
 | 
			
		||||
        this.mempoolBlocks = blocks;
 | 
			
		||||
        this.mempoolBlocksFull = JSON.parse(JSON.stringify(blocks));
 | 
			
		||||
        this.mempoolBlocks = this.reduceMempoolBlocksToFitScreen(blocks);
 | 
			
		||||
        this.calculateTransactionPosition();
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @HostListener('window:resize', ['$event'])
 | 
			
		||||
  onResize() {
 | 
			
		||||
    console.log('onResize');
 | 
			
		||||
    if (this.mempoolBlocks.length) {
 | 
			
		||||
      this.mempoolBlocks = this.reduceMempoolBlocksToFitScreen(JSON.parse(JSON.stringify(this.mempoolBlocksFull)));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  ngOnChanges() {
 | 
			
		||||
    this.calculateTransactionPosition();
 | 
			
		||||
  }
 | 
			
		||||
@ -44,6 +55,32 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
    return index;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  reduceMempoolBlocksToFitScreen(blocks: MempoolBlock[]): MempoolBlock[] {
 | 
			
		||||
    const blocksAmount = Math.max(1, Math.floor(window.innerWidth / 2 / (this.blockWidth + this.blockPadding)));
 | 
			
		||||
    while (blocks.length > blocksAmount) {
 | 
			
		||||
      const block = blocks.pop();
 | 
			
		||||
      const lastBlock = blocks[blocks.length - 1];
 | 
			
		||||
      lastBlock.blockSize += block.blockSize;
 | 
			
		||||
      lastBlock.blockVSize += block.blockVSize;
 | 
			
		||||
      lastBlock.nTx += block.nTx;
 | 
			
		||||
      lastBlock.feeRange = lastBlock.feeRange.concat(block.feeRange);
 | 
			
		||||
      lastBlock.feeRange.sort((a, b) => a - b);
 | 
			
		||||
      lastBlock.medianFee = this.median(lastBlock.feeRange);
 | 
			
		||||
    }
 | 
			
		||||
    return blocks;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  median(numbers: number[]) {
 | 
			
		||||
    let medianNr = 0;
 | 
			
		||||
    const numsLen = numbers.length;
 | 
			
		||||
    if (numsLen % 2 === 0) {
 | 
			
		||||
        medianNr = (numbers[numsLen / 2 - 1] + numbers[numsLen / 2]) / 2;
 | 
			
		||||
    } else {
 | 
			
		||||
        medianNr = numbers[(numsLen - 1) / 2];
 | 
			
		||||
    }
 | 
			
		||||
    return medianNr;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getStyleForMempoolBlockAtIndex(index: number) {
 | 
			
		||||
    const greenBackgroundHeight = 100 - this.mempoolBlocks[index].blockVSize / 1000000 * 100;
 | 
			
		||||
    return {
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
 | 
			
		||||
import { WebsocketResponse } from '../interfaces/websocket.interface';
 | 
			
		||||
import { WebsocketResponse, MempoolBlock } from '../interfaces/websocket.interface';
 | 
			
		||||
import { StateService } from './state.service';
 | 
			
		||||
import { Block, Transaction } from '../interfaces/electrs.interface';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user