Rearange network dropdown.
API for Bisq block height tip. Loading indicators on transactions/blocks view. Total sent now correctly display burnt on Pay trade fee txs.
This commit is contained in:
		
							parent
							
								
									3008f99668
								
							
						
					
					
						commit
						3333b76c98
					
				@ -5,6 +5,7 @@ import { BisqBlocks, BisqBlock, BisqTransaction, BisqStats, BisqTrade } from '..
 | 
			
		||||
import { Common } from './common';
 | 
			
		||||
 | 
			
		||||
class Bisq {
 | 
			
		||||
  private latestBlockHeight = 0;
 | 
			
		||||
  private blocks: BisqBlock[] = [];
 | 
			
		||||
  private transactions: BisqTransaction[] = [];
 | 
			
		||||
  private transactionIndex: { [txId: string]: BisqTransaction } = {};
 | 
			
		||||
@ -70,6 +71,10 @@ class Bisq {
 | 
			
		||||
    this.priceUpdateCallbackFunction = fn;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getLatestBlockHeight(): number {
 | 
			
		||||
    return this.latestBlockHeight;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private updatePrice() {
 | 
			
		||||
    request('https://markets.bisq.network/api/trades/?market=bsq_btc', { json: true }, (err, res, trades: BisqTrade[]) => {
 | 
			
		||||
      if (err) { return console.log(err); }
 | 
			
		||||
@ -180,6 +185,7 @@ class Bisq {
 | 
			
		||||
      if (data.blocks && data.blocks.length !== this.blocks.length) {
 | 
			
		||||
        this.blocks = data.blocks.filter((block) => block.txs.length > 0);
 | 
			
		||||
        this.blocks.reverse();
 | 
			
		||||
        this.latestBlockHeight = data.chainHeight;
 | 
			
		||||
        const time = new Date().getTime() - start;
 | 
			
		||||
        console.log('Bisq dump loaded in ' + time + ' ms');
 | 
			
		||||
      } else {
 | 
			
		||||
 | 
			
		||||
@ -96,6 +96,7 @@ class Server {
 | 
			
		||||
        .get(config.API_ENDPOINT + 'bisq/stats', routes.getBisqStats)
 | 
			
		||||
        .get(config.API_ENDPOINT + 'bisq/tx/:txId', routes.getBisqTransaction)
 | 
			
		||||
        .get(config.API_ENDPOINT + 'bisq/block/:hash', routes.getBisqBlock)
 | 
			
		||||
        .get(config.API_ENDPOINT + 'bisq/blocks/tip/height', routes.getBisqTip)
 | 
			
		||||
        .get(config.API_ENDPOINT + 'bisq/blocks/:index/:length', routes.getBisqBlocks)
 | 
			
		||||
        .get(config.API_ENDPOINT + 'bisq/address/:address', routes.getBisqAddress)
 | 
			
		||||
        .get(config.API_ENDPOINT + 'bisq/txs/:index/:length', routes.getBisqTransactions)
 | 
			
		||||
 | 
			
		||||
@ -92,6 +92,11 @@ class Routes {
 | 
			
		||||
    res.send(result);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getBisqTip(req: Request, res: Response) {
 | 
			
		||||
    const result = bisq.getLatestBlockHeight();
 | 
			
		||||
    res.send(result.toString());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getBisqTransaction(req: Request, res: Response) {
 | 
			
		||||
    const result = bisq.getTransaction(req.params.txId);
 | 
			
		||||
    if (result) {
 | 
			
		||||
 | 
			
		||||
@ -6,13 +6,13 @@
 | 
			
		||||
 | 
			
		||||
  <table class="table table-borderless table-striped">
 | 
			
		||||
    <thead>
 | 
			
		||||
      <th>Hash</th>
 | 
			
		||||
      <th>Total Sent (BSQ)</th>
 | 
			
		||||
      <th>Transactions</th>
 | 
			
		||||
      <th>Height</th>
 | 
			
		||||
      <th>Time</th>
 | 
			
		||||
      <th style="width: 20%;">Hash</th>
 | 
			
		||||
      <th style="width: 20%;">Total Sent (BSQ)</th>
 | 
			
		||||
      <th style="width: 20%;">Transactions</th>
 | 
			
		||||
      <th style="width: 20%;">Height</th>
 | 
			
		||||
      <th style="width: 20%;">Time</th>
 | 
			
		||||
    </thead>
 | 
			
		||||
    <tbody>
 | 
			
		||||
    <tbody *ngIf="!isLoading; else loadingTmpl">
 | 
			
		||||
      <tr *ngFor="let block of blocks; trackBy: trackByFn">
 | 
			
		||||
        <td><a [routerLink]="['/block/' | relativeUrl, block.hash]" title="{{ block.hash }}" [state]="{ data: { block: block } }">{{ block.hash | shortenString : 13 }}</a></td>
 | 
			
		||||
        <td>{{ calculateTotalOutput(block) / 100 | number: '1.2-2' }}</td>
 | 
			
		||||
@ -28,3 +28,9 @@
 | 
			
		||||
  <ngb-pagination [collectionSize]="totalCount" [rotate]="true" [pageSize]="itemsPerPage" [(page)]="page" (pageChange)="pageChange(page)" [maxSize]="5" [boundaryLinks]="true"></ngb-pagination>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<ng-template #loadingTmpl>
 | 
			
		||||
  <tr *ngFor="let i of loadingItems">
 | 
			
		||||
    <td *ngFor="let j of [1, 2, 3, 4, 5]"><span class="skeleton-loader"></span></td>
 | 
			
		||||
  </tr>
 | 
			
		||||
</ng-template>
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core';
 | 
			
		||||
import { BisqApiService } from '../bisq-api.service';
 | 
			
		||||
import { switchMap } from 'rxjs/operators';
 | 
			
		||||
import { switchMap, tap } from 'rxjs/operators';
 | 
			
		||||
import { Subject } from 'rxjs';
 | 
			
		||||
import { BisqBlock, BisqOutput, BisqTransaction } from '../bisq.interfaces';
 | 
			
		||||
import { SeoService } from 'src/app/services/seo.service';
 | 
			
		||||
@ -17,6 +17,8 @@ export class BisqBlocksComponent implements OnInit {
 | 
			
		||||
  itemsPerPage: number;
 | 
			
		||||
  contentSpace = window.innerHeight - (165 + 75);
 | 
			
		||||
  fiveItemsPxSize = 250;
 | 
			
		||||
  loadingItems: number[];
 | 
			
		||||
  isLoading = true;
 | 
			
		||||
 | 
			
		||||
  pageSubject$ = new Subject<number>();
 | 
			
		||||
 | 
			
		||||
@ -28,12 +30,15 @@ export class BisqBlocksComponent implements OnInit {
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    this.seoService.setTitle('Blocks', true);
 | 
			
		||||
    this.itemsPerPage = Math.max(Math.round(this.contentSpace / this.fiveItemsPxSize) * 5, 10);
 | 
			
		||||
    this.loadingItems = Array(this.itemsPerPage);
 | 
			
		||||
 | 
			
		||||
    this.pageSubject$
 | 
			
		||||
      .pipe(
 | 
			
		||||
        tap(() => this.isLoading = true),
 | 
			
		||||
        switchMap((page) => this.bisqApiService.listBlocks$((page - 1) * 10, this.itemsPerPage))
 | 
			
		||||
      )
 | 
			
		||||
      .subscribe((response) => {
 | 
			
		||||
        this.isLoading = false;
 | 
			
		||||
        this.blocks = response.body;
 | 
			
		||||
        this.totalCount = parseInt(response.headers.get('x-total-count'), 10);
 | 
			
		||||
      }, (error) => {
 | 
			
		||||
 | 
			
		||||
@ -6,18 +6,25 @@
 | 
			
		||||
 | 
			
		||||
  <table class="table table-borderless table-striped">
 | 
			
		||||
    <thead>
 | 
			
		||||
      <th>Transaction</th>
 | 
			
		||||
      <th>Type</th>
 | 
			
		||||
      <th>Total Sent (BSQ)</th>
 | 
			
		||||
      <th>Outputs</th>
 | 
			
		||||
      <th>Block Height</th>
 | 
			
		||||
      <th>Block Time</th>
 | 
			
		||||
      <th style="width: 18%;">Transaction</th>
 | 
			
		||||
      <th style="width: 15%;">Type</th>
 | 
			
		||||
      <th style="width: 15%;">Total Sent (BSQ)</th>
 | 
			
		||||
      <th style="width: 12%;">Outputs</th>
 | 
			
		||||
      <th style="width: 15%;">Block Height</th>
 | 
			
		||||
      <th style="width: 15%;">Block Time</th>
 | 
			
		||||
    </thead>
 | 
			
		||||
    <tbody>
 | 
			
		||||
    <tbody *ngIf="!isLoading; else loadingTmpl">
 | 
			
		||||
      <tr *ngFor="let tx of transactions; trackBy: trackByFn">
 | 
			
		||||
        <td><a [routerLink]="['/tx/' | relativeUrl, tx.id]" [state]="{ bsqTx: tx }">{{ tx.id | shortenString : 16 }}</a></td>
 | 
			
		||||
        <td><app-bisq-icon class="mr-1" [txType]="tx.txType"></app-bisq-icon> {{ tx.txTypeDisplayString }}</td>
 | 
			
		||||
        <td>{{ calculateTotalOutput(tx.outputs) / 100 | number: '1.2-2' }}</td>
 | 
			
		||||
        <td>
 | 
			
		||||
          <ng-template [ngIf]="tx.txType === 'PAY_TRADE_FEE'" [ngIfElse]="defaultTxType">
 | 
			
		||||
            {{ tx.burntFee / 100 | number: '1.2-2' }}
 | 
			
		||||
          </ng-template>
 | 
			
		||||
          <ng-template #defaultTxType>
 | 
			
		||||
            {{ calculateTotalOutput(tx.outputs) / 100 | number: '1.2-2' }}
 | 
			
		||||
          </ng-template>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td>{{ tx.outputs.length }}</td>
 | 
			
		||||
        <td><a [routerLink]="['/block/' | relativeUrl, tx.blockHash]">{{ tx.blockHeight }}</a></td>
 | 
			
		||||
        <td>{{ tx.time | date:'yyyy-MM-dd HH:mm' }}</td>
 | 
			
		||||
@ -30,3 +37,9 @@
 | 
			
		||||
  <ngb-pagination [collectionSize]="totalCount" [rotate]="true" [pageSize]="itemsPerPage" [(page)]="page" (pageChange)="pageChange(page)" [maxSize]="5" [boundaryLinks]="true"></ngb-pagination>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<ng-template #loadingTmpl>
 | 
			
		||||
  <tr *ngFor="let i of loadingItems">
 | 
			
		||||
    <td *ngFor="let j of [1, 2, 3, 4, 5, 6]"><span class="skeleton-loader"></span></td>
 | 
			
		||||
  </tr>
 | 
			
		||||
</ng-template>
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import { Component, OnInit } from '@angular/core';
 | 
			
		||||
import { BisqTransaction, BisqOutput } from '../bisq.interfaces';
 | 
			
		||||
import { Subject } from 'rxjs';
 | 
			
		||||
import { switchMap } from 'rxjs/operators';
 | 
			
		||||
import { switchMap, tap } from 'rxjs/operators';
 | 
			
		||||
import { BisqApiService } from '../bisq-api.service';
 | 
			
		||||
import { SeoService } from 'src/app/services/seo.service';
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,8 @@ export class BisqTransactionsComponent implements OnInit {
 | 
			
		||||
  itemsPerPage: number;
 | 
			
		||||
  contentSpace = window.innerHeight - (165 + 75);
 | 
			
		||||
  fiveItemsPxSize = 250;
 | 
			
		||||
 | 
			
		||||
  isLoading = true;
 | 
			
		||||
  loadingItems: number[];
 | 
			
		||||
  pageSubject$ = new Subject<number>();
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
@ -29,12 +30,15 @@ export class BisqTransactionsComponent implements OnInit {
 | 
			
		||||
    this.seoService.setTitle('Transactions', true);
 | 
			
		||||
 | 
			
		||||
    this.itemsPerPage = Math.max(Math.round(this.contentSpace / this.fiveItemsPxSize) * 5, 10);
 | 
			
		||||
    this.loadingItems = Array(this.itemsPerPage);
 | 
			
		||||
 | 
			
		||||
    this.pageSubject$
 | 
			
		||||
      .pipe(
 | 
			
		||||
        tap(() => this.isLoading = true),
 | 
			
		||||
        switchMap((page) => this.bisqApiService.listTransactions$((page - 1) * 10, this.itemsPerPage))
 | 
			
		||||
      )
 | 
			
		||||
      .subscribe((response) => {
 | 
			
		||||
        this.isLoading = false;
 | 
			
		||||
        this.transactions = response.body;
 | 
			
		||||
        this.totalCount = parseInt(response.headers.get('x-total-count'), 10);
 | 
			
		||||
      }, (error) => {
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,14 @@
 | 
			
		||||
<header>
 | 
			
		||||
  <nav class="navbar navbar-expand-md navbar-dark bg-dark">
 | 
			
		||||
  <a class="navbar-brand" [routerLink]="['/' | relativeUrl]" style="position: relative;">
 | 
			
		||||
  <a class="navbar-brand" [routerLink]="['/']" style="position: relative;">
 | 
			
		||||
    <img src="./resources/mempool-logo.png" height="35" width="140" class="logo" [ngStyle]="{'opacity': connectionState === 2 ? 1 : 0.5 }">
 | 
			
		||||
    <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>
 | 
			
		||||
 | 
			
		||||
  <img *ngIf="network !== ''" src="./resources/{{ network }}-logo.png" style="width: 35.5px;" class="mr-3">
 | 
			
		||||
  <a class="navbar-brand" [routerLink]="['/' | relativeUrl]">
 | 
			
		||||
    <img *ngIf="network !== ''" src="./resources/{{ network }}-logo.png" style="width: 35.5px;">
 | 
			
		||||
  </a>
 | 
			
		||||
 | 
			
		||||
  <div class="btn-group" style="margin-right: 16px;" *ngIf="env.TESTNET_ENABLED || env.LIQUID_ENABLED || env.BISQ_ENABLED">
 | 
			
		||||
    <button type="button" (click)="networkDropdownHidden = !networkDropdownHidden" class="btn btn-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
 | 
			
		||||
@ -14,9 +16,9 @@
 | 
			
		||||
    </button>
 | 
			
		||||
    <div class="dropdown-menu" [class.d-block]="!networkDropdownHidden">
 | 
			
		||||
      <a class="dropdown-item mainnet" routerLink="/"><img src="./resources/bitcoin-logo.png" style="width: 35.5px;"> Mainnet</a>
 | 
			
		||||
      <a *ngIf="env.TESTNET_ENABLED" class="dropdown-item testnet" [class.active]="network === 'testnet'" routerLink="/testnet"><img src="./resources/testnet-logo.png" style="width: 35.5px;"> Testnet</a>
 | 
			
		||||
      <a *ngIf="env.LIQUID_ENABLED" class="dropdown-item liquid" [class.active]="network === 'liquid'" routerLink="/liquid"><img src="./resources/liquid-logo.png" style="width: 35.5px;"> Liquid</a>
 | 
			
		||||
      <a *ngIf="env.BISQ_ENABLED" class="dropdown-item mainnet" [class.active]="network === 'bisq'" routerLink="/bisq"><img src="./resources/bisq-logo.png" style="width: 35.5px;"> Bisq</a>
 | 
			
		||||
      <a *ngIf="env.TESTNET_ENABLED" class="dropdown-item testnet" [class.active]="network === 'testnet'" routerLink="/testnet"><img src="./resources/testnet-logo.png" style="width: 35.5px;"> Testnet</a>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user