[tx] start adding acceleration preview

This commit is contained in:
nymkappa 2023-08-24 14:17:31 +02:00
parent 3aa938a94b
commit c89e283c8e
No known key found for this signature in database
GPG Key ID: E155910B16E8BD04
10 changed files with 112 additions and 16 deletions

View File

@ -0,0 +1,24 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-accelerator-preview',
templateUrl: 'accelerate-preview.component.html',
styleUrls: ['accelerate-preview.component.scss']
})
export class AcceleratePreviewComponent implements OnInit {
constructor(
private apiService: ApiService
) { }
ngOnInit() {
this.apiService.estimate$(this.txId).subscribe((estimate) => {
console.log(estimate.body);
document.getElementById('acceleratePreviewAnchor').scrollIntoView({
behavior: 'smooth',
inline: 'center',
block: 'center',
});
})
}
}

View File

@ -6,7 +6,7 @@
position: sticky;
top: 65px;
transition: 0.25s;
margin-left: -225px;
margin-left: -250px;
box-shadow: 5px 0px 30px 0px #000;
padding-bottom: 20px;
}

View File

@ -6,6 +6,13 @@
<app-truncate [text]="rbfTransaction.txid" [lastChars]="12" [link]="['/tx/' | relativeUrl, rbfTransaction.txid]"></app-truncate>
</div>
<div *ngIf="acceleratorAvailable && accelerateCtaType === 'alert' && !tx?.status?.confirmed" class="alert alert-mempool alert-dismissible" role="alert">
<span><a class="link accelerator" (click)="onAccelerateClicked()">Accelerate</a> this transaction using the Mempool Accelerator &trade;</span>
<button type="button" class="close" aria-label="Close" (click)="dismissAccelAlert()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<ng-container *ngIf="!rbfTransaction || rbfTransaction?.size || tx">
<h1 i18n="shared.transaction">Transaction</h1>
@ -66,12 +73,38 @@
<div class="col-sm">
<ng-container *ngTemplateOutlet="feeTable"></ng-container>
</div>
</div>
</div>
</ng-template>
<ng-container *ngIf="!tx?.status?.confirmed && showAccelerationSummary">
<div class="title mt-3" id="acceleratePreviewAnchor">
<h2>Accelerate</h2>
</div>
<div class="box">
<div class="row">
<div class="col">
Test
</div>
</div>
<div class="row">
<div class="col">
Test
</div>
</div>
<div class="row">
<div class="col">
Test
</div>
</div>
</div>
</ng-container>
<span id="acceleratePreviewAnchor"></span>
<ng-template #unconfirmedTemplate>
<div class="box">
@ -92,16 +125,18 @@
</ng-template>
</ng-template>
<tr *ngIf="!replaced && !isCached">
<td class="td-width" i18n="transaction.eta|Transaction ETA">ETA</td>
<td class="td-width align-items-center align-middle" i18n="transaction.eta|Transaction ETA">ETA</td>
<td>
<ng-template [ngIf]="this.mempoolPosition?.block == null" [ngIfElse]="estimationTmpl">
<span class="skeleton-loader"></span>
</ng-template>
<ng-template #estimationTmpl>
<ng-template [ngIf]="this.mempoolPosition.block >= 7" [ngIfElse]="belowBlockLimit">
<span class="eta d-flex">
<span i18n="transaction.eta.in-several-hours|Transaction ETA in several hours or more">In several hours (or more)</span>
<span class="ml-2"></span><a *ngIf="stateService.env.OFFICIAL_MEMPOOL_SPACE && stateService.env.ACCELERATOR && stateService.network === ''" [href]="'/services/accelerator/accelerate?txid=' + tx.txid" class="btn badge badge-primary accelerate ml-auto" i18n="transaction.accelerate|Accelerate button label">Accelerate</a>
<span class="eta d-flex align-items-center">
<span class="flex-grow-1" i18n="transaction.eta.in-several-hours|Transaction ETA in several hours or more">In several hours (or more)</span>
<button class="btn btn-sm btn-purple accelerate" *ngIf="acceleratorAvailable && accelerateCtaType === 'button'" (click)="onAccelerateClicked()">
Accelerate
</button>
</span>
</ng-template>
<ng-template #belowBlockLimit>
@ -109,9 +144,11 @@
<app-time kind="until" [time]="(60 * 1000 * this.mempoolPosition.block) + now" [fastRender]="false" [fixedRender]="true"></app-time>
</ng-template>
<ng-template #timeEstimateDefault>
<span class="d-flex">
<app-time kind="until" *ngIf="(da$ | async) as da;" [time]="da.timeAvg * (this.mempoolPosition.block + 1) + now + da.timeOffset" [fastRender]="false" [fixedRender]="true"></app-time>
<span class="ml-2"></span><a *ngIf="stateService.env.OFFICIAL_MEMPOOL_SPACE && stateService.env.ACCELERATOR && stateService.network === ''" [href]="'/services/accelerator/accelerate?txid=' + tx.txid" class="btn badge badge-primary accelerate ml-auto" i18n="transaction.accelerate|Accelerate button label">Accelerate</a>
<span class="d-flex align-items-center">
<app-time class="flex-grow-1" kind="until" *ngIf="(da$ | async) as da;" [time]="da.timeAvg * (this.mempoolPosition.block + 1) + now + da.timeOffset" [fastRender]="false" [fixedRender]="true"></app-time>
<button class="btn btn-sm btn-purple accelerate" *ngIf="acceleratorAvailable && accelerateCtaType === 'button'" (click)="onAccelerateClicked()">
Accelerate
</button>
</span>
</ng-template>
</ng-template>

View File

@ -228,11 +228,15 @@
}
}
.link.accelerator {
cursor: pointer;
}
.accelerate {
align-self: auto;
margin-top: 3px;
margin-left: 10px;
@media (min-width: 850px) {
justify-self: start;
margin-left: 0px;
}
}

View File

@ -19,6 +19,7 @@ import { WebsocketService } from '../../services/websocket.service';
import { AudioService } from '../../services/audio.service';
import { ApiService } from '../../services/api.service';
import { SeoService } from '../../services/seo.service';
import { StorageService } from '../../services/storage.service';
import { BlockExtended, CpfpInfo, RbfTree, MempoolPosition, DifficultyAdjustment } from '../../interfaces/node-api.interface';
import { LiquidUnblinding } from './liquid-ublinding';
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
@ -88,6 +89,9 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
rbfEnabled: boolean;
taprootEnabled: boolean;
hasEffectiveFeeRate: boolean;
accelerateCtaType: 'alert' | 'button' = 'alert';
acceleratorAvailable: boolean = this.stateService.env.OFFICIAL_MEMPOOL_SPACE && this.stateService.env.ACCELERATOR && this.stateService.network === '';
showAccelerationSummary = false;
@ViewChild('graphContainer')
graphContainer: ElementRef;
@ -104,14 +108,20 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
private apiService: ApiService,
private seoService: SeoService,
private priceService: PriceService,
private storageService: StorageService
) {}
ngOnInit() {
this.websocketService.want(['blocks', 'mempool-blocks']);
this.stateService.networkChanged$.subscribe(
(network) => (this.network = network)
(network) => {
this.network = network;
this.acceleratorAvailable = this.stateService.env.OFFICIAL_MEMPOOL_SPACE && this.stateService.env.ACCELERATOR && this.stateService.network === '';
}
);
this.accelerateCtaType = (this.storageService.getValue('accel-cta-type') as 'alert' | 'button') ?? 'alert';
this.setFlowEnabled();
this.flowPrefSubscription = this.stateService.hideFlow.subscribe((hide) => {
this.hideFlow = !!hide;
@ -486,6 +496,19 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
this.setGraphSize();
}
dismissAccelAlert(): void {
this.storageService.setValue('accel-cta-type', 'button');
this.accelerateCtaType = 'button';
}
onAccelerateClicked(): void {
if (!this.txId) {
return;
}
this.showAccelerationSummary = true && this.acceleratorAvailable;
}
handleLoadElectrsTransactionError(error: any): Observable<any> {
if (error.status === 404 && /^[a-fA-F0-9]{64}$/.test(this.txId)) {
this.websocketService.startMultiTrackTransaction(this.txId);

View File

@ -388,4 +388,8 @@ export class ApiService {
getServicesBackendInfo$(): Observable<IBackendInfo> {
return this.httpClient.get<IBackendInfo>(`${SERVICES_API_PREFIX}/version`);
}
estimate$(txInput: string) {
return this.httpClient.post<any>(`${SERVICES_API_PREFIX}/accelerator/estimate`, { txInput: txInput }, { observe: 'response' });
}
}

View File

@ -1,19 +1,19 @@
<ng-template [ngIf]="confirmations">
<button type="button" class="btn btn-sm btn-success {{buttonClass}}">
<button type="button" class="btn btn-sm btn-success no-cursor {{buttonClass}}">
<ng-container *ngTemplateOutlet="confirmations == 1 ? confirmationSingular : confirmationPlural; context: {$implicit: confirmations}"></ng-container>
<ng-template #confirmationSingular let-i i18n="shared.confirmation-count.singular|Transaction singular confirmation count">{{ i }} confirmation</ng-template>
<ng-template #confirmationPlural let-i i18n="shared.confirmation-count.plural|Transaction plural confirmation count">{{ i }} confirmations</ng-template>
</button>
</ng-template>
<ng-template [ngIf]="!confirmations && height != null">
<button type="button" class="btn btn-sm btn-success {{buttonClass}}" i18n="transaction.confirmed|Transaction confirmed state">Confirmed</button>
<button type="button" class="btn btn-sm btn-success no-cursor {{buttonClass}}" i18n="transaction.confirmed|Transaction confirmed state">Confirmed</button>
</ng-template>
<ng-template [ngIf]="!hideUnconfirmed && !confirmations && replaced">
<button type="button" class="btn btn-sm btn-warning {{buttonClass}}" i18n="transaction.replaced|Transaction replaced state">Replaced</button>
<button type="button" class="btn btn-sm btn-warning no-cursor {{buttonClass}}" i18n="transaction.replaced|Transaction replaced state">Replaced</button>
</ng-template>
<ng-template [ngIf]="!hideUnconfirmed && !confirmations && !replaced && removed">
<button type="button" class="btn btn-sm btn-warning {{buttonClass}}" i18n="transaction.audit.removed|Transaction removed state">Removed</button>
<button type="button" class="btn btn-sm btn-warning no-cursor {{buttonClass}}" i18n="transaction.audit.removed|Transaction removed state">Removed</button>
</ng-template>
<ng-template [ngIf]="!hideUnconfirmed && chainTip != null && !confirmations && !replaced && !removed">
<button type="button" class="btn btn-sm btn-danger {{buttonClass}}" i18n="transaction.unconfirmed|Transaction unconfirmed state">Unconfirmed</button>
<button type="button" class="btn btn-sm btn-danger no-cursor {{buttonClass}}" i18n="transaction.unconfirmed|Transaction unconfirmed state">Unconfirmed</button>
</ng-template>

View File

@ -0,0 +1,4 @@
.no-cursor {
cursor: default !important;
pointer-events: none;
}