Merge branch 'master' into breathe-effect-framerate

This commit is contained in:
Felipe Knorr Kuhn
2022-07-07 06:36:17 -07:00
committed by GitHub
34 changed files with 932 additions and 1035 deletions

View File

@@ -8,6 +8,10 @@ indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false

2
frontend/.prettierignore Normal file
View File

@@ -0,0 +1,2 @@
node_modules
package-lock.json

6
frontend/.prettierrc Normal file
View File

@@ -0,0 +1,6 @@
{
"endOfLine": "lf",
"printWidth": 80,
"tabWidth": 2,
"trailingComma": "es5"
}

View 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}`);
}
});

View File

@@ -56,14 +56,15 @@
"@typescript-eslint/parser": "^5.30.5",
"eslint": "^8.19.0",
"http-proxy-middleware": "~2.0.6",
"prettier": "^2.7.1",
"ts-node": "~10.8.1",
"typescript": "~4.6.4"
},
"optionalDependencies": {
"@cypress/schematic": "~2.0.0",
"cypress": "^10.0.2",
"cypress-fail-on-console-error": "~2.1.4",
"cypress-wait-until": "^1.7.1",
"cypress": "^10.3.0",
"cypress-fail-on-console-error": "~3.0.0",
"cypress-wait-until": "^1.7.2",
"mock-socket": "~9.1.4",
"start-server-and-test": "~1.14.0"
}
@@ -1366,9 +1367,9 @@
}
},
"node_modules/@babel/helper-plugin-utils": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz",
"integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==",
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz",
"integrity": "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg==",
"engines": {
"node": ">=6.9.0"
}
@@ -7293,9 +7294,9 @@
"peer": true
},
"node_modules/cypress": {
"version": "10.0.2",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-10.0.2.tgz",
"integrity": "sha512-7+C4KHYBcfZrawss+Gt5PlS35rfc6ySc59JcHDVsIMm1E/J35dqE41UEXpdtwIq3549umCerNWnFADzqib4kcA==",
"version": "10.3.0",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-10.3.0.tgz",
"integrity": "sha512-txkQWKzvBVnWdCuKs5Xc08gjpO89W2Dom2wpZgT9zWZT5jXxqPIxqP/NC1YArtkpmp3fN5HW8aDjYBizHLUFvg==",
"hasInstallScript": true,
"optional": true,
"dependencies": {
@@ -7350,9 +7351,9 @@
}
},
"node_modules/cypress-fail-on-console-error": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/cypress-fail-on-console-error/-/cypress-fail-on-console-error-2.1.4.tgz",
"integrity": "sha512-arjx2xfQN1FDM3s4HoKK0ZXszPgIZLAI61sbwaZfdo8HEIVJPdOwY+oBKM1XY9yso80rgtwlSY75KJOQTNOkdg==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cypress-fail-on-console-error/-/cypress-fail-on-console-error-3.0.0.tgz",
"integrity": "sha512-DBu5DI3gMzwFkzuOTbJ/A1xbGtYKukFoe7o07unEJlqe0f50xwB5OnAm6Pxe7J9eNtg40ZUJB8fcATqDr0qwgw==",
"optional": true,
"dependencies": {
"chai": "^4.3.4",
@@ -7361,9 +7362,9 @@
}
},
"node_modules/cypress-wait-until": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-1.7.1.tgz",
"integrity": "sha512-8DL5IsBTbAxBjfYgCzdbohPq/bY+IKc63fxtso1C8RWhLnQkZbVESyaclNr76jyxfId6uyzX8+Xnt0ZwaXNtkA==",
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-1.7.2.tgz",
"integrity": "sha512-uZ+M8/MqRcpf+FII/UZrU7g1qYZ4aVlHcgyVopnladyoBrpoaMJ4PKZDrdOJ05H5RHbr7s9Tid635X3E+ZLU/Q==",
"optional": true
},
"node_modules/cypress/node_modules/@types/node": {
@@ -10994,9 +10995,9 @@
}
},
"node_modules/jest-worker": {
"version": "27.2.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.0.tgz",
"integrity": "sha512-laB0ZVIBz+voh/QQy9dmUuuDsadixeerrKqyVpgPz+CCWiOYjOBabUXHIXZhsdvkWbLqSHbgkAHWl5cg24Q6RA==",
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
"integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
"dependencies": {
"@types/node": "*",
"merge-stream": "^2.0.0",
@@ -14340,6 +14341,21 @@
"node": ">= 0.8.0"
}
},
"node_modules/prettier": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true,
"bin": {
"prettier": "bin-prettier.js"
},
"engines": {
"node": ">=10.13.0"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/pretty-bytes": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
@@ -18695,9 +18711,9 @@
}
},
"@babel/helper-plugin-utils": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz",
"integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA=="
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz",
"integrity": "sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg=="
},
"@babel/helper-remap-async-to-generator": {
"version": "7.16.8",
@@ -23197,9 +23213,9 @@
"peer": true
},
"cypress": {
"version": "10.0.2",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-10.0.2.tgz",
"integrity": "sha512-7+C4KHYBcfZrawss+Gt5PlS35rfc6ySc59JcHDVsIMm1E/J35dqE41UEXpdtwIq3549umCerNWnFADzqib4kcA==",
"version": "10.3.0",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-10.3.0.tgz",
"integrity": "sha512-txkQWKzvBVnWdCuKs5Xc08gjpO89W2Dom2wpZgT9zWZT5jXxqPIxqP/NC1YArtkpmp3fN5HW8aDjYBizHLUFvg==",
"optional": true,
"requires": {
"@cypress/request": "^2.88.10",
@@ -23374,9 +23390,9 @@
}
},
"cypress-fail-on-console-error": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/cypress-fail-on-console-error/-/cypress-fail-on-console-error-2.1.4.tgz",
"integrity": "sha512-arjx2xfQN1FDM3s4HoKK0ZXszPgIZLAI61sbwaZfdo8HEIVJPdOwY+oBKM1XY9yso80rgtwlSY75KJOQTNOkdg==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cypress-fail-on-console-error/-/cypress-fail-on-console-error-3.0.0.tgz",
"integrity": "sha512-DBu5DI3gMzwFkzuOTbJ/A1xbGtYKukFoe7o07unEJlqe0f50xwB5OnAm6Pxe7J9eNtg40ZUJB8fcATqDr0qwgw==",
"optional": true,
"requires": {
"chai": "^4.3.4",
@@ -23385,9 +23401,9 @@
}
},
"cypress-wait-until": {
"version": "1.7.1",
"resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-1.7.1.tgz",
"integrity": "sha512-8DL5IsBTbAxBjfYgCzdbohPq/bY+IKc63fxtso1C8RWhLnQkZbVESyaclNr76jyxfId6uyzX8+Xnt0ZwaXNtkA==",
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-1.7.2.tgz",
"integrity": "sha512-uZ+M8/MqRcpf+FII/UZrU7g1qYZ4aVlHcgyVopnladyoBrpoaMJ4PKZDrdOJ05H5RHbr7s9Tid635X3E+ZLU/Q==",
"optional": true
},
"d": {
@@ -26030,9 +26046,9 @@
}
},
"jest-worker": {
"version": "27.2.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.0.tgz",
"integrity": "sha512-laB0ZVIBz+voh/QQy9dmUuuDsadixeerrKqyVpgPz+CCWiOYjOBabUXHIXZhsdvkWbLqSHbgkAHWl5cg24Q6RA==",
"version": "27.5.1",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
"integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
"requires": {
"@types/node": "*",
"merge-stream": "^2.0.0",
@@ -28514,6 +28530,12 @@
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
},
"prettier": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true
},
"pretty-bytes": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",

View File

@@ -44,6 +44,7 @@
"test": "npm run ng -- test",
"lint": "./node_modules/.bin/eslint . --ext .ts",
"lint:fix": "./node_modules/.bin/eslint . --ext .ts --fix",
"prettier": "prettier --write \"src/app/**/*.{js,json,css,scss,less,md,ts,html,component.html}\"",
"e2e": "npm run generate-config && npm run ng -- e2e",
"e2e:ci": "npm run cypress:run:ci",
"config:defaults:mempool": "node update-config.js TESTNET_ENABLED=true SIGNET_ENABLED=true LIQUID_ENABLED=true LIQUID_TESTNET_ENABLED=true BISQ_ENABLED=true ITEMS_PER_PAGE=25 BASE_MODULE=mempool BLOCK_WEIGHT_UNITS=4000000 && npm run generate-config",
@@ -109,14 +110,15 @@
"@typescript-eslint/parser": "^5.30.5",
"eslint": "^8.19.0",
"http-proxy-middleware": "~2.0.6",
"prettier": "^2.7.1",
"ts-node": "~10.8.1",
"typescript": "~4.6.4"
},
"optionalDependencies": {
"@cypress/schematic": "~2.0.0",
"cypress": "^10.0.2",
"cypress-fail-on-console-error": "~2.1.4",
"cypress-wait-until": "^1.7.1",
"cypress": "^10.3.0",
"cypress-fail-on-console-error": "~3.0.0",
"cypress-wait-until": "^1.7.2",
"mock-socket": "~9.1.4",
"start-server-and-test": "~1.14.0"
},

View File

@@ -2,41 +2,41 @@
<div class="full-container">
<div class="card-header mb-0 mb-md-4">
<span i18n="mining.block-prediction-accuracy">Block Predictions Accuracy</span>
<span i18n="mining.block-prediction-accuracy">Block Prediction Accuracy</span>
<button class="btn" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(statsObservable$ | 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 >= 144">
<input ngbButton type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-predictions' | relativeUrl]"> 24h
<input ngbButton type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]"> 24h
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 432">
<input ngbButton type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-predictions' | relativeUrl]"> 3D
<input ngbButton type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]"> 3D
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 1008">
<input ngbButton type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-predictions' | relativeUrl]"> 1W
<input ngbButton type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]"> 1W
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 4320">
<input ngbButton type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-predictions' | relativeUrl]"> 1M
<input ngbButton type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]"> 1M
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 12960">
<input ngbButton type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-predictions' | relativeUrl]"> 3M
<input ngbButton type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]"> 3M
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 25920">
<input ngbButton type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-predictions' | relativeUrl]"> 6M
<input ngbButton type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]"> 6M
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 52560">
<input ngbButton type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-predictions' | relativeUrl]"> 1Y
<input ngbButton type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]"> 1Y
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 105120">
<input ngbButton type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-predictions' | relativeUrl]"> 2Y
<input ngbButton type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]"> 2Y
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 157680">
<input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-predictions' | relativeUrl]"> 3Y
<input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]"> 3Y
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount > 157680">
<input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-predictions' | relativeUrl]"> ALL
<input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-prediction' | relativeUrl]"> ALL
</label>
</div>
</form>

View File

@@ -13,9 +13,9 @@ import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.
import { StateService } from 'src/app/services/state.service';
@Component({
selector: 'app-block-predictions-graph',
templateUrl: './block-predictions-graph.component.html',
styleUrls: ['./block-predictions-graph.component.scss'],
selector: 'app-block-prediction-graph',
templateUrl: './block-prediction-graph.component.html',
styleUrls: ['./block-prediction-graph.component.scss'],
styles: [`
.loadingGraphs {
position: absolute;
@@ -26,7 +26,7 @@ import { StateService } from 'src/app/services/state.service';
`],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BlockPredictionsGraphComponent implements OnInit {
export class BlockPredictionGraphComponent implements OnInit {
@Input() right: number | string = 45;
@Input() left: number | string = 75;
@@ -60,7 +60,7 @@ export class BlockPredictionsGraphComponent implements OnInit {
}
ngOnInit(): void {
this.seoService.setTitle($localize`Block predictions accuracy`);
this.seoService.setTitle($localize`:@@d7d5fcf50179ad70c938491c517efb82de2c8146:Block Prediction Accuracy`);
this.miningWindowPreference = '24h';//this.miningService.getDefaultTimespan('24h');
this.radioGroupForm = this.formBuilder.group({ dateSpan: this.miningWindowPreference });
this.radioGroupForm.controls.dateSpan.setValue(this.miningWindowPreference);

View File

@@ -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>

View File

@@ -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)}">&nbsp;</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]="'&lrm;' + (block.size | bytes: 2)"></div>
<div class="transaction-count">
<div [attr.data-cy]="'bitcoin-block-' + i + 'block-size'" *ngIf="!showMiningInfo" class="block-size" [innerHTML]="'&lrm;' + (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>

View File

@@ -19,7 +19,7 @@
<a class="dropdown-item" routerLinkActive="active"
[routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" i18n="mining.block-sizes-weights">Block Sizes and Weights</a>
<a class="dropdown-item" routerLinkActive="active"
[routerLink]="['/graphs/mining/block-predictions' | relativeUrl]" i18n="mining.block-prediction-accuracy">Blocks Predictions Accuracy</a>
[routerLink]="['/graphs/mining/block-prediction' | relativeUrl]" i18n="mining.block-prediction-accuracy">Block Prediction Accuracy</a>
</div>
</div>
</div>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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)}">&nbsp;</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]="'&lrm;' + (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>

View File

@@ -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>&nbsp;
<span [attr.data-cy]="'reward-stats'" i18n="mining.reward-stats">Reward stats</span>&nbsp;
<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 &raquo;</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 &raquo;</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 &raquo;</a></div>
</div>
</div>
@@ -54,7 +54,7 @@
<span>&nbsp;</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>&nbsp;</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>

View File

@@ -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">

View File

@@ -22,7 +22,7 @@ import { DashboardComponent } from '../dashboard/dashboard.component';
import { MiningDashboardComponent } from '../components/mining-dashboard/mining-dashboard.component';
import { HashrateChartComponent } from '../components/hashrate-chart/hashrate-chart.component';
import { HashrateChartPoolsComponent } from '../components/hashrates-chart-pools/hashrate-chart-pools.component';
import { BlockPredictionsGraphComponent } from '../components/block-predictions-graph/block-predictions-graph.component';
import { BlockPredictionGraphComponent } from '../components/block-prediction-graph/block-prediction-graph.component';
import { CommonModule } from '@angular/common';
@NgModule({
@@ -48,7 +48,7 @@ import { CommonModule } from '@angular/common';
LbtcPegsGraphComponent,
HashrateChartComponent,
HashrateChartPoolsComponent,
BlockPredictionsGraphComponent,
BlockPredictionGraphComponent,
],
imports: [
CommonModule,

View File

@@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { BlockPredictionsGraphComponent } from '../components/block-predictions-graph/block-predictions-graph.component';
import { BlockPredictionGraphComponent } from '../components/block-prediction-graph/block-prediction-graph.component';
import { BlockFeeRatesGraphComponent } from '../components/block-fee-rates-graph/block-fee-rates-graph.component';
import { BlockFeesGraphComponent } from '../components/block-fees-graph/block-fees-graph.component';
import { BlockRewardsGraphComponent } from '../components/block-rewards-graph/block-rewards-graph.component';
@@ -94,8 +94,8 @@ const routes: Routes = [
redirectTo: 'mempool',
},
{
path: 'mining/block-predictions',
component: BlockPredictionsGraphComponent,
path: 'mining/block-prediction',
component: BlockPredictionGraphComponent,
},
]
},

File diff suppressed because it is too large Load Diff