Merge pull request #1503 from mempool/nymkappa/feature/additional-pool-data
Updated pool summary page to display more info on hashrate and blocks
This commit is contained in:
		
						commit
						33001ce96c
					
				@ -45,8 +45,8 @@ class Mining {
 | 
			
		||||
    const blockCount: number = await BlocksRepository.$blockCount(null, interval);
 | 
			
		||||
    poolsStatistics['blockCount'] = blockCount;
 | 
			
		||||
 | 
			
		||||
    const blockHeightTip = await bitcoinClient.getBlockCount();
 | 
			
		||||
    const lastBlockHashrate = await bitcoinClient.getNetworkHashPs(144, blockHeightTip);
 | 
			
		||||
    const totalBlock24h: number = await BlocksRepository.$blockCount(null, '24h');
 | 
			
		||||
    const lastBlockHashrate = await bitcoinClient.getNetworkHashPs(totalBlock24h);
 | 
			
		||||
    poolsStatistics['lastEstimatedHashrate'] = lastBlockHashrate;
 | 
			
		||||
 | 
			
		||||
    return poolsStatistics;
 | 
			
		||||
@ -62,12 +62,30 @@ class Mining {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const blockCount: number = await BlocksRepository.$blockCount(pool.id);
 | 
			
		||||
    const emptyBlocksCount = await BlocksRepository.$countEmptyBlocks(pool.id);
 | 
			
		||||
    const totalBlock: number = await BlocksRepository.$blockCount(null, null);
 | 
			
		||||
 | 
			
		||||
    const blockCount24h: number = await BlocksRepository.$blockCount(pool.id, '24h');
 | 
			
		||||
    const totalBlock24h: number = await BlocksRepository.$blockCount(null, '24h');
 | 
			
		||||
 | 
			
		||||
    const blockCount1w: number = await BlocksRepository.$blockCount(pool.id, '1w');
 | 
			
		||||
    const totalBlock1w: number = await BlocksRepository.$blockCount(null, '1w');
 | 
			
		||||
 | 
			
		||||
    const currentEstimatedkHashrate = await bitcoinClient.getNetworkHashPs(totalBlock24h);
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      pool: pool,
 | 
			
		||||
      blockCount: blockCount,
 | 
			
		||||
      emptyBlocks: emptyBlocksCount.length > 0 ? emptyBlocksCount[0]['count'] : 0,
 | 
			
		||||
      blockCount: {
 | 
			
		||||
        'all': blockCount,
 | 
			
		||||
        '24h': blockCount24h,
 | 
			
		||||
        '1w': blockCount1w,
 | 
			
		||||
      },
 | 
			
		||||
      blockShare: {
 | 
			
		||||
        'all': blockCount / totalBlock,
 | 
			
		||||
        '24h': blockCount24h / totalBlock24h,
 | 
			
		||||
        '1w': blockCount1w / totalBlock1w,
 | 
			
		||||
      },
 | 
			
		||||
      estimatedHashrate: currentEstimatedkHashrate * (blockCount24h / totalBlock24h),
 | 
			
		||||
      reportedHashrate: null,
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -360,23 +360,6 @@ class BlocksRepository {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Return oldest blocks height
 | 
			
		||||
   */
 | 
			
		||||
  public async $getOldestIndexedBlockHeight(): Promise<number> {
 | 
			
		||||
    const connection = await DB.getConnection();
 | 
			
		||||
    try {
 | 
			
		||||
      const [rows]: any[] = await connection.query(`SELECT MIN(height) as minHeight FROM blocks`);
 | 
			
		||||
      connection.release();
 | 
			
		||||
 | 
			
		||||
      return rows[0].minHeight;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      connection.release();
 | 
			
		||||
      logger.err('$getOldestIndexedBlockHeight() error' + (e instanceof Error ? e.message : e));
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get general block stats
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@
 | 
			
		||||
    "serve:stg": "npm run generate-config && ng serve -c staging",
 | 
			
		||||
    "serve:local-prod": "npm run generate-config && ng serve -c local-prod",
 | 
			
		||||
    "serve:local-staging": "npm run generate-config && ng serve -c local-staging",
 | 
			
		||||
    "start": "npm run generate-config && npm run sync-assets-dev && ng serve -c local",
 | 
			
		||||
    "start": "npm run generate-config && npm run sync-assets-dev && ng serve -c local --host 192.168.0.110",
 | 
			
		||||
    "start:stg": "npm run generate-config && npm run sync-assets-dev && ng serve -c staging",
 | 
			
		||||
    "start:local-prod": "npm run generate-config && npm run sync-assets-dev && ng serve -c local-prod",
 | 
			
		||||
    "start:local-staging": "npm run generate-config && npm run sync-assets-dev && ng serve -c local-staging",
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
<div class="container-xl">
 | 
			
		||||
 | 
			
		||||
  <!-- Pool overview -->
 | 
			
		||||
  <div *ngIf="poolStats$ | async as poolStats; else loadingMain">
 | 
			
		||||
    <div style="display:flex" class="mb-3">
 | 
			
		||||
      <img width="50" height="50" src="{{ poolStats['logo'] }}"
 | 
			
		||||
@ -10,22 +11,21 @@
 | 
			
		||||
    <div class="box">
 | 
			
		||||
      <div class="row">
 | 
			
		||||
 | 
			
		||||
        <div class="col-lg-9">
 | 
			
		||||
          <table class="table table-borderless table-striped" style="table-layout: fixed;">
 | 
			
		||||
        <div class="col-lg-6">
 | 
			
		||||
          <table class="table table-borderless table-striped taller" style="table-layout: fixed;">
 | 
			
		||||
            <tbody>
 | 
			
		||||
 | 
			
		||||
              <!-- Regexes desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()">
 | 
			
		||||
              <tr *ngIf="!isMobile()" class="taller-row">
 | 
			
		||||
                <td class="label" i18n="mining.tags">Tags</td>
 | 
			
		||||
                <td *ngIf="poolStats.pool.regexes.length else nodata">
 | 
			
		||||
                  {{ poolStats.pool.regexes }}
 | 
			
		||||
                <td *ngIf="poolStats.pool.regexes.length else nodata" style="vertical-align: middle">
 | 
			
		||||
                  <div class="scrollable">{{ poolStats.pool.regexes }}</div>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
              <!-- Regexes mobile -->
 | 
			
		||||
              <tr *ngIf="isMobile()">
 | 
			
		||||
                <td colspan=2>
 | 
			
		||||
                  <span i18n="mining.tags" class="label">Tags</span>
 | 
			
		||||
                  <span class="label" i18n="mining.tags">Tags</span>
 | 
			
		||||
                  <div *ngIf="poolStats.pool.regexes.length else nodatamobile" class="overflow-auto">
 | 
			
		||||
                    {{ poolStats.pool.regexes }}
 | 
			
		||||
                  </div>
 | 
			
		||||
@ -33,32 +33,35 @@
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
              <!-- Addresses desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()">
 | 
			
		||||
                <td class="label" i18n="mining.addresses">Addresses</td>
 | 
			
		||||
                <td *ngIf="poolStats.pool.addresses.length else nodata" style="padding-bottom: 0;">
 | 
			
		||||
              <tr *ngIf="!isMobile()" class="taller-row">
 | 
			
		||||
                <td class="label addresses" i18n="mining.addresses">Addresses</td>
 | 
			
		||||
                <td *ngIf="poolStats.pool.addresses.length else nodata" style="padding-top: 25px">
 | 
			
		||||
                  <a [routerLink]="['/address' | relativeUrl, poolStats.pool.addresses[0]]" class="first-address">
 | 
			
		||||
                    {{ poolStats.pool.addresses[0] }}
 | 
			
		||||
                  </a>
 | 
			
		||||
                  <button *ngIf="poolStats.pool.addresses.length >= 2" style="transform: translateY(-3px);"
 | 
			
		||||
                    type="button" class="btn btn-outline-info btn-sm float-right" (click)="collapse.toggle()"
 | 
			
		||||
                    [attr.aria-expanded]="!gfg" aria-controls="collapseExample">
 | 
			
		||||
                    <span i18n="show-all">Show all</span> ({{ poolStats.pool.addresses.length }})
 | 
			
		||||
                  </button>
 | 
			
		||||
                  <div #collapse="ngbCollapse" [(ngbCollapse)]="gfg">
 | 
			
		||||
                    <a *ngFor="let address of poolStats.pool.addresses | slice: 1"
 | 
			
		||||
                      [routerLink]="['/address' | relativeUrl, address]">{{
 | 
			
		||||
                      address }}<br></a>
 | 
			
		||||
                  <div>
 | 
			
		||||
                    <div #collapse="ngbCollapse" [(ngbCollapse)]="gfg">
 | 
			
		||||
                      <a *ngFor="let address of poolStats.pool.addresses | slice: 1"
 | 
			
		||||
                        [routerLink]="['/address' | relativeUrl, address]">{{
 | 
			
		||||
                        address }}<br></a>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <button *ngIf="poolStats.pool.addresses.length >= 2" type="button"
 | 
			
		||||
                      class="btn btn-sm btn-primary small-button" (click)="collapse.toggle()"
 | 
			
		||||
                      [attr.aria-expanded]="!gfg" aria-controls="collapseExample">
 | 
			
		||||
                      <div *ngIf="gfg"><span i18n="show-all">Show all</span> ({{ poolStats.pool.addresses.length }})
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <span *ngIf="!gfg" i18n="hide">Hide</span>
 | 
			
		||||
                    </button>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
              <!-- Addresses mobile -->
 | 
			
		||||
              <tr *ngIf="isMobile()">
 | 
			
		||||
                <td colspan=2>
 | 
			
		||||
                  <span class="label" i18n="mining.addresses">Addresses</span>
 | 
			
		||||
                  <div *ngIf="poolStats.pool.addresses.length else nodatamobile">
 | 
			
		||||
                    <button *ngIf="poolStats.pool.addresses.length >= 2" type="button"
 | 
			
		||||
                      class="btn btn-outline-info btn-sm float-right small-button" (click)="collapse.toggle()"
 | 
			
		||||
                      class="btn btn-sm btn-primary float-right small-button mobile" (click)="collapse.toggle()"
 | 
			
		||||
                      [attr.aria-expanded]="!gfg" aria-controls="collapseExample">
 | 
			
		||||
                      <span i18n="show-all">Show all</span> ({{ poolStats.pool.addresses.length }})
 | 
			
		||||
                    </button>
 | 
			
		||||
@ -77,105 +80,198 @@
 | 
			
		||||
          </table>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="col-lg-3">
 | 
			
		||||
        <div class="col-lg-6">
 | 
			
		||||
          <table class="table table-borderless table-striped">
 | 
			
		||||
            <tbody>
 | 
			
		||||
 | 
			
		||||
              <!-- Mined blocks desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()">
 | 
			
		||||
                <td class="label" i18n="mining.mined-blocks">Mined Blocks</td>
 | 
			
		||||
                <td class="data">{{ formatNumber(poolStats.blockCount, this.locale, '1.0-0') }}</td>
 | 
			
		||||
              <!-- Hashrate desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()" class="taller-row">
 | 
			
		||||
                <td class="label" i18n="mining.hashrate-24h">Hashrate (24h)</td>
 | 
			
		||||
                <td class="data">
 | 
			
		||||
                  <table class="table table-xs table-data">
 | 
			
		||||
                    <thead>
 | 
			
		||||
                      <tr>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="mining.estimated">Estimated
 | 
			
		||||
                        </th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="mining.reported">Reported
 | 
			
		||||
                        </th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 26%" i18n="mining.luck">Luck</th>
 | 
			
		||||
                      </tr>
 | 
			
		||||
                    </thead>
 | 
			
		||||
                    <tbody>
 | 
			
		||||
                      <td>{{ poolStats.estimatedHashrate | amountShortener : 1 : 'H/s' }}</td>
 | 
			
		||||
                      <ng-template *ngIf="poolStats.luck; else noreported">
 | 
			
		||||
                        <td>{{ poolStats.reportedHashrate | amountShortener : 1 : 'H/s' }}</td>
 | 
			
		||||
                        <td>{{ formatNumber(poolStats.luck, this.locale, '1.2-2') }}%</td>
 | 
			
		||||
                      </ng-template>
 | 
			
		||||
                    </tbody>
 | 
			
		||||
                  </table>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
              <!-- Mined blocks desktop -->
 | 
			
		||||
              <!-- Hashrate mobile -->
 | 
			
		||||
              <tr *ngIf="isMobile()">
 | 
			
		||||
                <td colspan=2>
 | 
			
		||||
                  <span class="label" i18n="mining.mined-blocks">Mined Blocks</span>
 | 
			
		||||
                  <div>{{ formatNumber(poolStats.blockCount, this.locale, '1.0-0') }}</div>
 | 
			
		||||
                <td colspan="2">
 | 
			
		||||
                  <span class="label" i18n="mining.hashrate-24h">Hashrate (24h)</span>
 | 
			
		||||
                  <table class="table table-xs table-data">
 | 
			
		||||
                    <thead>
 | 
			
		||||
                      <tr>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 33%" i18n="mining.estimated">Estimated
 | 
			
		||||
                        </th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="mining.reported">Reported
 | 
			
		||||
                        </th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 30%" i18n="mining.luck">Luck</th>
 | 
			
		||||
                      </tr>
 | 
			
		||||
                    </thead>
 | 
			
		||||
                    <tbody>
 | 
			
		||||
                      <td>{{ poolStats.estimatedHashrate | amountShortener : 1 : 'H/s' }}</td>
 | 
			
		||||
                      <ng-template *ngIf="poolStats.luck; else noreported">
 | 
			
		||||
                        <td>{{ poolStats.reportedHashrate | amountShortener : 1 : 'H/s' }}</td>
 | 
			
		||||
                        <td>{{ formatNumber(poolStats.luck, this.locale, '1.2-2') }}%</td>
 | 
			
		||||
                      </ng-template>
 | 
			
		||||
                    </tbody>
 | 
			
		||||
                  </table>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
              <!-- Empty blocks desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()">
 | 
			
		||||
                <td class="label" i18n="mining.empty-blocks">Empty Blocks</td>
 | 
			
		||||
                <td class="data">{{ formatNumber(poolStats.emptyBlocks, this.locale, '1.0-0') }}</td>
 | 
			
		||||
              <ng-template #noreported>
 | 
			
		||||
                <td>~</td>
 | 
			
		||||
                <td>~</td>
 | 
			
		||||
              </ng-template>
 | 
			
		||||
 | 
			
		||||
              <!-- Mined blocks desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()" class="taller-row">
 | 
			
		||||
                <td class="label" i18n="mining.mined-blocks">Mined Blocks</td>
 | 
			
		||||
                <td class="data">
 | 
			
		||||
                  <table class="table table-xs table-data">
 | 
			
		||||
                    <thead>
 | 
			
		||||
                      <tr>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="24h">24h</th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="1w">1w</th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 26%" i18n="all">All</th>
 | 
			
		||||
                      </tr>
 | 
			
		||||
                    </thead>
 | 
			
		||||
                    <tbody>
 | 
			
		||||
                      <td>{{ formatNumber(poolStats.blockCount['24h'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
 | 
			
		||||
                        poolStats.blockShare['24h'], this.locale, '1.0-0') }}%)</td>
 | 
			
		||||
                      <td>{{ formatNumber(poolStats.blockCount['1w'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
 | 
			
		||||
                        poolStats.blockShare['1w'], this.locale, '1.0-0') }}%)</td>
 | 
			
		||||
                      <td>{{ formatNumber(poolStats.blockCount['all'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
 | 
			
		||||
                        poolStats.blockShare['all'], this.locale, '1.0-0') }}%)</td>
 | 
			
		||||
                    </tbody>
 | 
			
		||||
                  </table>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
              <!-- Empty blocks mobile -->
 | 
			
		||||
              <!-- Mined blocks mobile -->
 | 
			
		||||
              <tr *ngIf="isMobile()">
 | 
			
		||||
                <td colspan="2">
 | 
			
		||||
                  <span class="label" i18n="mining.empty-blocks">Empty Blocks</span>
 | 
			
		||||
                  <div>{{ formatNumber(poolStats.emptyBlocks, this.locale, '1.0-0') }}</div>
 | 
			
		||||
                <td colspan=2>
 | 
			
		||||
                  <span class="label" i18n="mining.mined-blocks">Mined Blocks</span>
 | 
			
		||||
                  <table class="table table-xs table-data">
 | 
			
		||||
                    <thead>
 | 
			
		||||
                      <tr>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 33%" i18n="24h">24h</th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="1w">1w</th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 30%" i18n="all">All</th>
 | 
			
		||||
                      </tr>
 | 
			
		||||
                    </thead>
 | 
			
		||||
                    <tbody>
 | 
			
		||||
                      <td>{{ formatNumber(poolStats.blockCount['24h'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
 | 
			
		||||
                        poolStats.blockShare['24h'], this.locale, '1.0-0') }}%)</td>
 | 
			
		||||
                      <td>{{ formatNumber(poolStats.blockCount['1w'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
 | 
			
		||||
                        poolStats.blockShare['1w'], this.locale, '1.0-0') }}%)</td>
 | 
			
		||||
                      <td>{{ formatNumber(poolStats.blockCount['all'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
 | 
			
		||||
                        poolStats.blockShare['all'], this.locale, '1.0-0') }}%)</td>
 | 
			
		||||
                    </tbody>
 | 
			
		||||
                  </table>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
            </tbody>
 | 
			
		||||
          </table>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <ng-template #nodata>
 | 
			
		||||
    <td>~</td>
 | 
			
		||||
    <td class="taller-row" style="vertical-align: middle">~</td>
 | 
			
		||||
  </ng-template>
 | 
			
		||||
  <ng-template #nodatamobile>
 | 
			
		||||
    <div>~</div>
 | 
			
		||||
  </ng-template>
 | 
			
		||||
 | 
			
		||||
  <!-- Hashrate chart -->
 | 
			
		||||
  <div class="chart" echarts [initOpts]="chartInitOptions" [options]="chartOptions"></div>
 | 
			
		||||
  <div class="text-center loadingGraphs" *ngIf="isLoading">
 | 
			
		||||
    <div class="spinner-border text-light"></div>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <!-- Blocks list -->
 | 
			
		||||
  <table class="table table-borderless" [alwaysCallback]="true" infiniteScroll [infiniteScrollDistance]="1.5"
 | 
			
		||||
    [infiniteScrollUpDistance]="1.5" [infiniteScrollThrottle]="50" (scrolled)="loadMore()">
 | 
			
		||||
    <thead>
 | 
			
		||||
      <th class="height" i18n="latest-blocks.height">Height</th>
 | 
			
		||||
      <th class="timestamp" i18n="latest-blocks.timestamp">Timestamp</th>
 | 
			
		||||
      <th class="mined" i18n="latest-blocks.mined">Mined</th>
 | 
			
		||||
      <th class="coinbase text-left" i18n="latest-blocks.coinbasetag">
 | 
			
		||||
        Coinbase Tag</th>
 | 
			
		||||
      <th class="reward text-right" i18n="latest-blocks.reward">
 | 
			
		||||
        Reward</th>
 | 
			
		||||
      <th class="fees text-right" i18n="latest-blocks.fees">Fees</th>
 | 
			
		||||
      <th class="txs text-right" i18n="latest-blocks.transactions">Txs</th>
 | 
			
		||||
      <th class="size" i18n="latest-blocks.size">Size</th>
 | 
			
		||||
    </thead>
 | 
			
		||||
    <tbody *ngIf="blocks$ | async as blocks; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
 | 
			
		||||
      <tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock">
 | 
			
		||||
        <td class="height">
 | 
			
		||||
          <a [routerLink]="['/block' | relativeUrl, block.height]">{{ block.height
 | 
			
		||||
            }}</a>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td class="timestamp">
 | 
			
		||||
          ‎{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }}
 | 
			
		||||
        </td>
 | 
			
		||||
        <td class="mined">
 | 
			
		||||
          <app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td class="coinbase">
 | 
			
		||||
          <span class="badge badge-secondary scriptmessage longer">
 | 
			
		||||
            {{ block.extras.coinbaseRaw | hex2ascii }}
 | 
			
		||||
          </span>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td class="reward text-right">
 | 
			
		||||
          <app-amount [satoshis]="block.extras.reward" digitsInfo="1.2-2"></app-amount>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td class="fees text-right">
 | 
			
		||||
          <app-amount [satoshis]="block.extras.totalFees" digitsInfo="1.2-2"></app-amount>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td class="txs text-right">
 | 
			
		||||
          {{ block.tx_count | number }}
 | 
			
		||||
        </td>
 | 
			
		||||
        <td class="size">
 | 
			
		||||
          <div class="progress">
 | 
			
		||||
            <div class="progress-bar progress-mempool" role="progressbar"
 | 
			
		||||
              [ngStyle]="{'width': (block.weight / stateService.env.BLOCK_WEIGHT_UNITS)*100 + '%' }"></div>
 | 
			
		||||
            <div class="progress-text" [innerHTML]="block.size | bytes: 2"></div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </td>
 | 
			
		||||
      </tr>
 | 
			
		||||
    </tbody>
 | 
			
		||||
    <ng-container *ngIf="blocks$ | async as blocks; else skeleton">
 | 
			
		||||
      <thead *ngIf="blocks.length > 0">
 | 
			
		||||
        <th class="height" i18n="latest-blocks.height">Height</th>
 | 
			
		||||
        <th class="timestamp" i18n="latest-blocks.timestamp">Timestamp</th>
 | 
			
		||||
        <th class="mined" i18n="latest-blocks.mined">Mined</th>
 | 
			
		||||
        <th class="coinbase text-left" i18n="latest-blocks.coinbasetag">
 | 
			
		||||
          Coinbase Tag</th>
 | 
			
		||||
        <th class="reward text-right" i18n="latest-blocks.reward">
 | 
			
		||||
          Reward</th>
 | 
			
		||||
        <th class="fees text-right" i18n="latest-blocks.fees">Fees</th>
 | 
			
		||||
        <th class="txs text-right" i18n="latest-blocks.transactions">Txs</th>
 | 
			
		||||
        <th class="size" i18n="latest-blocks.size">Size</th>
 | 
			
		||||
      </thead>
 | 
			
		||||
      <tbody [style]="isLoading ? 'opacity: 0.75' : ''">
 | 
			
		||||
        <tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock">
 | 
			
		||||
          <td class="height">
 | 
			
		||||
            <a [routerLink]="['/block' | relativeUrl, block.height]">{{ block.height
 | 
			
		||||
              }}</a>
 | 
			
		||||
          </td>
 | 
			
		||||
          <td class="timestamp">
 | 
			
		||||
            ‎{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }}
 | 
			
		||||
          </td>
 | 
			
		||||
          <td class="mined">
 | 
			
		||||
            <app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since>
 | 
			
		||||
          </td>
 | 
			
		||||
          <td class="coinbase">
 | 
			
		||||
            <span class="badge badge-secondary scriptmessage longer">
 | 
			
		||||
              {{ block.extras.coinbaseRaw | hex2ascii }}
 | 
			
		||||
            </span>
 | 
			
		||||
          </td>
 | 
			
		||||
          <td class="reward text-right">
 | 
			
		||||
            <app-amount [satoshis]="block.extras.reward" digitsInfo="1.2-2"></app-amount>
 | 
			
		||||
          </td>
 | 
			
		||||
          <td class="fees text-right">
 | 
			
		||||
            <app-amount [satoshis]="block.extras.totalFees" digitsInfo="1.2-2"></app-amount>
 | 
			
		||||
          </td>
 | 
			
		||||
          <td class="txs text-right">
 | 
			
		||||
            {{ block.tx_count | number }}
 | 
			
		||||
          </td>
 | 
			
		||||
          <td class="size">
 | 
			
		||||
            <div class="progress">
 | 
			
		||||
              <div class="progress-bar progress-mempool" role="progressbar"
 | 
			
		||||
                [ngStyle]="{'width': (block.weight / stateService.env.BLOCK_WEIGHT_UNITS)*100 + '%' }"></div>
 | 
			
		||||
              <div class="progress-text" [innerHTML]="block.size | bytes: 2"></div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
      </tbody>
 | 
			
		||||
    </ng-container>
 | 
			
		||||
 | 
			
		||||
    <ng-template #skeleton>
 | 
			
		||||
      <thead>
 | 
			
		||||
        <th class="height" i18n="latest-blocks.height">Height</th>
 | 
			
		||||
        <th class="timestamp" i18n="latest-blocks.timestamp">Timestamp</th>
 | 
			
		||||
        <th class="mined" i18n="latest-blocks.mined">Mined</th>
 | 
			
		||||
        <th class="coinbase text-left" i18n="latest-blocks.coinbasetag">
 | 
			
		||||
          Coinbase Tag</th>
 | 
			
		||||
        <th class="reward text-right" i18n="latest-blocks.reward">
 | 
			
		||||
          Reward</th>
 | 
			
		||||
        <th class="fees text-right" i18n="latest-blocks.fees">Fees</th>
 | 
			
		||||
        <th class="txs text-right" i18n="latest-blocks.transactions">Txs</th>
 | 
			
		||||
        <th class="size" i18n="latest-blocks.size">Size</th>
 | 
			
		||||
      </thead>
 | 
			
		||||
      <tbody>
 | 
			
		||||
        <tr *ngFor="let item of [1,2,3,4,5]">
 | 
			
		||||
          <td class="height">
 | 
			
		||||
@ -209,6 +305,7 @@
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<!-- Main table skeleton -->
 | 
			
		||||
<ng-template #loadingMain>
 | 
			
		||||
  <div>
 | 
			
		||||
    <div class="mb-3" style="display:flex; position: relative">
 | 
			
		||||
@ -220,18 +317,18 @@
 | 
			
		||||
 | 
			
		||||
    <div class="box">
 | 
			
		||||
      <div class="row">
 | 
			
		||||
        <div class="col-lg-9">
 | 
			
		||||
          <table class="table table-borderless table-striped">
 | 
			
		||||
 | 
			
		||||
        <div class="col-lg-6">
 | 
			
		||||
          <table class="table table-borderless table-striped taller" style="table-layout: fixed;">
 | 
			
		||||
            <tbody>
 | 
			
		||||
 | 
			
		||||
              <!-- Regexes desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()">
 | 
			
		||||
              <tr *ngIf="!isMobile()" class="taller-row">
 | 
			
		||||
                <td class="label" i18n="mining.tags">Tags</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                <td style="vertical-align: middle">
 | 
			
		||||
                  <div class="skeleton-loader"></div>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
              <!-- Regexes mobile -->
 | 
			
		||||
              <tr *ngIf="isMobile()">
 | 
			
		||||
                <td colspan=2>
 | 
			
		||||
@ -243,71 +340,149 @@
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
              <!-- Addresses desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()">
 | 
			
		||||
              <tr *ngIf="!isMobile()" class="taller-row">
 | 
			
		||||
                <td class="label" i18n="mining.addresses">Addresses</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                <td style="vertical-align: middle;">
 | 
			
		||||
                  <div class="skeleton-loader"></div>
 | 
			
		||||
                  <div #collapse="ngbCollapse" [(ngbCollapse)]="gfg">
 | 
			
		||||
                    <div class="skeleton-loader"></div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </td>
 | 
			
		||||
                <ng-template #nodata>
 | 
			
		||||
                  <td>~</td>
 | 
			
		||||
                </ng-template>
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
              <!-- Addresses mobile -->
 | 
			
		||||
              <tr *ngIf="isMobile()">
 | 
			
		||||
                <td colspan=2>
 | 
			
		||||
                  <span class="label" i18n="mining.addresses">Addresses</span>
 | 
			
		||||
                  <div>
 | 
			
		||||
                    <div class="skeleton-loader"></div>
 | 
			
		||||
                    <div #collapse="ngbCollapse" [(ngbCollapse)]="gfg" style="width: 100%">
 | 
			
		||||
                      <div class="skeleton-loader"></div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
            </tbody>
 | 
			
		||||
          </table>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="col-lg-3">
 | 
			
		||||
        <div class="col-lg-6">
 | 
			
		||||
          <table class="table table-borderless table-striped">
 | 
			
		||||
            <tbody>
 | 
			
		||||
 | 
			
		||||
              <!-- Mined blocks desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()">
 | 
			
		||||
                <td class="label" i18n="mining.mined-blocks">Mined Blocks</td>
 | 
			
		||||
              <!-- Hashrate desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()" class="taller-row">
 | 
			
		||||
                <td class="label" i18n="mining.hashrate-24h">Hashrate (24h)</td>
 | 
			
		||||
                <td class="data">
 | 
			
		||||
                  <div class="skeleton-loader"></div>
 | 
			
		||||
                  <table class="table table-xs table-data text-center">
 | 
			
		||||
                    <thead>
 | 
			
		||||
                      <tr>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="mining.estimated">Estimated
 | 
			
		||||
                        </th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="mining.reported">Reported
 | 
			
		||||
                        </th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 26%" i18n="mining.luck">Luck</th>
 | 
			
		||||
                      </tr>
 | 
			
		||||
                    </thead>
 | 
			
		||||
                    <tbody>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                    </tbody>
 | 
			
		||||
                  </table>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
              <!-- Mined blocks desktop -->
 | 
			
		||||
              <!-- Hashrate mobile -->
 | 
			
		||||
              <tr *ngIf="isMobile()">
 | 
			
		||||
                <td colspan=2>
 | 
			
		||||
                  <span class="label" i18n="mining.mined-blocks">Mined Blocks</span>
 | 
			
		||||
                  <div>
 | 
			
		||||
                    <div class="skeleton-loader"></div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                <td colspan="2">
 | 
			
		||||
                  <span class="label" i18n="mining.hashrate-24h">Hashrate (24h)</span>
 | 
			
		||||
                  <table class="table table-xs table-data text-center">
 | 
			
		||||
                    <thead>
 | 
			
		||||
                      <tr>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 33%" i18n="mining.estimated">Estimated
 | 
			
		||||
                        </th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="mining.reported">Reported
 | 
			
		||||
                        </th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 30%" i18n="mining.luck">Luck</th>
 | 
			
		||||
                      </tr>
 | 
			
		||||
                    </thead>
 | 
			
		||||
                    <tbody>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                    </tbody>
 | 
			
		||||
                  </table>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
              <!-- Empty blocks desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()">
 | 
			
		||||
                <td class="label" i18n="mining.empty-blocks">Empty Blocks</td>
 | 
			
		||||
              <!-- Mined blocks desktop -->
 | 
			
		||||
              <tr *ngIf="!isMobile()" class="taller-row">
 | 
			
		||||
                <td class="label" i18n="mining.mined-blocks">Mined Blocks</td>
 | 
			
		||||
                <td class="data">
 | 
			
		||||
                  <div class="skeleton-loader"></div>
 | 
			
		||||
                  <table class="table table-xs table-data text-center">
 | 
			
		||||
                    <thead>
 | 
			
		||||
                      <tr>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="24h">24h</th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="1w">1w</th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 26%" i18n="all">All</th>
 | 
			
		||||
                      </tr>
 | 
			
		||||
                    </thead>
 | 
			
		||||
                    <tbody>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                    </tbody>
 | 
			
		||||
                  </table>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
              <!-- Empty blocks mobile -->
 | 
			
		||||
              <!-- Mined blocks mobile -->
 | 
			
		||||
              <tr *ngIf="isMobile()">
 | 
			
		||||
                <td colspan="2">
 | 
			
		||||
                  <span class="label" i18n="mining.empty-blocks">Empty Blocks</span>
 | 
			
		||||
                  <div>
 | 
			
		||||
                    <div class="skeleton-loader"></div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                <td colspan=2>
 | 
			
		||||
                  <span class="label" i18n="mining.mined-blocks">Mined Blocks</span>
 | 
			
		||||
                  <table class="table table-xs table-data text-center">
 | 
			
		||||
                    <thead>
 | 
			
		||||
                      <tr>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 33%" i18n="24h">24h</th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 37%" i18n="1w">1w</th>
 | 
			
		||||
                        <th scope="col" class="block-count-title" style="width: 30%" i18n="all">All</th>
 | 
			
		||||
                      </tr>
 | 
			
		||||
                    </thead>
 | 
			
		||||
                    <tbody>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                      <td>
 | 
			
		||||
                        <div class="skeleton-loader data"></div>
 | 
			
		||||
                      </td>
 | 
			
		||||
                    </tbody>
 | 
			
		||||
                  </table>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
            </tbody>
 | 
			
		||||
          </table>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
@ -36,6 +36,7 @@
 | 
			
		||||
  @media (max-width: 768px) {
 | 
			
		||||
    margin-bottom: 10px;
 | 
			
		||||
  }
 | 
			
		||||
  height: 400px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
div.scrollable {
 | 
			
		||||
@ -49,18 +50,28 @@ div.scrollable {
 | 
			
		||||
 | 
			
		||||
.box {
 | 
			
		||||
  padding-bottom: 5px;
 | 
			
		||||
  @media (min-width: 767.98px) {
 | 
			
		||||
    min-height: 187px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.label {
 | 
			
		||||
  width: 30%;
 | 
			
		||||
  width: 25%;
 | 
			
		||||
  @media (min-width: 767.98px) {
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
  }
 | 
			
		||||
  @media (max-width: 767.98px) {
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.label.addresses {
 | 
			
		||||
  vertical-align: top;
 | 
			
		||||
  padding-top: 25px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.data {
 | 
			
		||||
  text-align: right;
 | 
			
		||||
  padding-left: 25%;
 | 
			
		||||
  padding-left: 5%;
 | 
			
		||||
  @media (max-width: 992px) {
 | 
			
		||||
    text-align: left;
 | 
			
		||||
    padding-left: 12px;
 | 
			
		||||
@ -114,10 +125,6 @@ div.scrollable {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.fees {
 | 
			
		||||
  width: 0%;  
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.size {
 | 
			
		||||
  width: 12%;
 | 
			
		||||
  @media (max-width: 1000px) {
 | 
			
		||||
@ -146,6 +153,10 @@ div.scrollable {
 | 
			
		||||
.skeleton-loader {
 | 
			
		||||
  max-width: 200px;
 | 
			
		||||
}
 | 
			
		||||
.skeleton-loader.data {
 | 
			
		||||
  max-width: 70px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.loadingGraphs {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
@ -159,8 +170,38 @@ div.scrollable {
 | 
			
		||||
 | 
			
		||||
.small-button {
 | 
			
		||||
  height: 20px;
 | 
			
		||||
  transform: translateY(-20px);
 | 
			
		||||
  font-size: 10px;
 | 
			
		||||
  padding-top: 0;
 | 
			
		||||
  padding-bottom: 0;
 | 
			
		||||
  outline: none;
 | 
			
		||||
  box-shadow: none;
 | 
			
		||||
}
 | 
			
		||||
.small-button.mobile {
 | 
			
		||||
  transform: translateY(-20px);
 | 
			
		||||
  @media (min-width: 767.98px) {
 | 
			
		||||
    transform: translateY(-17px);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.block-count-title {
 | 
			
		||||
  color: #4a68b9;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  text-align: left;
 | 
			
		||||
  @media (max-width: 767.98px) {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.table-data tr {
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
}
 | 
			
		||||
.table-data td {
 | 
			
		||||
  text-align: left;
 | 
			
		||||
  @media (max-width: 767.98px) {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.taller-row {
 | 
			
		||||
  height: 75px;
 | 
			
		||||
}
 | 
			
		||||
@ -8,6 +8,7 @@ import { ApiService } from 'src/app/services/api.service';
 | 
			
		||||
import { StateService } from 'src/app/services/state.service';
 | 
			
		||||
import { selectPowerOfTen } from 'src/app/bitcoin.utils';
 | 
			
		||||
import { formatNumber } from '@angular/common';
 | 
			
		||||
import { SeoService } from 'src/app/services/seo.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-pool',
 | 
			
		||||
@ -41,6 +42,7 @@ export class PoolComponent implements OnInit {
 | 
			
		||||
    private apiService: ApiService,
 | 
			
		||||
    private route: ActivatedRoute,
 | 
			
		||||
    public stateService: StateService,
 | 
			
		||||
    private seoService: SeoService,
 | 
			
		||||
  ) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -66,6 +68,7 @@ export class PoolComponent implements OnInit {
 | 
			
		||||
          this.loadMoreSubject.next(this.blocks[this.blocks.length - 1]?.height);
 | 
			
		||||
        }),
 | 
			
		||||
        map((poolStats) => {
 | 
			
		||||
          this.seoService.setTitle(poolStats.pool.name);
 | 
			
		||||
          let regexes = '"';
 | 
			
		||||
          for (const regex of poolStats.pool.regexes) {
 | 
			
		||||
            regexes += regex + '", "';
 | 
			
		||||
@ -73,6 +76,10 @@ export class PoolComponent implements OnInit {
 | 
			
		||||
          poolStats.pool.regexes = regexes.slice(0, -3);
 | 
			
		||||
          poolStats.pool.addresses = poolStats.pool.addresses;
 | 
			
		||||
 | 
			
		||||
          if (poolStats.reportedHashrate) {
 | 
			
		||||
            poolStats.luck = poolStats.estimatedHashrate / poolStats.reportedHashrate * 100;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          return Object.assign({
 | 
			
		||||
            logo: `./resources/mining-pools/` + poolStats.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg'
 | 
			
		||||
          }, poolStats);
 | 
			
		||||
@ -97,7 +104,21 @@ export class PoolComponent implements OnInit {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  prepareChartOptions(data) {
 | 
			
		||||
    let title: object;
 | 
			
		||||
    if (data.length === 0) {
 | 
			
		||||
      title = {
 | 
			
		||||
        textStyle: {
 | 
			
		||||
          color: 'grey',
 | 
			
		||||
          fontSize: 15
 | 
			
		||||
        },
 | 
			
		||||
        text: `No data`,
 | 
			
		||||
        left: 'center',
 | 
			
		||||
        top: 'center'
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.chartOptions = {
 | 
			
		||||
      title: title,
 | 
			
		||||
      animation: false,
 | 
			
		||||
      color: [
 | 
			
		||||
        new graphic.LinearGradient(0, 0, 0, 0.65, [
 | 
			
		||||
@ -178,7 +199,7 @@ export class PoolComponent implements OnInit {
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      ],
 | 
			
		||||
      dataZoom: [{
 | 
			
		||||
      dataZoom: data.length === 0 ? undefined : [{
 | 
			
		||||
        type: 'inside',
 | 
			
		||||
        realtime: true,
 | 
			
		||||
        zoomLock: true,
 | 
			
		||||
 | 
			
		||||
@ -93,8 +93,19 @@ export interface PoolInfo {
 | 
			
		||||
}
 | 
			
		||||
export interface PoolStat {
 | 
			
		||||
  pool: PoolInfo;
 | 
			
		||||
  blockCount: number;
 | 
			
		||||
  emptyBlocks: number;
 | 
			
		||||
  blockCount: {
 | 
			
		||||
    all: number,
 | 
			
		||||
    '24h': number,
 | 
			
		||||
    '1w': number,
 | 
			
		||||
  };
 | 
			
		||||
  blockShare: {
 | 
			
		||||
    all: number,
 | 
			
		||||
    '24h': number,
 | 
			
		||||
    '1w': number,
 | 
			
		||||
  };
 | 
			
		||||
  estimatedHashrate: number;
 | 
			
		||||
  reportedHashrate: number;
 | 
			
		||||
  luck?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface BlockExtension {
 | 
			
		||||
 | 
			
		||||
@ -4,8 +4,9 @@ import { Pipe, PipeTransform } from '@angular/core';
 | 
			
		||||
  name: 'amountShortener'
 | 
			
		||||
})
 | 
			
		||||
export class AmountShortenerPipe implements PipeTransform {
 | 
			
		||||
  transform(num: number, ...args: number[]): unknown {
 | 
			
		||||
  transform(num: number, ...args: any[]): unknown {
 | 
			
		||||
    const digits = args[0] || 1;
 | 
			
		||||
    const unit = args[1] || undefined;
 | 
			
		||||
 | 
			
		||||
    if (num < 1000) {
 | 
			
		||||
      return num.toFixed(digits);
 | 
			
		||||
@ -21,7 +22,12 @@ export class AmountShortenerPipe implements PipeTransform {
 | 
			
		||||
      { value: 1e18, symbol: 'E' }
 | 
			
		||||
    ];
 | 
			
		||||
    const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
 | 
			
		||||
    var item = lookup.slice().reverse().find((item) => num >= item.value);
 | 
			
		||||
    return item ? (num / item.value).toFixed(digits).replace(rx, '$1') + item.symbol : '0';
 | 
			
		||||
    const item = lookup.slice().reverse().find((item) => num >= item.value);
 | 
			
		||||
 | 
			
		||||
    if (unit !== undefined) {
 | 
			
		||||
      return item ? (num / item.value).toFixed(digits).replace(rx, '$1') + ' ' + item.symbol + unit : '0';
 | 
			
		||||
    } else {
 | 
			
		||||
      return item ? (num / item.value).toFixed(digits).replace(rx, '$1') + item.symbol : '0';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user