Loading progressbar for loading address, block transactions and blocks
This commit is contained in:
		
							parent
							
								
									b91516a1c1
								
							
						
					
					
						commit
						6a58717694
					
				@ -10,6 +10,7 @@ import logger from '../../logger';
 | 
			
		||||
import * as ElectrumClient from '@mempool/electrum-client';
 | 
			
		||||
import * as sha256 from 'crypto-js/sha256';
 | 
			
		||||
import * as hexEnc from 'crypto-js/enc-hex';
 | 
			
		||||
import loadingIndicators from '../loading-indicators';
 | 
			
		||||
 | 
			
		||||
class BitcoindElectrsApi extends BitcoinApi implements AbstractBitcoinApi {
 | 
			
		||||
  private electrumClient: any;
 | 
			
		||||
@ -121,6 +122,8 @@ class BitcoindElectrsApi extends BitcoinApi implements AbstractBitcoinApi {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      loadingIndicators.setProgress('address-' + address, 0);
 | 
			
		||||
 | 
			
		||||
      const transactions: IEsploraApi.Transaction[] = [];
 | 
			
		||||
      const history = await this.$getScriptHashHistory(addressInfo.scriptPubKey);
 | 
			
		||||
      history.reverse();
 | 
			
		||||
@ -132,16 +135,17 @@ class BitcoindElectrsApi extends BitcoinApi implements AbstractBitcoinApi {
 | 
			
		||||
          startingIndex = pos + 1;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      const endIndex = Math.min(startingIndex + 10, history.length);
 | 
			
		||||
 | 
			
		||||
      for (let i = startingIndex; i < Math.min(startingIndex + 10, history.length); i++) {
 | 
			
		||||
      for (let i = startingIndex; i < endIndex; i++) {
 | 
			
		||||
        const tx = await this.$getRawTransaction(history[i].tx_hash, false, true);
 | 
			
		||||
        if (tx) {
 | 
			
		||||
          transactions.push(tx);
 | 
			
		||||
        }
 | 
			
		||||
        transactions.push(tx);
 | 
			
		||||
        loadingIndicators.setProgress('address-' + address, (i + 1) / endIndex * 100);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return transactions;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      loadingIndicators.setProgress('address-' + address, 100);
 | 
			
		||||
      if (e === 'failed to get confirmed status') {
 | 
			
		||||
        e = 'The number of transactions on this address exceeds the Electrum server limit';
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@ import logger from './logger';
 | 
			
		||||
import bitcoinApi from './api/bitcoin/bitcoin-api-factory';
 | 
			
		||||
import transactionUtils from './api/transaction-utils';
 | 
			
		||||
import blocks from './api/blocks';
 | 
			
		||||
import loadingIndicators from './api/loading-indicators';
 | 
			
		||||
 | 
			
		||||
class Routes {
 | 
			
		||||
  private cache: { [date: string]: OptimizedStatistic[] } = {
 | 
			
		||||
@ -553,6 +554,8 @@ class Routes {
 | 
			
		||||
 | 
			
		||||
  public async getBlocks(req: Request, res: Response) {
 | 
			
		||||
    try {
 | 
			
		||||
      loadingIndicators.setProgress('blocks', 0);
 | 
			
		||||
 | 
			
		||||
      const returnBlocks: IEsploraApi.Block[] = [];
 | 
			
		||||
      const fromHeight = parseInt(req.params.height, 10) || blocks.getCurrentBlockHeight();
 | 
			
		||||
 | 
			
		||||
@ -576,28 +579,35 @@ class Routes {
 | 
			
		||||
          returnBlocks.push(block);
 | 
			
		||||
          nextHash = block.previousblockhash;
 | 
			
		||||
        }
 | 
			
		||||
        loadingIndicators.setProgress('blocks', i / 10 * 100);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      res.json(returnBlocks);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      loadingIndicators.setProgress('blocks', 100);
 | 
			
		||||
      res.status(500).send(e.message || e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async getBlockTransactions(req: Request, res: Response) {
 | 
			
		||||
    try {
 | 
			
		||||
      loadingIndicators.setProgress('blocktxs-' + req.params.hash, 0);
 | 
			
		||||
 | 
			
		||||
      const txIds = await bitcoinApi.$getTxIdsForBlock(req.params.hash);
 | 
			
		||||
      const transactions: TransactionExtended[] = [];
 | 
			
		||||
      const startingIndex = Math.max(0, parseInt(req.params.index, 10));
 | 
			
		||||
 | 
			
		||||
      for (let i = startingIndex; i < Math.min(startingIndex + 10, txIds.length); i++) {
 | 
			
		||||
      const endIndex = Math.min(startingIndex + 10, txIds.length);
 | 
			
		||||
      for (let i = startingIndex; i < endIndex; i++) {
 | 
			
		||||
        const transaction = await transactionUtils.$getTransactionExtended(txIds[i], false, true);
 | 
			
		||||
        if (transaction) {
 | 
			
		||||
          transactions.push(transaction);
 | 
			
		||||
          loadingIndicators.setProgress('blocktxs-' + req.params.hash, (i + 1) / endIndex * 100);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      res.json(transactions);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      loadingIndicators.setProgress('blocktxs-' + req.params.hash, 100);
 | 
			
		||||
      res.status(500).send(e.message || e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -67,6 +67,14 @@
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <ng-container *ngIf="addressLoadingStatus$ | async as addressLoadingStatus">
 | 
			
		||||
          <br>
 | 
			
		||||
          <div  class="progress position-relative progress-dark">
 | 
			
		||||
            <div class="progress-bar progress-darklight" role="progressbar" [ngStyle]="{'width': addressLoadingStatus + '%' }"></div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </ng-container>
 | 
			
		||||
 | 
			
		||||
      </ng-template>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,13 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy } from '@angular/core';
 | 
			
		||||
import { ActivatedRoute, ParamMap } from '@angular/router';
 | 
			
		||||
import { ElectrsApiService } from '../../services/electrs-api.service';
 | 
			
		||||
import { switchMap, filter, catchError } from 'rxjs/operators';
 | 
			
		||||
import { switchMap, filter, catchError, map, tap } from 'rxjs/operators';
 | 
			
		||||
import { Address, Transaction } from '../../interfaces/electrs.interface';
 | 
			
		||||
import { WebsocketService } from 'src/app/services/websocket.service';
 | 
			
		||||
import { StateService } from 'src/app/services/state.service';
 | 
			
		||||
import { AudioService } from 'src/app/services/audio.service';
 | 
			
		||||
import { ApiService } from 'src/app/services/api.service';
 | 
			
		||||
import { of, merge, Subscription } from 'rxjs';
 | 
			
		||||
import { of, merge, Subscription, Observable } from 'rxjs';
 | 
			
		||||
import { SeoService } from 'src/app/services/seo.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
@ -25,6 +25,7 @@ export class AddressComponent implements OnInit, OnDestroy {
 | 
			
		||||
  isLoadingTransactions = true;
 | 
			
		||||
  error: any;
 | 
			
		||||
  mainSubscription: Subscription;
 | 
			
		||||
  addressLoadingStatus$: Observable<number>;
 | 
			
		||||
 | 
			
		||||
  totalConfirmedTxCount = 0;
 | 
			
		||||
  loadedConfirmedTxCount = 0;
 | 
			
		||||
@ -48,7 +49,13 @@ export class AddressComponent implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.stateService.networkChanged$.subscribe((network) => this.network = network);
 | 
			
		||||
    this.websocketService.want(['blocks', 'mempool-blocks']);
 | 
			
		||||
    this.websocketService.want(['blocks']);
 | 
			
		||||
 | 
			
		||||
    this.addressLoadingStatus$ = this.route.paramMap
 | 
			
		||||
      .pipe(
 | 
			
		||||
        switchMap(() => this.stateService.loadingIndicators$),
 | 
			
		||||
        map((indicators) => indicators['address-' + this.addressString] !== undefined ? indicators['address-' + this.addressString] : 0)
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
    this.mainSubscription = this.route.paramMap
 | 
			
		||||
      .pipe(
 | 
			
		||||
 | 
			
		||||
@ -112,6 +112,13 @@
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <ng-container *ngIf="(txsLoadingStatus$ | async) as txsLoadingStatus">
 | 
			
		||||
          <br>
 | 
			
		||||
          <div class="progress position-relative progress-dark">
 | 
			
		||||
            <div class="progress-bar progress-darklight" role="progressbar" [ngStyle]="{'width': txsLoadingStatus + '%' }"></div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </ng-container>
 | 
			
		||||
        
 | 
			
		||||
      </div>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
 | 
			
		||||
@ -2,9 +2,9 @@ import { Component, OnInit, OnDestroy } from '@angular/core';
 | 
			
		||||
import { Location } from '@angular/common';
 | 
			
		||||
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
 | 
			
		||||
import { ElectrsApiService } from '../../services/electrs-api.service';
 | 
			
		||||
import { switchMap, tap, debounceTime, catchError } from 'rxjs/operators';
 | 
			
		||||
import { switchMap, tap, debounceTime, catchError, map } from 'rxjs/operators';
 | 
			
		||||
import { Block, Transaction, Vout } from '../../interfaces/electrs.interface';
 | 
			
		||||
import { of, Subscription } from 'rxjs';
 | 
			
		||||
import { Observable, of, Subscription } from 'rxjs';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { SeoService } from 'src/app/services/seo.service';
 | 
			
		||||
import { WebsocketService } from 'src/app/services/websocket.service';
 | 
			
		||||
@ -31,6 +31,7 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
			
		||||
  coinbaseTx: Transaction;
 | 
			
		||||
  page = 1;
 | 
			
		||||
  itemsPerPage: number;
 | 
			
		||||
  txsLoadingStatus$: Observable<number>;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private route: ActivatedRoute,
 | 
			
		||||
@ -48,6 +49,12 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
			
		||||
    this.network = this.stateService.network;
 | 
			
		||||
    this.itemsPerPage = this.stateService.env.ELECTRS_ITEMS_PER_PAGE;
 | 
			
		||||
 | 
			
		||||
    this.txsLoadingStatus$ = this.route.paramMap
 | 
			
		||||
      .pipe(
 | 
			
		||||
        switchMap(() => this.stateService.loadingIndicators$),
 | 
			
		||||
        map((indicators) => indicators['blocktxs-' + this.blockHash] !== undefined ? indicators['blocktxs-' + this.blockHash] : 0)
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
    this.subscription = this.route.paramMap
 | 
			
		||||
    .pipe(
 | 
			
		||||
      switchMap((params: ParamMap) => {
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,16 @@
 | 
			
		||||
          <td class="d-none d-lg-block"><span class="skeleton-loader"></span></td>
 | 
			
		||||
          <td><span class="skeleton-loader"></span></td>
 | 
			
		||||
        </tr>
 | 
			
		||||
      </ng-template>
 | 
			
		||||
      <ng-container *ngIf="(blocksLoadingStatus$ | async) as blocksLoadingStatus">
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td colspan="5">
 | 
			
		||||
          <div class="progress position-relative progress-dark">
 | 
			
		||||
            <div class="progress-bar progress-darklight" role="progressbar" [ngStyle]="{'width': blocksLoadingStatus + '%' }"></div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </td>
 | 
			
		||||
      </tr>
 | 
			
		||||
      </ng-container>
 | 
			
		||||
    </ng-template>
 | 
			
		||||
    </tbody>
 | 
			
		||||
  </table>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,7 @@ import { Block } from '../../interfaces/electrs.interface';
 | 
			
		||||
import { Subscription, Observable, merge, of } from 'rxjs';
 | 
			
		||||
import { SeoService } from '../../services/seo.service';
 | 
			
		||||
import { WebsocketService } from 'src/app/services/websocket.service';
 | 
			
		||||
import { map } from 'rxjs/operators';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-latest-blocks',
 | 
			
		||||
@ -19,6 +20,7 @@ export class LatestBlocksComponent implements OnInit, OnDestroy {
 | 
			
		||||
  blockSubscription: Subscription;
 | 
			
		||||
  isLoading = true;
 | 
			
		||||
  interval: any;
 | 
			
		||||
  blocksLoadingStatus$: Observable<number>;
 | 
			
		||||
 | 
			
		||||
  latestBlockHeight: number;
 | 
			
		||||
 | 
			
		||||
@ -39,6 +41,11 @@ export class LatestBlocksComponent implements OnInit, OnDestroy {
 | 
			
		||||
 | 
			
		||||
    this.network$ = merge(of(''), this.stateService.networkChanged$);
 | 
			
		||||
 | 
			
		||||
    this.blocksLoadingStatus$ = this.stateService.loadingIndicators$
 | 
			
		||||
      .pipe(
 | 
			
		||||
        map((indicators) => indicators['blocks'] !== undefined ? indicators['blocks'] : 0)
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
    this.blockSubscription = this.stateService.blocks$
 | 
			
		||||
      .subscribe(([block]) => {
 | 
			
		||||
        if (block === null || !this.blocks.length) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user