Merge pull request #4818 from mempool/mononaut/halving-widget
Add halving countdown widget to main dashboard
This commit is contained in:
		
						commit
						365c89d98f
					
				@ -1,7 +1,15 @@
 | 
				
			|||||||
<div *ngIf="showTitle" class="main-title" i18n="dashboard.difficulty-adjustment">Difficulty Adjustment</div>
 | 
					<div *ngIf="showTitle && mode === 'difficulty'" class="main-title" i18n="dashboard.difficulty-adjustment">Difficulty Adjustment</div>
 | 
				
			||||||
 | 
					<div *ngIf="showTitle && mode === 'halving'" class="main-title" i18n="dashboard.halving-countdown">Halving Countdown</div>
 | 
				
			||||||
<div class="card-wrapper">
 | 
					<div class="card-wrapper">
 | 
				
			||||||
  <div class="card">
 | 
					  <div class="card">
 | 
				
			||||||
    <div class="card-body more-padding">
 | 
					    <div class="widget-toggler">
 | 
				
			||||||
 | 
					      <a href="" (click)="setMode('difficulty')" class="toggler-option"
 | 
				
			||||||
 | 
					        [ngClass]="{'inactive': mode === 'difficulty'}"><small i18n="statistics.average-small">difficulty</small></a>
 | 
				
			||||||
 | 
					      <span style="color: #ffffff66; font-size: 8px"> | </span>
 | 
				
			||||||
 | 
					      <a href="" (click)="setMode('halving')" class="toggler-option"
 | 
				
			||||||
 | 
					        [ngClass]="{'inactive': mode === 'halving'}"><small i18n="statistics.median-small">halving</small></a>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div *ngIf="mode === 'difficulty'; else halving" class="card-body more-padding">
 | 
				
			||||||
      <div class="difficulty-adjustment-container" *ngIf="(isLoadingWebSocket$ | async) === false && (difficultyEpoch$ | async) as epochData; else loadingDifficulty">
 | 
					      <div class="difficulty-adjustment-container" *ngIf="(isLoadingWebSocket$ | async) === false && (difficultyEpoch$ | async) as epochData; else loadingDifficulty">
 | 
				
			||||||
        <div class="epoch-progress">
 | 
					        <div class="epoch-progress">
 | 
				
			||||||
          <svg #epochSvg class="epoch-blocks" height="22px" width="100%" viewBox="0 0 224 9" shape-rendering="crispEdges" preserveAspectRatio="none">
 | 
					          <svg #epochSvg class="epoch-blocks" height="22px" width="100%" viewBox="0 0 224 9" shape-rendering="crispEdges" preserveAspectRatio="none">
 | 
				
			||||||
@ -76,6 +84,52 @@
 | 
				
			|||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<ng-template #halving>
 | 
				
			||||||
 | 
					  <div class="card-body more-padding">
 | 
				
			||||||
 | 
					    <div class="difficulty-adjustment-container halving" *ngIf="(isLoadingWebSocket$ | async) === false && (difficultyEpoch$ | async) as epochData; else loadingDifficulty">
 | 
				
			||||||
 | 
					      <div class="halving-progress">
 | 
				
			||||||
 | 
					        <div class="background"></div>
 | 
				
			||||||
 | 
					        <div class="remaining" [style]="{ left: ((210000 - epochData.blocksUntilHalving) / 2100).toFixed(2) + '%' }"></div>
 | 
				
			||||||
 | 
					        <div class="label">
 | 
				
			||||||
 | 
					          {{ ((210000 - epochData.blocksUntilHalving) / 2100).toFixed(2) }}%
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="difficulty-stats">
 | 
				
			||||||
 | 
					        <div class="item">
 | 
				
			||||||
 | 
					          <div class="card-text bigger">
 | 
				
			||||||
 | 
					            <app-btc [satoshis]="312500000"></app-btc>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          <div class="symbol">
 | 
				
			||||||
 | 
					            <span i18n="difficulty-box.new-subsidy">New subsidy</span>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="item">
 | 
				
			||||||
 | 
					          <div class="card-text">
 | 
				
			||||||
 | 
					            {{ epochData.blocksUntilHalving | number }}
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          <div class="symbol">
 | 
				
			||||||
 | 
					            <span *ngIf="epochData.blocksUntilHalving > 1" i18n="shared.blocks-remaining">Blocks remaining</span>
 | 
				
			||||||
 | 
					            <span *ngIf="epochData.blocksUntilHalving === 1" i18n="shared.block-remaining">Block remaining</span>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="item">
 | 
				
			||||||
 | 
					          <div class="card-text" i18n-ngbTooltip="mining.average-fee" placement="bottom">
 | 
				
			||||||
 | 
					            <span>{{ epochData.timeUntilHalving | date }}</span>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          <div class="symbol" *ngIf="epochData.blocksUntilHalving === 1; else approxTime">
 | 
				
			||||||
 | 
					            <app-time kind="until" [time]="epochData.adjustedTimeAvg + now" [fastRender]="false" [fixedRender]="true" [precision]="1" minUnit="minute"></app-time>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          <ng-template #approxTime>
 | 
				
			||||||
 | 
					            <div class="symbol">
 | 
				
			||||||
 | 
					              <app-time kind="until" [time]="epochData.timeUntilHalving" [fastRender]="false" [fixedRender]="true" [precision]="0" [numUnits]="2" [units]="['year', 'day', 'hour', 'minute']"></app-time>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </ng-template>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</ng-template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<ng-template #loadingDifficulty>
 | 
					<ng-template #loadingDifficulty>
 | 
				
			||||||
  <div class="epoch-progress">
 | 
					  <div class="epoch-progress">
 | 
				
			||||||
    <div class="skeleton-loader"></div>
 | 
					    <div class="skeleton-loader"></div>
 | 
				
			||||||
 | 
				
			|||||||
@ -168,7 +168,7 @@
 | 
				
			|||||||
  white-space: nowrap;
 | 
					  white-space: nowrap;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.epoch-progress {
 | 
					.epoch-progress, .halving-progress {
 | 
				
			||||||
  width: 100%;
 | 
					  width: 100%;
 | 
				
			||||||
  height: 22px;
 | 
					  height: 22px;
 | 
				
			||||||
  margin-bottom: 12px;
 | 
					  margin-bottom: 12px;
 | 
				
			||||||
@ -213,3 +213,42 @@
 | 
				
			|||||||
.blocks-behind {
 | 
					.blocks-behind {
 | 
				
			||||||
  color: #D81B60;
 | 
					  color: #D81B60;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.halving-progress {
 | 
				
			||||||
 | 
					  position: relative;
 | 
				
			||||||
 | 
					  .background, .remaining {
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    top: 0;
 | 
				
			||||||
 | 
					    bottom: 0;
 | 
				
			||||||
 | 
					    height: 100%;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .background {
 | 
				
			||||||
 | 
					    background: linear-gradient(to right, #105fb0, #9339f4);
 | 
				
			||||||
 | 
					    left: 0;
 | 
				
			||||||
 | 
					    right: 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .remaining {
 | 
				
			||||||
 | 
					    background: #2d3348;
 | 
				
			||||||
 | 
					    right: 0;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  .label {
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    margin: auto;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.widget-toggler {
 | 
				
			||||||
 | 
					  font-size: 12px;
 | 
				
			||||||
 | 
					  position: absolute;
 | 
				
			||||||
 | 
					  top: -20px;
 | 
				
			||||||
 | 
					  right: 3px;
 | 
				
			||||||
 | 
					  text-align: right;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.toggler-option {
 | 
				
			||||||
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.inactive {
 | 
				
			||||||
 | 
					  color: #ffffff66;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -51,6 +51,10 @@ export class DifficultyComponent implements OnInit {
 | 
				
			|||||||
  isLoadingWebSocket$: Observable<boolean>;
 | 
					  isLoadingWebSocket$: Observable<boolean>;
 | 
				
			||||||
  difficultyEpoch$: Observable<EpochProgress>;
 | 
					  difficultyEpoch$: Observable<EpochProgress>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mode: 'difficulty' | 'halving' = 'difficulty';
 | 
				
			||||||
 | 
					  userSelectedMode: boolean = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  now: number = Date.now();
 | 
				
			||||||
  epochStart: number;
 | 
					  epochStart: number;
 | 
				
			||||||
  currentHeight: number;
 | 
					  currentHeight: number;
 | 
				
			||||||
  currentIndex: number;
 | 
					  currentIndex: number;
 | 
				
			||||||
@ -101,6 +105,11 @@ export class DifficultyComponent implements OnInit {
 | 
				
			|||||||
        const timeUntilHalving = new Date().getTime() + (blocksUntilHalving * 600000);
 | 
					        const timeUntilHalving = new Date().getTime() + (blocksUntilHalving * 600000);
 | 
				
			||||||
        const newEpochStart = Math.floor(this.stateService.latestBlockHeight / EPOCH_BLOCK_LENGTH) * EPOCH_BLOCK_LENGTH;
 | 
					        const newEpochStart = Math.floor(this.stateService.latestBlockHeight / EPOCH_BLOCK_LENGTH) * EPOCH_BLOCK_LENGTH;
 | 
				
			||||||
        const newExpectedHeight = Math.floor(newEpochStart + da.expectedBlocks);
 | 
					        const newExpectedHeight = Math.floor(newEpochStart + da.expectedBlocks);
 | 
				
			||||||
 | 
					        this.now = new Date().getTime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (blocksUntilHalving < da.remainingBlocks && !this.userSelectedMode) {
 | 
				
			||||||
 | 
					          this.mode = 'halving';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (newEpochStart !== this.epochStart || newExpectedHeight !== this.expectedHeight || this.currentHeight !== this.stateService.latestBlockHeight) {
 | 
					        if (newEpochStart !== this.epochStart || newExpectedHeight !== this.expectedHeight || this.currentHeight !== this.stateService.latestBlockHeight) {
 | 
				
			||||||
          this.epochStart = newEpochStart;
 | 
					          this.epochStart = newEpochStart;
 | 
				
			||||||
@ -194,6 +203,12 @@ export class DifficultyComponent implements OnInit {
 | 
				
			|||||||
    return shapes;
 | 
					    return shapes;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setMode(mode: 'difficulty' | 'halving'): boolean {
 | 
				
			||||||
 | 
					    this.mode = mode;
 | 
				
			||||||
 | 
					    this.userSelectedMode = true;
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @HostListener('pointerdown', ['$event'])
 | 
					  @HostListener('pointerdown', ['$event'])
 | 
				
			||||||
  onPointerDown(event): void {
 | 
					  onPointerDown(event): void {
 | 
				
			||||||
    if (this.epochSvgElement?.nativeElement?.contains(event.target)) {
 | 
					    if (this.epochSvgElement?.nativeElement?.contains(event.target)) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user