diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index fd7ab3a3d..3e2c40b25 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -46,6 +46,7 @@ import { SharedModule } from './shared/shared.module';
import { NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
import { FeesBoxComponent } from './components/fees-box/fees-box.component';
import { DashboardComponent } from './dashboard/dashboard.component';
+import { DifficultyComponent } from './components/difficulty/difficulty.component';
import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome';
import { faFilter, faAngleDown, faAngleUp, faAngleRight, faAngleLeft, faBolt, faChartArea, faCogs, faCubes, faDatabase, faExchangeAlt, faInfoCircle,
faLink, faList, faSearch, faCaretUp, faCaretDown, faTachometerAlt, faThList, faTint, faTv, faAngleDoubleDown, faSortUp, faAngleDoubleUp, faChevronDown, faFileAlt, faRedoAlt, faArrowAltCircleRight, faExternalLinkAlt, faBook, faListUl } from '@fortawesome/free-solid-svg-icons';
@@ -97,6 +98,7 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
StatusViewComponent,
FeesBoxComponent,
DashboardComponent,
+ DifficultyComponent,
ApiDocsComponent,
CodeTemplateComponent,
TermsOfServiceComponent,
diff --git a/frontend/src/app/components/difficulty/difficulty.component.html b/frontend/src/app/components/difficulty/difficulty.component.html
new file mode 100644
index 000000000..5064c1c08
--- /dev/null
+++ b/frontend/src/app/components/difficulty/difficulty.component.html
@@ -0,0 +1,78 @@
+
Difficulty Adjustment
+
+
+
+
+
+
Remaining
+
+
+ {{ i }} blocks
+ {{ i }} block
+
+
+
+
+
Estimate
+
+ 0; else arrowDownDifficulty" >
+
+
+
+
+
+ {{ epochData.change | absolute | number: '1.2-2' }}
+ %
+
+
+ —
+
+
+ Previous:
+
+ 0; else arrowDownPreviousDifficulty" >
+
+
+
+
+
+ {{ epochData.previousRetarget | absolute | number: '1.2-2' }} %
+
+
+
+
Current Period
+
{{ epochData.progress | number: '1.2-2' }} %
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/app/components/difficulty/difficulty.component.scss b/frontend/src/app/components/difficulty/difficulty.component.scss
new file mode 100644
index 000000000..f66e2c8e5
--- /dev/null
+++ b/frontend/src/app/components/difficulty/difficulty.component.scss
@@ -0,0 +1,150 @@
+.difficulty-adjustment-container {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-around;
+ height: 76px;
+ .shared-block {
+ color: #ffffff66;
+ font-size: 12px;
+ }
+ .item {
+ padding: 0 5px;
+ width: 100%;
+ &:nth-child(1) {
+ display: none;
+ @media (min-width: 485px) {
+ display: table-cell;
+ }
+ @media (min-width: 768px) {
+ display: none;
+ }
+ @media (min-width: 992px) {
+ display: table-cell;
+ }
+ }
+ }
+ .card-text {
+ font-size: 22px;
+ margin-top: -9px;
+ position: relative;
+ }
+}
+
+
+.difficulty-skeleton {
+ display: flex;
+ justify-content: space-between;
+ @media (min-width: 376px) {
+ flex-direction: row;
+ }
+ .item {
+ max-width: 150px;
+ margin: 0;
+ width: -webkit-fill-available;
+ @media (min-width: 376px) {
+ margin: 0 auto 0px;
+ }
+ &:first-child{
+ display: none;
+ @media (min-width: 485px) {
+ display: block;
+ }
+ @media (min-width: 768px) {
+ display: none;
+ }
+ @media (min-width: 992px) {
+ display: block;
+ }
+ }
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+ .card-text {
+ .skeleton-loader {
+ width: 100%;
+ display: block;
+ &:first-child {
+ margin: 14px auto 0;
+ max-width: 80px;
+ }
+ &:last-child {
+ margin: 10px auto 0;
+ max-width: 120px;
+ }
+ }
+ }
+}
+
+.card {
+ background-color: #1d1f31;
+ height: 100%;
+}
+
+.card-title {
+ color: #4a68b9;
+ font-size: 1rem;
+}
+
+.progress {
+ display: inline-flex;
+ width: 100%;
+ background-color: #2d3348;
+ height: 1.1rem;
+ max-width: 180px;
+}
+
+.skeleton-loader {
+ max-width: 100%;
+}
+
+.more-padding {
+ padding: 18px;
+}
+
+.small-bar {
+ height: 8px;
+ top: -4px;
+ max-width: 120px;
+}
+
+.loading-container {
+ min-height: 76px;
+}
+
+.main-title {
+ position: relative;
+ color: #ffffff91;
+ margin-top: -13px;
+ font-size: 10px;
+ text-transform: uppercase;
+ font-weight: 500;
+ text-align: center;
+ padding-bottom: 3px;
+}
+
+.card-wrapper {
+ .card {
+ height: auto !important;
+ }
+ .card-body {
+ display: flex;
+ flex: inherit;
+ text-align: center;
+ flex-direction: column;
+ justify-content: space-around;
+ padding: 22px 20px;
+ }
+}
+
+.retarget-sign {
+ margin-right: -3px;
+ font-size: 14px;
+ top: -2px;
+ position: relative;
+}
+
+.previous-retarget-sign {
+ margin-right: -2px;
+ font-size: 10px;
+}
diff --git a/frontend/src/app/components/difficulty/difficulty.component.ts b/frontend/src/app/components/difficulty/difficulty.component.ts
new file mode 100644
index 000000000..312c1b2d0
--- /dev/null
+++ b/frontend/src/app/components/difficulty/difficulty.component.ts
@@ -0,0 +1,111 @@
+import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
+import { combineLatest, Observable, timer } from 'rxjs';
+import { map, switchMap } from 'rxjs/operators';
+import { StateService } from '../..//services/state.service';
+
+interface EpochProgress {
+ base: string;
+ change: number;
+ progress: string;
+ remainingBlocks: number;
+ newDifficultyHeight: number;
+ colorAdjustments: string;
+ colorPreviousAdjustments: string;
+ timeAvg: string;
+ remainingTime: number;
+ previousRetarget: number;
+}
+
+@Component({
+ selector: 'app-difficulty',
+ templateUrl: './difficulty.component.html',
+ styleUrls: ['./difficulty.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class DifficultyComponent implements OnInit {
+ isLoadingWebSocket$: Observable;
+ difficultyEpoch$: Observable;
+
+ constructor(
+ public stateService: StateService,
+ ) { }
+
+ ngOnInit(): void {
+ this.isLoadingWebSocket$ = this.stateService.isLoadingWebSocket$;
+ this.difficultyEpoch$ = timer(0, 1000)
+ .pipe(
+ switchMap(() => combineLatest([
+ this.stateService.blocks$.pipe(map(([block]) => block)),
+ this.stateService.lastDifficultyAdjustment$,
+ this.stateService.previousRetarget$
+ ])),
+ map(([block, DATime, previousRetarget]) => {
+ const now = new Date().getTime() / 1000;
+ const diff = now - DATime;
+ const blocksInEpoch = block.height % 2016;
+ const progress = (blocksInEpoch >= 0) ? (blocksInEpoch / 2016 * 100).toFixed(2) : `100`;
+ const remainingBlocks = 2016 - blocksInEpoch;
+ const newDifficultyHeight = block.height + remainingBlocks;
+
+ let change = 0;
+ if (remainingBlocks < 1870) {
+ if (blocksInEpoch > 0) {
+ change = (600 / (diff / blocksInEpoch ) - 1) * 100;
+ }
+ if (change > 300) {
+ change = 300;
+ }
+ if (change < -75) {
+ change = -75;
+ }
+ }
+
+ const timeAvgDiff = change * 0.1;
+
+ let timeAvgMins = 10;
+ if (timeAvgDiff > 0) {
+ timeAvgMins -= Math.abs(timeAvgDiff);
+ } else {
+ timeAvgMins += Math.abs(timeAvgDiff);
+ }
+
+ const timeAvg = timeAvgMins.toFixed(0);
+ const remainingTime = (remainingBlocks * timeAvgMins * 60 * 1000) + (now * 1000);
+
+ let colorAdjustments = '#ffffff66';
+ if (change > 0) {
+ colorAdjustments = '#3bcc49';
+ }
+ if (change < 0) {
+ colorAdjustments = '#dc3545';
+ }
+
+ let colorPreviousAdjustments = '#dc3545';
+ if (previousRetarget) {
+ if (previousRetarget >= 0) {
+ colorPreviousAdjustments = '#3bcc49';
+ }
+ if (previousRetarget === 0) {
+ colorPreviousAdjustments = '#ffffff66';
+ }
+ } else {
+ colorPreviousAdjustments = '#ffffff66';
+ }
+
+ return {
+ base: `${progress}%`,
+ change,
+ progress,
+ remainingBlocks,
+ timeAvg,
+ colorAdjustments,
+ colorPreviousAdjustments,
+ blocksInEpoch,
+ newDifficultyHeight,
+ remainingTime,
+ previousRetarget,
+ };
+ })
+ );
+ }
+}
diff --git a/frontend/src/app/dashboard/dashboard.component.html b/frontend/src/app/dashboard/dashboard.component.html
index 25cacb428..b3cbd5fa1 100644
--- a/frontend/src/app/dashboard/dashboard.component.html
+++ b/frontend/src/app/dashboard/dashboard.component.html
@@ -11,7 +11,7 @@
@@ -228,84 +228,3 @@
-
-
- Difficulty Adjustment
-
-
-
-
-
-
Remaining
-
-
- {{ i }} blocks
- {{ i }} block
-
-
-
-
-
Estimate
-
- 0; else arrowDownDifficulty" >
-
-
-
-
-
- {{ epochData.change | absolute | number: '1.2-2' }}
- %
-
-
- —
-
-
- Previous:
-
- 0; else arrowDownPreviousDifficulty" >
-
-
-
-
-
- {{ epochData.previousRetarget | absolute | number: '1.2-2' }} %
-
-
-
-
Current Period
-
{{ epochData.progress | number: '1.2-2' }} %
-
-
-
-
-
-
-
-
-
-
-
diff --git a/frontend/src/app/dashboard/dashboard.component.scss b/frontend/src/app/dashboard/dashboard.component.scss
index 541bd2129..39ca2101a 100644
--- a/frontend/src/app/dashboard/dashboard.component.scss
+++ b/frontend/src/app/dashboard/dashboard.component.scss
@@ -243,84 +243,6 @@
max-width: 120px;
}
-.difficulty-adjustment-container {
- display: flex;
- flex-direction: row;
- justify-content: space-around;
- height: 76px;
- .shared-block {
- color: #ffffff66;
- font-size: 12px;
- }
- .item {
- padding: 0 5px;
- width: 100%;
- &:nth-child(1) {
- display: none;
- @media (min-width: 485px) {
- display: table-cell;
- }
- @media (min-width: 768px) {
- display: none;
- }
- @media (min-width: 992px) {
- display: table-cell;
- }
- }
- }
- .card-text {
- font-size: 22px;
- margin-top: -9px;
- position: relative;
- }
-}
-
-
-.difficulty-skeleton {
- display: flex;
- justify-content: space-between;
- @media (min-width: 376px) {
- flex-direction: row;
- }
- .item {
- max-width: 150px;
- margin: 0;
- width: -webkit-fill-available;
- @media (min-width: 376px) {
- margin: 0 auto 0px;
- }
- &:first-child{
- display: none;
- @media (min-width: 485px) {
- display: block;
- }
- @media (min-width: 768px) {
- display: none;
- }
- @media (min-width: 992px) {
- display: block;
- }
- }
- &:last-child {
- margin-bottom: 0;
- }
- }
- .card-text {
- .skeleton-loader {
- width: 100%;
- display: block;
- &:first-child {
- margin: 14px auto 0;
- max-width: 80px;
- }
- &:last-child {
- margin: 10px auto 0;
- max-width: 120px;
- }
- }
- }
-}
-
.loading-container {
min-height: 76px;
}
diff --git a/frontend/src/app/dashboard/dashboard.component.ts b/frontend/src/app/dashboard/dashboard.component.ts
index 3dbec5ce3..a582baba3 100644
--- a/frontend/src/app/dashboard/dashboard.component.ts
+++ b/frontend/src/app/dashboard/dashboard.component.ts
@@ -15,19 +15,6 @@ interface MempoolBlocksData {
size: number;
}
-interface EpochProgress {
- base: string;
- change: number;
- progress: string;
- remainingBlocks: number;
- newDifficultyHeight: number;
- colorAdjustments: string;
- colorPreviousAdjustments: string;
- timeAvg: string;
- remainingTime: number;
- previousRetarget: number;
-}
-
interface MempoolInfoData {
memPoolInfo: MempoolInfo;
vBytesPerSecond: number;
@@ -51,7 +38,6 @@ export class DashboardComponent implements OnInit {
network$: Observable
;
mempoolBlocksData$: Observable;
mempoolInfoData$: Observable;
- difficultyEpoch$: Observable;
mempoolLoadingStatus$: Observable;
vBytesPerSecondLimit = 1667;
blocks$: Observable;
@@ -126,82 +112,6 @@ export class DashboardComponent implements OnInit {
})
);
- this.difficultyEpoch$ = timer(0, 1000)
- .pipe(
- switchMap(() => combineLatest([
- this.stateService.blocks$.pipe(map(([block]) => block)),
- this.stateService.lastDifficultyAdjustment$,
- this.stateService.previousRetarget$
- ])),
- map(([block, DATime, previousRetarget]) => {
- const now = new Date().getTime() / 1000;
- const diff = now - DATime;
- const blocksInEpoch = block.height % 2016;
- const progress = (blocksInEpoch >= 0) ? (blocksInEpoch / 2016 * 100).toFixed(2) : `100`;
- const remainingBlocks = 2016 - blocksInEpoch;
- const newDifficultyHeight = block.height + remainingBlocks;
-
- let change = 0;
- if (remainingBlocks < 1870) {
- if (blocksInEpoch > 0) {
- change = (600 / (diff / blocksInEpoch ) - 1) * 100;
- }
- if (change > 300) {
- change = 300;
- }
- if (change < -75) {
- change = -75;
- }
- }
-
- const timeAvgDiff = change * 0.1;
-
- let timeAvgMins = 10;
- if (timeAvgDiff > 0) {
- timeAvgMins -= Math.abs(timeAvgDiff);
- } else {
- timeAvgMins += Math.abs(timeAvgDiff);
- }
-
- const timeAvg = timeAvgMins.toFixed(0);
- const remainingTime = (remainingBlocks * timeAvgMins * 60 * 1000) + (now * 1000);
-
- let colorAdjustments = '#ffffff66';
- if (change > 0) {
- colorAdjustments = '#3bcc49';
- }
- if (change < 0) {
- colorAdjustments = '#dc3545';
- }
-
- let colorPreviousAdjustments = '#dc3545';
- if (previousRetarget) {
- if (previousRetarget >= 0) {
- colorPreviousAdjustments = '#3bcc49';
- }
- if (previousRetarget === 0) {
- colorPreviousAdjustments = '#ffffff66';
- }
- } else {
- colorPreviousAdjustments = '#ffffff66';
- }
-
- return {
- base: `${progress}%`,
- change,
- progress,
- remainingBlocks,
- timeAvg,
- colorAdjustments,
- colorPreviousAdjustments,
- blocksInEpoch,
- newDifficultyHeight,
- remainingTime,
- previousRetarget,
- };
- })
- );
-
this.mempoolBlocksData$ = this.stateService.mempoolBlocks$
.pipe(
map((mempoolBlocks) => {