Merge pull request #1986 from knorrium/mining_e2e_tests_v2
Mining e2e tests
This commit is contained in:
		
						commit
						76b6f72f04
					
				
							
								
								
									
										171
									
								
								frontend/cypress/e2e/mainnet/mining.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								frontend/cypress/e2e/mainnet/mining.spec.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,171 @@
 | 
			
		||||
const baseModule = Cypress.env("BASE_MODULE");
 | 
			
		||||
 | 
			
		||||
describe('Mainnet - Mining Features', () => {
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    //https://github.com/cypress-io/cypress/issues/14459
 | 
			
		||||
    if (Cypress.browser.family === 'chromium') {
 | 
			
		||||
      Cypress.automation('remote:debugger:protocol', {
 | 
			
		||||
        command: 'Network.enable',
 | 
			
		||||
        params: {}
 | 
			
		||||
      });
 | 
			
		||||
      Cypress.automation('remote:debugger:protocol', {
 | 
			
		||||
        command: 'Network.setCacheDisabled',
 | 
			
		||||
        params: { cacheDisabled: true }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  if (baseModule === 'mempool') {
 | 
			
		||||
 | 
			
		||||
    describe('Miner page', () => {
 | 
			
		||||
      beforeEach(() => {
 | 
			
		||||
        cy.intercept('/api/v1/mining/pool/**').as('pool');
 | 
			
		||||
        cy.intercept('/api/v1/mining/hashrate/pools/**').as('hashrate');
 | 
			
		||||
        cy.intercept('/api/tx/**').as('tx');
 | 
			
		||||
        cy.intercept('/api/v1/outpends/**').as('outspends');
 | 
			
		||||
      });
 | 
			
		||||
      it('loads the mining pool page from the dashboard', () => {
 | 
			
		||||
        cy.visit('/mining');
 | 
			
		||||
        cy.waitForSkeletonGone();
 | 
			
		||||
        cy.get('[data-cy="bitcoin-block-0-pool"]').click().then(() => {
 | 
			
		||||
          cy.waitForSkeletonGone();
 | 
			
		||||
          cy.wait('@pool');
 | 
			
		||||
          cy.url().should('match', /\/mining\/pool\/(\w+)/);
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      it('loads the mining pool page from the blocks page', () => {
 | 
			
		||||
        cy.visit('/mining');
 | 
			
		||||
        cy.waitForSkeletonGone();
 | 
			
		||||
        cy.get('[data-cy="bitcoin-block-0-height"]').click().then(() => {
 | 
			
		||||
          cy.waitForSkeletonGone();
 | 
			
		||||
          cy.get('[data-cy="block-details-miner-badge"]').click().then(() => {
 | 
			
		||||
            cy.waitForSkeletonGone();
 | 
			
		||||
            cy.wait('@pool');
 | 
			
		||||
            cy.url().should('match', /\/mining\/pool\/(\w+)/);
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('Mining Dashboard Landing page widgets', () => {
 | 
			
		||||
 | 
			
		||||
      beforeEach(() => {
 | 
			
		||||
        cy.visit('/mining');
 | 
			
		||||
        cy.waitForSkeletonGone();
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      it('shows the mempool blocks', () => {
 | 
			
		||||
        cy.get('[data-cy="mempool-block-0-fees"]').invoke('text').should('match', /~(.*) sat\/vB/);
 | 
			
		||||
        cy.get('[data-cy="mempool-block-0-fee-span"]').invoke('text').should('match', /(.*) - (.*) sat\/vB/);
 | 
			
		||||
        cy.get('[data-cy="mempool-block-0-total-fees"]').invoke('text').should('match', /(.*) BTC/);
 | 
			
		||||
        cy.get('[data-cy="mempool-block-0-transaction-count"]').invoke('text').should('match', /(.*) transactions/);
 | 
			
		||||
        cy.get('[data-cy="mempool-block-0-time"]').invoke('text').should('match', /In ~(.*) minutes/);
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      it('shows the mined blocks', () => {
 | 
			
		||||
        cy.get('[data-cy="bitcoin-block-0-height"]').invoke('text').should('match', /(\d)/);
 | 
			
		||||
        cy.get('[data-cy="bitcoin-block-0-fees"]').invoke('text').should('match', /~(.*) sat\/vB/);
 | 
			
		||||
        cy.get('[data-cy="bitcoin-block-0-fee-span"]').invoke('text').should('match', /(.*) - (.*) sat\/vB/);
 | 
			
		||||
        cy.get('[data-cy="bitcoin-block-0-total-fees"]').invoke('text').should('match', /(.*) BTC/);
 | 
			
		||||
        cy.get('[data-cy="bitcoin-block-0-transactions"]').invoke('text').should('match', /(.*) transactions/);
 | 
			
		||||
        cy.get('[data-cy="bitcoin-block-0-time"]').invoke('text').should('match', /((.*) ago|Just now)/);
 | 
			
		||||
        cy.get('[data-cy="bitcoin-block-0-pool"]').invoke('text').should('match', /(\w)/);
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      it('shows the reward stats for the last 144 blocks', () => {
 | 
			
		||||
        cy.get('[data-cy="reward-stats"]');
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      it('shows the difficulty adjustment stats', () => {
 | 
			
		||||
        cy.get('[data-cy="difficulty-adjustment"]');
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      it('shows the latest blocks', () => {
 | 
			
		||||
        cy.get('[data-cy="latest-blocks"]');
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      it('shows the pools pie chart', () => {
 | 
			
		||||
        cy.get('[data-cy="pool-distribution"]');
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      it('shows the hashrate graph', () => {
 | 
			
		||||
        cy.get('[data-cy="hashrate-graph"]');
 | 
			
		||||
      });
 | 
			
		||||
      it('shows the latest blocks', () => {
 | 
			
		||||
        cy.get('[data-cy="latest-blocks"]');
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      it('shows the latest adjustments', () => {
 | 
			
		||||
        cy.get('[data-cy="difficulty-adjustments-table"]');
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe.only('mining graphs', () => {
 | 
			
		||||
      describe('pools ranking', () => {
 | 
			
		||||
        it('loads the graph', () => {
 | 
			
		||||
          cy.visit('/graphs/mining/pools');
 | 
			
		||||
          cy.waitForSkeletonGone();
 | 
			
		||||
          cy.waitForPageIdle();
 | 
			
		||||
          cy.get('.spinner-border').should('not.exist');
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      describe('pools dominance', () => {
 | 
			
		||||
        it('loads the graph', () => {
 | 
			
		||||
          cy.visit('/graphs/mining/pools-dominance');
 | 
			
		||||
          cy.waitForSkeletonGone();
 | 
			
		||||
          cy.waitForPageIdle();
 | 
			
		||||
          cy.get('.spinner-border').should('not.exist');
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      describe('hashrate & difficulty', () => {
 | 
			
		||||
        it('loads the graph', () => {
 | 
			
		||||
          cy.visit('/graphs/mining/hashrate-difficulty');
 | 
			
		||||
          cy.waitForSkeletonGone();
 | 
			
		||||
          cy.waitForPageIdle();
 | 
			
		||||
          cy.get('.spinner-border').should('not.exist');
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      describe('block fee rates', () => {
 | 
			
		||||
        it('loads the graph', () => {
 | 
			
		||||
          cy.visit('/graphs/mining/block-fee-rates');
 | 
			
		||||
          cy.waitForSkeletonGone();
 | 
			
		||||
          cy.waitForPageIdle();
 | 
			
		||||
          cy.get('.spinner-border').should('not.exist');
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      describe('block fees', () => {
 | 
			
		||||
        it('loads the graph', () => {
 | 
			
		||||
          cy.visit('/graphs/mining/block-fees');
 | 
			
		||||
          cy.waitForSkeletonGone();
 | 
			
		||||
          cy.waitForPageIdle();
 | 
			
		||||
          cy.get('.spinner-border').should('not.exist');
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      describe('block rewards', () => {
 | 
			
		||||
        it('loads the graph', () => {
 | 
			
		||||
          cy.visit('/graphs/mining/block-rewards');
 | 
			
		||||
          cy.waitForSkeletonGone();
 | 
			
		||||
          cy.waitForPageIdle();
 | 
			
		||||
          cy.get('.spinner-border').should('not.exist');
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      describe('block sizes and weights', () => {
 | 
			
		||||
        it('loads the graph', () => {
 | 
			
		||||
          cy.visit('/graphs/mining/block-sizes-weights');
 | 
			
		||||
          cy.waitForSkeletonGone();
 | 
			
		||||
          cy.waitForPageIdle();
 | 
			
		||||
          cy.get('.spinner-border').should('not.exist');
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  } else {
 | 
			
		||||
    it.skip(`Tests cannot be run on the selected BASE_MODULE ${baseModule}`);
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
@ -113,13 +113,13 @@
 | 
			
		||||
                <tr *ngIf="network !== 'liquid' && network !== 'liquidtestnet'">
 | 
			
		||||
                  <td i18n="block.miner">Miner</td>
 | 
			
		||||
                  <td *ngIf="stateService.env.MINING_DASHBOARD">
 | 
			
		||||
                    <a placement="bottom" [routerLink]="['/mining/pool' | relativeUrl, block.extras.pool.slug]" class="badge"
 | 
			
		||||
                    <a [attr.data-cy]="'block-details-miner-badge'" placement="bottom" [routerLink]="['/mining/pool' | relativeUrl, block.extras.pool.slug]" class="badge"
 | 
			
		||||
                      [class]="block.extras.pool.name === 'Unknown' ? 'badge-secondary' : 'badge-primary'">
 | 
			
		||||
                      {{ block.extras.pool.name }}
 | 
			
		||||
                    </a>
 | 
			
		||||
                  </td>
 | 
			
		||||
                  <td *ngIf="!stateService.env.MINING_DASHBOARD && stateService.env.BASE_MODULE === 'mempool'">
 | 
			
		||||
                    <span placement="bottom" class="badge"
 | 
			
		||||
                    <span [attr.data-cy]="'block-details-miner-badge'" placement="bottom" class="badge"
 | 
			
		||||
                      [class]="block.extras.pool.name === 'Unknown' ? 'badge-secondary' : 'badge-primary'">
 | 
			
		||||
                      {{ block.extras.pool.name }}
 | 
			
		||||
                  </span>
 | 
			
		||||
 | 
			
		||||
@ -1,31 +1,31 @@
 | 
			
		||||
<div class="blocks-container blockchain-blocks-container" *ngIf="(loadingBlocks$ | async) === false; else loadingBlocksTemplate">
 | 
			
		||||
  <div *ngFor="let block of blocks; let i = index; trackBy: trackByBlocksFn" >
 | 
			
		||||
    <div class="text-center bitcoin-block mined-block blockchain-blocks-{{ i }}" id="bitcoin-block-{{ block.height }}" [ngStyle]="blockStyles[i]" [class.blink-bg]="(specialBlocks[block.height] !== undefined)">
 | 
			
		||||
      <a draggable="false" [routerLink]="['/block/' | relativeUrl, block.id]" [state]="{ data: { block: block } }" 
 | 
			
		||||
    <div [attr.data-cy]="'bitcoin-block-' + i" class="text-center bitcoin-block mined-block blockchain-blocks-{{ i }}" id="bitcoin-block-{{ block.height }}" [ngStyle]="blockStyles[i]" [class.blink-bg]="(specialBlocks[block.height] !== undefined)">
 | 
			
		||||
      <a draggable="false" [routerLink]="['/block/' | relativeUrl, block.id]" [state]="{ data: { block: block } }"
 | 
			
		||||
        class="blockLink" [ngClass]="{'disabled': (this.stateService.blockScrolling$ | async)}"> </a>
 | 
			
		||||
      <div class="block-height">
 | 
			
		||||
      <div [attr.data-cy]="'bitcoin-block-' + i + '-height'" class="block-height">
 | 
			
		||||
        <a [routerLink]="['/block/' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="block-body">
 | 
			
		||||
        <div class="fees">
 | 
			
		||||
        <div [attr.data-cy]="'bitcoin-block-' + i + '-fees'" class="fees">
 | 
			
		||||
          ~{{ block?.extras?.medianFee | number:feeRounding }} <ng-container i18n="shared.sat-vbyte|sat/vB">sat/vB</ng-container>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="fee-span">
 | 
			
		||||
        <div [attr.data-cy]="'bitcoin-block-' + i + '-fee-span'" class="fee-span">
 | 
			
		||||
          {{ block?.extras?.feeRange[1] | number:feeRounding }} - {{ block?.extras?.feeRange[block?.extras?.feeRange.length - 1] | number:feeRounding }} <ng-container i18n="shared.sat-vbyte|sat/vB">sat/vB</ng-container>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div *ngIf="showMiningInfo" class="block-size">
 | 
			
		||||
        <div [attr.data-cy]="'bitcoin-block-' + i + '-total-fees'" *ngIf="showMiningInfo" class="block-size">
 | 
			
		||||
          <app-amount [satoshis]="block.extras?.totalFees ?? 0" digitsInfo="1.2-3" [noFiat]="true"></app-amount>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div *ngIf="!showMiningInfo" class="block-size" [innerHTML]="'‎' + (block.size | bytes: 2)"></div>
 | 
			
		||||
        <div class="transaction-count">
 | 
			
		||||
        <div [attr.data-cy]="'bitcoin-block-' + i + 'block-size'" *ngIf="!showMiningInfo" class="block-size" [innerHTML]="'‎' + (block.size | bytes: 2)"></div>
 | 
			
		||||
        <div [attr.data-cy]="'bitcoin-block-' + i + '-transactions'" class="transaction-count">
 | 
			
		||||
          <ng-container *ngTemplateOutlet="block.tx_count === 1 ? transactionsSingular : transactionsPlural; context: {$implicit: block.tx_count | number}"></ng-container>
 | 
			
		||||
          <ng-template #transactionsSingular let-i i18n="shared.transaction-count.singular">{{ i }} transaction</ng-template>
 | 
			
		||||
          <ng-template #transactionsPlural let-i i18n="shared.transaction-count.plural">{{ i }} transactions</ng-template>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="time-difference"><app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since></div>
 | 
			
		||||
        <div [attr.data-cy]="'bitcoin-block-' + i + '-time'" class="time-difference"><app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since></div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="animated" [class]="showMiningInfo ? 'show' : 'hide'" *ngIf="block.extras?.pool != undefined">
 | 
			
		||||
        <a class="badge badge-primary" [routerLink]="[('/mining/pool/' + block.extras.pool.slug) | relativeUrl]">
 | 
			
		||||
        <a [attr.data-cy]="'bitcoin-block-' + i + '-pool'" class="badge badge-primary" [routerLink]="[('/mining/pool/' + block.extras.pool.slug) | relativeUrl]">
 | 
			
		||||
          {{ block.extras.pool.name}}</a>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
@ -28,22 +28,22 @@
 | 
			
		||||
    <form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(hashrateObservable$ | async) as stats">
 | 
			
		||||
      <div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="dateSpan">
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 12960">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]"> 3M
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'3m'"> 3M
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 25920">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]"> 6M
 | 
			
		||||
          <input ngbButton type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'6m'"> 6M
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 52560">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]"> 1Y
 | 
			
		||||
          <input ngbButton type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'1y'"> 1Y
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 105120">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]"> 2Y
 | 
			
		||||
          <input ngbButton type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'2y'"> 2Y
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 157680">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]"> 3Y
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'3y'"> 3Y
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]"> ALL
 | 
			
		||||
          <input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'all'"> ALL
 | 
			
		||||
        </label>
 | 
			
		||||
      </div>
 | 
			
		||||
    </form>
 | 
			
		||||
 | 
			
		||||
@ -10,19 +10,19 @@
 | 
			
		||||
    <form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(hashrateObservable$ | async) as stats">
 | 
			
		||||
      <div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="dateSpan">
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 25920">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]"> 6M
 | 
			
		||||
          <input ngbButton type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'6m'"> 6M
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 52560">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]"> 1Y
 | 
			
		||||
          <input ngbButton type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'1y'"> 1Y
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 105120">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]"> 2Y
 | 
			
		||||
          <input ngbButton type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'2y'"> 2Y
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 157680">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]"> 3Y
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'3y'"> 3Y
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]"> ALL
 | 
			
		||||
          <input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'all'"> ALL
 | 
			
		||||
        </label>
 | 
			
		||||
      </div>
 | 
			
		||||
    </form>
 | 
			
		||||
 | 
			
		||||
@ -2,26 +2,26 @@
 | 
			
		||||
  <div class="mempool-blocks-container" *ngIf="(difficultyAdjustments$ | async) as da;">
 | 
			
		||||
    <div class="flashing">
 | 
			
		||||
      <ng-template ngFor let-projectedBlock [ngForOf]="mempoolBlocks$ | async" let-i="index" [ngForTrackBy]="trackByFn">
 | 
			
		||||
        <div class="bitcoin-block text-center mempool-block" id="mempool-block-{{ i }}" [ngStyle]="mempoolBlockStyles[i]" [class.blink-bg]="projectedBlock.blink">
 | 
			
		||||
        <div [attr.data-cy]="'mempool-block-' + i" class="bitcoin-block text-center mempool-block" id="mempool-block-{{ i }}" [ngStyle]="mempoolBlockStyles[i]" [class.blink-bg]="projectedBlock.blink">
 | 
			
		||||
          <a draggable="false" [routerLink]="['/mempool-block/' | relativeUrl, i]"
 | 
			
		||||
            class="blockLink" [ngClass]="{'disabled': (this.stateService.blockScrolling$ | async)}"> </a>
 | 
			
		||||
          <div class="block-body">
 | 
			
		||||
            <div class="fees">
 | 
			
		||||
            <div [attr.data-cy]="'mempool-block-' + i + '-fees'" class="fees">
 | 
			
		||||
              ~{{ projectedBlock.medianFee | number:feeRounding }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="fee-span">
 | 
			
		||||
            <div [attr.data-cy]="'mempool-block-' + i + '-fee-span'" class="fee-span">
 | 
			
		||||
              {{ projectedBlock.feeRange[0] | number:feeRounding }} - {{ projectedBlock.feeRange[projectedBlock.feeRange.length - 1] | number:feeRounding }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div *ngIf="showMiningInfo" class="block-size">
 | 
			
		||||
              <app-amount [satoshis]="projectedBlock.totalFees" digitsInfo="1.2-3" [noFiat]="true"></app-amount>
 | 
			
		||||
              <app-amount [attr.data-cy]="'mempool-block-' + i + '-total-fees'" [satoshis]="projectedBlock.totalFees" digitsInfo="1.2-3" [noFiat]="true"></app-amount>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div *ngIf="!showMiningInfo" class="block-size" [innerHTML]="'‎' + (projectedBlock.blockSize | bytes: 2)"></div>
 | 
			
		||||
            <div class="transaction-count">
 | 
			
		||||
            <div [attr.data-cy]="'mempool-block-' + i + '-transaction-count'" class="transaction-count">
 | 
			
		||||
              <ng-container *ngTemplateOutlet="projectedBlock.nTx === 1 ? transactionsSingular : transactionsPlural; context: {$implicit: projectedBlock.nTx | number}"></ng-container>
 | 
			
		||||
              <ng-template #transactionsSingular let-i i18n="shared.transaction-count.singular">{{ i }} transaction</ng-template>
 | 
			
		||||
              <ng-template #transactionsPlural let-i i18n="shared.transaction-count.plural">{{ i }} transactions</ng-template>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="time-difference" *ngIf="projectedBlock.blockVSize <= stateService.blockVSize; else mergedBlock">
 | 
			
		||||
            <div [attr.data-cy]="'mempool-block-' + i + '-time'" class="time-difference" *ngIf="projectedBlock.blockVSize <= stateService.blockVSize; else mergedBlock">
 | 
			
		||||
              <ng-template [ngIf]="network === 'liquid' || network === 'liquidtestnet'" [ngIfElse]="timeDiffMainnet">
 | 
			
		||||
                <app-time-until [time]="(1 * i) + now + 61000" [fastRender]="false" [fixedRender]="true"></app-time-until>
 | 
			
		||||
              </ng-template>
 | 
			
		||||
@ -30,7 +30,7 @@
 | 
			
		||||
              </ng-template>
 | 
			
		||||
            </div>
 | 
			
		||||
            <ng-template #mergedBlock>
 | 
			
		||||
              <div class="time-difference">
 | 
			
		||||
              <div [attr.data-cy]="'mempool-block-' + i + '-blocks'" class="time-difference">
 | 
			
		||||
                <b>(<ng-container *ngTemplateOutlet="blocksPlural; context: {$implicit: projectedBlock.blockVSize / stateService.blockVSize | ceil }"></ng-container>)</b>
 | 
			
		||||
                <ng-template #blocksPlural let-i i18n="shared.blocks">{{ i }} <span class="shared-block">blocks</span></ng-template>
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
    <!-- Temporary stuff here - Will be moved to a component once we have more useful data to show -->
 | 
			
		||||
    <div class="col">
 | 
			
		||||
      <div class="main-title">
 | 
			
		||||
        <span i18n="mining.reward-stats">Reward stats</span> 
 | 
			
		||||
        <span [attr.data-cy]="'reward-stats'" i18n="mining.reward-stats">Reward stats</span> 
 | 
			
		||||
        <span style="font-size: xx-small" i18n="mining.144-blocks">(144 blocks)</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="card-wrapper">
 | 
			
		||||
@ -22,15 +22,15 @@
 | 
			
		||||
    <!-- difficulty adjustment -->
 | 
			
		||||
    <div class="col">
 | 
			
		||||
      <div class="main-title" i18n="dashboard.difficulty-adjustment">Difficulty Adjustment</div>
 | 
			
		||||
      <app-difficulty [showTitle]="false" [showProgress]="false" [showHalving]="true"></app-difficulty>
 | 
			
		||||
      <app-difficulty [attr.data-cy]="'difficulty-adjustment'" [showTitle]="false" [showProgress]="false" [showHalving]="true"></app-difficulty>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <!-- pool distribution -->
 | 
			
		||||
    <div class="col" style="margin-bottom: 1.47rem">
 | 
			
		||||
      <div class="card graph-card">
 | 
			
		||||
        <div class="card-body pl-2 pr-2">
 | 
			
		||||
          <app-pool-ranking [widget]=true></app-pool-ranking>
 | 
			
		||||
          <div class="mt-1"><a [routerLink]="['/graphs/mining/pools' | relativeUrl]" i18n="dashboard.view-more">View more »</a></div>
 | 
			
		||||
          <app-pool-ranking [attr.data-cy]="'pool-distribution'" [widget]=true></app-pool-ranking>
 | 
			
		||||
          <div class="mt-1"><a [attr.data-cy]="'pool-distribution-view-more'" [routerLink]="['/graphs/mining/pools' | relativeUrl]" i18n="dashboard.view-more">View more »</a></div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
@ -39,7 +39,7 @@
 | 
			
		||||
    <div class="col" style="margin-bottom: 1.47rem">
 | 
			
		||||
      <div class="card">
 | 
			
		||||
        <div class="card-body pl-lg-3 pr-lg-3 pl-2 pr-2">
 | 
			
		||||
          <app-hashrate-chart [widget]="true"></app-hashrate-chart>
 | 
			
		||||
          <app-hashrate-chart [attr.data-cy]="'hashrate-graph'" [widget]="true"></app-hashrate-chart>
 | 
			
		||||
          <div class="mt-1"><a [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" fragment="1y" i18n="dashboard.view-more">View more »</a></div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
@ -54,7 +54,7 @@
 | 
			
		||||
            <span> </span>
 | 
			
		||||
            <fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: 'text-top'; font-size: 13px; color: '#4a68b9'"></fa-icon>
 | 
			
		||||
          </a>
 | 
			
		||||
          <app-blocks-list [widget]=true></app-blocks-list>
 | 
			
		||||
          <app-blocks-list [attr.data-cy]="'latest-blocks'" [widget]=true></app-blocks-list>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
@ -68,7 +68,7 @@
 | 
			
		||||
            <span> </span>
 | 
			
		||||
            <fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: 'text-top'; font-size: 13px; color: '#4a68b9'"></fa-icon>
 | 
			
		||||
          </a>
 | 
			
		||||
          <app-difficulty-adjustments-table></app-difficulty-adjustments-table>
 | 
			
		||||
          <app-difficulty-adjustments-table [attr.data-cy]="'difficulty-adjustments-table'"></app-difficulty-adjustments-table>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
@ -40,34 +40,34 @@
 | 
			
		||||
      *ngIf="!widget && (miningStatsObservable$ | async) as stats">
 | 
			
		||||
      <div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="dateSpan">
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 144">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/pools' | relativeUrl]"> 24h
 | 
			
		||||
          <input ngbButton type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'24h'"> 24h
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 432">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/pools' | relativeUrl]"> 3D
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'3d'"> 3D
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 1008">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/pools' | relativeUrl]"> 1W
 | 
			
		||||
          <input ngbButton type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'1w'"> 1W
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 4320">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/pools' | relativeUrl]"> 1M
 | 
			
		||||
          <input ngbButton type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'1m'"> 1M
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 12960">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/pools' | relativeUrl]"> 3M
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'3m'"> 3M
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 25920">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/pools' | relativeUrl]"> 6M
 | 
			
		||||
          <input ngbButton type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'6m'"> 6M
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 52560">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/pools' | relativeUrl]"> 1Y
 | 
			
		||||
          <input ngbButton type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'1y'"> 1Y
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 105120">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/pools' | relativeUrl]"> 2Y
 | 
			
		||||
          <input ngbButton type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'2y'"> 2Y
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 157680">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/pools' | relativeUrl]"> 3Y
 | 
			
		||||
          <input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'3y'"> 3Y
 | 
			
		||||
        </label>
 | 
			
		||||
        <label ngbButtonLabel class="btn-primary btn-sm">
 | 
			
		||||
          <input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/pools' | relativeUrl]"><span i18n>All</span>
 | 
			
		||||
          <input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'all'"><span i18n>All</span>
 | 
			
		||||
        </label>
 | 
			
		||||
      </div>
 | 
			
		||||
    </form>
 | 
			
		||||
@ -95,7 +95,7 @@
 | 
			
		||||
          <th class="d-none d-md-block" i18n="mining.empty-blocks">Empty blocks</th>
 | 
			
		||||
        </tr>
 | 
			
		||||
      </thead>
 | 
			
		||||
      <tbody *ngIf="(miningStatsObservable$ | async) as miningStats">
 | 
			
		||||
      <tbody [attr.data-cy]="'pools-table'" *ngIf="(miningStatsObservable$ | async) as miningStats">
 | 
			
		||||
        <tr *ngFor="let pool of miningStats.pools">
 | 
			
		||||
          <td class="d-none d-md-block">{{ pool.rank }}</td>
 | 
			
		||||
          <td class="text-right">
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user