[tx] start adding acceleration preview
This commit is contained in:
parent
3aa938a94b
commit
c89e283c8e
@ -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',
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@
|
|||||||
position: sticky;
|
position: sticky;
|
||||||
top: 65px;
|
top: 65px;
|
||||||
transition: 0.25s;
|
transition: 0.25s;
|
||||||
margin-left: -225px;
|
margin-left: -250px;
|
||||||
box-shadow: 5px 0px 30px 0px #000;
|
box-shadow: 5px 0px 30px 0px #000;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,13 @@
|
|||||||
<app-truncate [text]="rbfTransaction.txid" [lastChars]="12" [link]="['/tx/' | relativeUrl, rbfTransaction.txid]"></app-truncate>
|
<app-truncate [text]="rbfTransaction.txid" [lastChars]="12" [link]="['/tx/' | relativeUrl, rbfTransaction.txid]"></app-truncate>
|
||||||
</div>
|
</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 ™</span>
|
||||||
|
<button type="button" class="close" aria-label="Close" (click)="dismissAccelAlert()">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ng-container *ngIf="!rbfTransaction || rbfTransaction?.size || tx">
|
<ng-container *ngIf="!rbfTransaction || rbfTransaction?.size || tx">
|
||||||
<h1 i18n="shared.transaction">Transaction</h1>
|
<h1 i18n="shared.transaction">Transaction</h1>
|
||||||
|
|
||||||
@ -66,12 +73,38 @@
|
|||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<ng-container *ngTemplateOutlet="feeTable"></ng-container>
|
<ng-container *ngTemplateOutlet="feeTable"></ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</ng-template>
|
</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>
|
<ng-template #unconfirmedTemplate>
|
||||||
|
|
||||||
<div class="box">
|
<div class="box">
|
||||||
@ -92,16 +125,18 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<tr *ngIf="!replaced && !isCached">
|
<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>
|
<td>
|
||||||
<ng-template [ngIf]="this.mempoolPosition?.block == null" [ngIfElse]="estimationTmpl">
|
<ng-template [ngIf]="this.mempoolPosition?.block == null" [ngIfElse]="estimationTmpl">
|
||||||
<span class="skeleton-loader"></span>
|
<span class="skeleton-loader"></span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #estimationTmpl>
|
<ng-template #estimationTmpl>
|
||||||
<ng-template [ngIf]="this.mempoolPosition.block >= 7" [ngIfElse]="belowBlockLimit">
|
<ng-template [ngIf]="this.mempoolPosition.block >= 7" [ngIfElse]="belowBlockLimit">
|
||||||
<span class="eta d-flex">
|
<span class="eta d-flex align-items-center">
|
||||||
<span i18n="transaction.eta.in-several-hours|Transaction ETA in several hours or more">In several hours (or more)</span>
|
<span class="flex-grow-1" 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>
|
<button class="btn btn-sm btn-purple accelerate" *ngIf="acceleratorAvailable && accelerateCtaType === 'button'" (click)="onAccelerateClicked()">
|
||||||
|
Accelerate
|
||||||
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #belowBlockLimit>
|
<ng-template #belowBlockLimit>
|
||||||
@ -109,9 +144,11 @@
|
|||||||
<app-time kind="until" [time]="(60 * 1000 * this.mempoolPosition.block) + now" [fastRender]="false" [fixedRender]="true"></app-time>
|
<app-time kind="until" [time]="(60 * 1000 * this.mempoolPosition.block) + now" [fastRender]="false" [fixedRender]="true"></app-time>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template #timeEstimateDefault>
|
<ng-template #timeEstimateDefault>
|
||||||
<span class="d-flex">
|
<span class="d-flex align-items-center">
|
||||||
<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>
|
<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>
|
||||||
<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>
|
<button class="btn btn-sm btn-purple accelerate" *ngIf="acceleratorAvailable && accelerateCtaType === 'button'" (click)="onAccelerateClicked()">
|
||||||
|
Accelerate
|
||||||
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -228,11 +228,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.link.accelerator {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.accelerate {
|
.accelerate {
|
||||||
align-self: auto;
|
align-self: auto;
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
|
margin-left: 10px;
|
||||||
@media (min-width: 850px) {
|
@media (min-width: 850px) {
|
||||||
justify-self: start;
|
justify-self: start;
|
||||||
margin-left: 0px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -19,6 +19,7 @@ import { WebsocketService } from '../../services/websocket.service';
|
|||||||
import { AudioService } from '../../services/audio.service';
|
import { AudioService } from '../../services/audio.service';
|
||||||
import { ApiService } from '../../services/api.service';
|
import { ApiService } from '../../services/api.service';
|
||||||
import { SeoService } from '../../services/seo.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 { BlockExtended, CpfpInfo, RbfTree, MempoolPosition, DifficultyAdjustment } from '../../interfaces/node-api.interface';
|
||||||
import { LiquidUnblinding } from './liquid-ublinding';
|
import { LiquidUnblinding } from './liquid-ublinding';
|
||||||
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
|
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
|
||||||
@ -88,6 +89,9 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
rbfEnabled: boolean;
|
rbfEnabled: boolean;
|
||||||
taprootEnabled: boolean;
|
taprootEnabled: boolean;
|
||||||
hasEffectiveFeeRate: 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')
|
@ViewChild('graphContainer')
|
||||||
graphContainer: ElementRef;
|
graphContainer: ElementRef;
|
||||||
@ -104,14 +108,20 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
private seoService: SeoService,
|
private seoService: SeoService,
|
||||||
private priceService: PriceService,
|
private priceService: PriceService,
|
||||||
|
private storageService: StorageService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.websocketService.want(['blocks', 'mempool-blocks']);
|
this.websocketService.want(['blocks', 'mempool-blocks']);
|
||||||
this.stateService.networkChanged$.subscribe(
|
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.setFlowEnabled();
|
||||||
this.flowPrefSubscription = this.stateService.hideFlow.subscribe((hide) => {
|
this.flowPrefSubscription = this.stateService.hideFlow.subscribe((hide) => {
|
||||||
this.hideFlow = !!hide;
|
this.hideFlow = !!hide;
|
||||||
@ -486,6 +496,19 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
this.setGraphSize();
|
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> {
|
handleLoadElectrsTransactionError(error: any): Observable<any> {
|
||||||
if (error.status === 404 && /^[a-fA-F0-9]{64}$/.test(this.txId)) {
|
if (error.status === 404 && /^[a-fA-F0-9]{64}$/.test(this.txId)) {
|
||||||
this.websocketService.startMultiTrackTransaction(this.txId);
|
this.websocketService.startMultiTrackTransaction(this.txId);
|
||||||
|
@ -388,4 +388,8 @@ export class ApiService {
|
|||||||
getServicesBackendInfo$(): Observable<IBackendInfo> {
|
getServicesBackendInfo$(): Observable<IBackendInfo> {
|
||||||
return this.httpClient.get<IBackendInfo>(`${SERVICES_API_PREFIX}/version`);
|
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' });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
<ng-template [ngIf]="confirmations">
|
<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-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 #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>
|
<ng-template #confirmationPlural let-i i18n="shared.confirmation-count.plural|Transaction plural confirmation count">{{ i }} confirmations</ng-template>
|
||||||
</button>
|
</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template [ngIf]="!confirmations && height != null">
|
<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>
|
||||||
<ng-template [ngIf]="!hideUnconfirmed && !confirmations && replaced">
|
<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>
|
||||||
<ng-template [ngIf]="!hideUnconfirmed && !confirmations && !replaced && removed">
|
<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>
|
||||||
<ng-template [ngIf]="!hideUnconfirmed && chainTip != null && !confirmations && !replaced && !removed">
|
<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>
|
</ng-template>
|
@ -0,0 +1,4 @@
|
|||||||
|
.no-cursor {
|
||||||
|
cursor: default !important;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user