mirror of
https://github.com/mempool/mempool.git
synced 2025-02-28 16:58:32 +01:00
98 lines
3 KiB
TypeScript
98 lines
3 KiB
TypeScript
import { Component, OnInit, Input, Output, OnChanges, EventEmitter, HostListener, Inject, LOCALE_ID } from '@angular/core';
|
|
import { StateService } from '../../services/state.service';
|
|
import { Outspend, Transaction, Vin, Vout } from '../../interfaces/electrs.interface';
|
|
import { Router } from '@angular/router';
|
|
import { ReplaySubject, merge, Subscription, of } from 'rxjs';
|
|
import { tap, switchMap } from 'rxjs/operators';
|
|
import { ApiService } from '../../services/api.service';
|
|
import { AccelerationEstimate, RateOption } from './accelerate-preview.component';
|
|
|
|
interface GraphBar {
|
|
rate: number;
|
|
style: any;
|
|
class: 'tx' | 'target' | 'max';
|
|
label: string;
|
|
active?: boolean;
|
|
rateIndex?: number;
|
|
fee?: number;
|
|
}
|
|
|
|
@Component({
|
|
selector: 'app-accelerate-fee-graph',
|
|
templateUrl: './accelerate-fee-graph.component.html',
|
|
styleUrls: ['./accelerate-fee-graph.component.scss'],
|
|
})
|
|
export class AccelerateFeeGraphComponent implements OnInit, OnChanges {
|
|
@Input() tx: Transaction;
|
|
@Input() estimate: AccelerationEstimate;
|
|
@Input() maxRateOptions: RateOption[] = [];
|
|
@Input() maxRateIndex: number = 0;
|
|
@Output() setUserBid = new EventEmitter<{ fee: number, index: number }>();
|
|
|
|
bars: GraphBar[] = [];
|
|
tooltipPosition = { x: 0, y: 0 };
|
|
|
|
ngOnInit(): void {
|
|
this.initGraph();
|
|
}
|
|
|
|
ngOnChanges(): void {
|
|
this.initGraph();
|
|
}
|
|
|
|
initGraph(): void {
|
|
if (!this.tx || !this.estimate) {
|
|
return;
|
|
}
|
|
const maxRate = Math.max(...this.maxRateOptions.map(option => option.rate));
|
|
const baseRate = this.estimate.txSummary.effectiveFee / this.estimate.txSummary.effectiveVsize;
|
|
const baseHeight = baseRate / maxRate;
|
|
const bars: GraphBar[] = this.maxRateOptions.slice().reverse().map(option => {
|
|
return {
|
|
rate: option.rate,
|
|
style: this.getStyle(option.rate, maxRate, baseHeight),
|
|
class: 'max',
|
|
label: 'maximum',
|
|
active: option.index === this.maxRateIndex,
|
|
rateIndex: option.index,
|
|
fee: option.fee,
|
|
}
|
|
});
|
|
if (this.estimate.nextBlockFee > this.estimate.txSummary.effectiveFee) {
|
|
bars.push({
|
|
rate: this.estimate.targetFeeRate,
|
|
style: this.getStyle(this.estimate.targetFeeRate, maxRate, baseHeight),
|
|
class: 'target',
|
|
label: 'next block',
|
|
fee: this.estimate.nextBlockFee - this.estimate.txSummary.effectiveFee
|
|
});
|
|
}
|
|
bars.push({
|
|
rate: baseRate,
|
|
style: this.getStyle(baseRate, maxRate, 0),
|
|
class: 'tx',
|
|
label: '',
|
|
fee: this.estimate.txSummary.effectiveFee,
|
|
});
|
|
this.bars = bars;
|
|
}
|
|
|
|
getStyle(rate, maxRate, base) {
|
|
const top = (rate / maxRate);
|
|
return {
|
|
height: `${(top - base) * 100}%`,
|
|
bottom: base ? `${base * 100}%` : '0',
|
|
}
|
|
}
|
|
|
|
onClick(event, bar): void {
|
|
if (bar.rateIndex != null) {
|
|
this.setUserBid.emit({ fee: bar.fee, index: bar.rateIndex });
|
|
}
|
|
}
|
|
|
|
@HostListener('pointermove', ['$event'])
|
|
onPointerMove(event) {
|
|
this.tooltipPosition = { x: event.offsetX, y: event.offsetY };
|
|
}
|
|
}
|