From 415ad3de708183ac80b0465b68420b6974a44ed5 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Thu, 27 Jun 2024 09:10:32 +0000 Subject: [PATCH] Merge simple & advanced acceleration checkout components --- .../accelerate-checkout.component.html | 342 +++++++++++++++--- .../accelerate-checkout.component.scss | 130 +++++++ .../accelerate-checkout.component.ts | 160 +++++++- .../accelerate-fee-graph.component.html | 21 ++ .../accelerate-fee-graph.component.scss | 156 ++++++++ .../accelerate-fee-graph.component.ts | 100 +++++ .../components/tracker/tracker.component.html | 2 +- .../transaction/transaction.component.html | 16 +- .../transaction/transaction.module.ts | 4 +- frontend/src/app/services/eta.service.ts | 2 +- 10 files changed, 854 insertions(+), 79 deletions(-) create mode 100644 frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.html create mode 100644 frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.scss create mode 100644 frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.ts diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html index 1b1ca6ca4..39e659971 100644 --- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html +++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.html @@ -1,66 +1,306 @@ -
+
@if (error) {
} - - @else if (step === 'cta') { - -
-
-

Accelerate your Bitcoin transaction?

-
-
- -
-
-
-
- - + @else if (step === 'quote') { + @if (!simpleMode) { + +
+
+
+ Transaction has now been submitted to mining pools for acceleration.
-
-
- -
+ + +
+
+ +
+
+ +
+ + + + + +
+ +
+
You are currently on the waitlist
+
+ + @if (showDetails) { +
Your transaction
+
+
+ + Plus {{ estimate.txSummary.ancestorCount - 1 }} unconfirmed ancestor(s) + + + + + + + + + + + + + + + + + + +
Virtual size
+ Size in vbytes of this transaction (including unconfirmed ancestors) +
In-band fees + {{ estimate.txSummary.effectiveFee | number : '1.0-0' }} sats +
+ Fees already paid by this transaction (including unconfirmed ancestors) +
+
+
+
+ } +
How much faster?
+
+
+ + Your transaction will be prioritized by up to {{ etaInfo.hashratePercentage | number : '1.1-1' }}% of miners. + This will reduce your expected waiting time until the first confirmation to + +
+
+ +
+
+
+
+
+
+
+ + + +
+
+
+
+
+ +
Summary
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Next block market rate + {{ estimate.targetFeeRate | number : '1.0-0' }} + sat/vB
+ Estimated extra fee required + + {{ math.max(0, estimate.nextBlockFee - estimate.txSummary.effectiveFee) | number }} + + sats + +
Mempool Acceleratorâ„¢ fees
+ Accelerator Service Fee + + +{{ estimate.mempoolBaseFee | number }} + + sats + +
+ Transaction Size Surcharge + + +{{ estimate.vsizeFee | number }} + + sats + +
+ Estimated acceleration cost ~{{ estimate.targetFeeRate | number : '1.0-0' }} sat/vB + + + {{ estimate.cost + estimate.mempoolBaseFee + estimate.vsizeFee | number }} + + + sats + +
+ @if (isLoggedIn()) { + Maximum acceleration cost + } @else { + Acceleration cost + } + + + {{ cost | number }} + + + sats + + + +
Available balance + {{ estimate.userBalance | number }} + + sats + + + +
+
+ +
+
+
+
+
+
+
+ + +
+
+
+ } + @else { + +
+
+

Accelerate your Bitcoin transaction?

+
+
+ + +
+
+
+ + + +
+
+
+
+ + +
+
+
+ Your transaction will be prioritized by up to {{ etaInfo.hashratePercentage | number : '1.1-1' }}% of miners. +
-
- Your transaction will be prioritized by up to {{ etaInfo.hashratePercentage | number : '1.1-1' }}% of miners. - +
+
+ +
-
-
-
- -
-
- - + + } } @else if (step === 'paymentMethod') {
@@ -82,7 +322,7 @@
- +
diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.scss b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.scss index af11f6c2b..e03f223ca 100644 --- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.scss +++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.scss @@ -24,4 +24,134 @@ display: flex; align-items: center; max-width: 330px; +} + +.fee-card { + padding: 15px; + background-color: var(--bg); + + .feerate { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + .rate { + font-size: 0.9em; + .symbol { + color: white; + } + } + } +} + +.btn-border { + border: solid 1px black; + background-color: #0c4a87; +} + +.feerate.active { + background-color: var(--primary) !important; + opacity: 1; + border: 1px solid #007fff !important; +} +.feerate:focus { + box-shadow: none !important; +} + +.estimateDisabled { + opacity: 0.5; + pointer-events: none; +} + +.table-toggle { + width: 100%; + margin-top: 0.5em; +} + +.tab { + &:first-child { + margin-right: 1px; + } + border: solid 1px black; + border-bottom: none; + background-color: #323655; + border-top-left-radius: 10px !important; + border-top-right-radius: 10px !important; +} +.tab.active { + background-color: #5d659d !important; + opacity: 1; +} +.tab:focus { + box-shadow: none !important; +} + +.table-accelerator { + tr { + td { + padding-top: 0; + padding-bottom: 0; + vertical-align: baseline; + } + + &.group-first { + td { + padding-top: 0.75rem; + } + } + &.group-last, &:last-child { + td { + padding-bottom: 0.75rem; + } + } + &.dashed-top { + border-top: 1px dashed grey; + } + &.dashed-bottom { + border-bottom: 1px dashed grey + } + } + td { + &:first-child { + width: 100vw; + } + &.info { + color: #6c757d; + white-space: initial; + } + &.amt { + text-align: right; + padding-right: 0.2em; + } + &.units { + padding-left: 0.2em; + white-space: nowrap; + display: flex; + justify-content: space-between; + align-items: center; + } + } +} + +.accelerate-cols { + display: flex; + flex-direction: row; + align-items: stretch; + margin-top: 1em; +} + +.col.pie { + flex-grow: 0; + padding: 0 1em; + position: relative; + top: -15px; +} + +.item { + white-space: initial; +} + +.table-background { + background-color: var(--bg); } \ No newline at end of file diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts index 8714373d0..3d720e757 100644 --- a/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts +++ b/frontend/src/app/components/accelerate-checkout/accelerate-checkout.component.ts @@ -1,13 +1,42 @@ -import { Component, OnInit, OnDestroy, Output, EventEmitter, Input, ChangeDetectorRef, SimpleChanges } from '@angular/core'; +import { Component, OnInit, OnDestroy, Output, EventEmitter, Input, ChangeDetectorRef, SimpleChanges, HostListener } from '@angular/core'; import { Subscription, tap, of, catchError, Observable } from 'rxjs'; import { ServicesApiServices } from '../../services/services-api.service'; import { nextRoundNumber } from '../../shared/common.utils'; import { StateService } from '../../services/state.service'; import { AudioService } from '../../services/audio.service'; -import { AccelerationEstimate } from '../accelerate-preview/accelerate-preview.component'; import { ETA, EtaService } from '../../services/eta.service'; import { Transaction } from '../../interfaces/electrs.interface'; import { MiningStats } from '../../services/mining.service'; +import { StorageService } from '../../services/storage.service'; + +export type AccelerationEstimate = { + hasAccess: boolean; + txSummary: TxSummary; + nextBlockFee: number; + targetFeeRate: number; + userBalance: number; + enoughBalance: boolean; + cost: number; + mempoolBaseFee: number; + vsizeFee: number; + pools: number[] +} +export type TxSummary = { + txid: string; // txid of the current transaction + effectiveVsize: number; // Total vsize of the dependency tree + effectiveFee: number; // Total fee of the dependency tree in sats + ancestorCount: number; // Number of ancestors +} + +export interface RateOption { + fee: number; + rate: number; + index: number; +} + +export const MIN_BID_RATIO = 1; +export const DEFAULT_BID_RATIO = 2; +export const MAX_BID_RATIO = 4; @Component({ selector: 'app-accelerate-checkout', @@ -20,24 +49,43 @@ export class AccelerateCheckout implements OnInit, OnDestroy { @Input() eta: ETA; @Input() scrollEvent: boolean; @Input() cashappEnabled: boolean; - @Input() isTracker: boolean = false; + @Input() showDetails: boolean; + @Input() advancedEnabled: boolean = false; + @Input() forceMobile: boolean = false; + @Output() changeMode = new EventEmitter(); @Output() close = new EventEmitter(); calculating = true; choosenOption: 'wait' | 'accel'; error = ''; + math = Math; + isMobile: boolean = window.innerWidth <= 767.98; - step: 'paymentMethod' | 'cta' | 'checkout' | 'processing' = 'cta'; + step: 'quote' | 'paymentMethod' | 'checkout' | 'processing' = 'quote'; + simpleMode: boolean = true; paymentMethod: 'cashapp' | 'btcpay'; + user: any = undefined; + // accelerator stuff square: { appId: string, locationId: string}; accelerationUUID: string; + accelerationSubscription: Subscription; + difficultySubscription: Subscription; estimateSubscription: Subscription; estimate: AccelerationEstimate; maxBidBoost: number; // sats cost: number; // sats etaInfo$: Observable<{ hashratePercentage: number, ETA: number, acceleratedETA: number }>; + showSuccess = false; + hasAncestors: boolean = false; + minExtraCost = 0; + minBidAllowed = 0; + maxBidAllowed = 0; + defaultBid = 0; + userBid = 0; + selectFeeRateIndex = 1; + maxRateOptions: RateOption[] = []; // square loadingCashapp = false; @@ -52,8 +100,9 @@ export class AccelerateCheckout implements OnInit, OnDestroy { invoice = undefined; constructor( + public stateService: StateService, private servicesApiService: ServicesApiServices, - private stateService: StateService, + private storageService: StorageService, private etaService: EtaService, private audioService: AudioService, private cd: ChangeDetectorRef @@ -62,6 +111,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy { } ngOnInit() { + this.user = this.storageService.getAuth()?.user ?? null; const urlParams = new URLSearchParams(window.location.search); if (urlParams.get('cash_request_id')) { // Redirected from cashapp this.insertSquare(); @@ -74,7 +124,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy { appId: ids.squareAppId, locationId: ids.squareLocationId }; - if (this.step === 'cta') { + if (this.step === 'quote') { this.fetchEstimate(); } }); @@ -95,7 +145,7 @@ export class AccelerateCheckout implements OnInit, OnDestroy { /** * Scroll to element id with or without setTimeout */ - scrollToElementWithTimeout(id: string, position: ScrollLogicalPosition, timeout: number = 1000) { + scrollToElementWithTimeout(id: string, position: ScrollLogicalPosition, timeout: number = 1000): void { setTimeout(() => { this.scrollToElement(id, position); }, timeout); @@ -130,24 +180,100 @@ export class AccelerateCheckout implements OnInit, OnDestroy { this.error = `cannot_accelerate_tx`; return; } + if (this.estimate.hasAccess === true && this.estimate.userBalance <= 0) { + if (this.isLoggedIn()) { + this.error = `not_enough_balance`; + } + } + this.hasAncestors = this.estimate.txSummary.ancestorCount > 1; + this.etaInfo$ = this.etaService.getProjectedEtaObservable(this.estimate, this.miningStats); + // Make min extra fee at least 50% of the current tx fee - const minExtraBoost = nextRoundNumber(Math.max(this.estimate.cost * 2, this.estimate.txSummary.effectiveFee)); - const DEFAULT_BID_RATIO = 1.5; - this.maxBidBoost = minExtraBoost * DEFAULT_BID_RATIO; - this.cost = this.maxBidBoost + this.estimate.mempoolBaseFee + this.estimate.vsizeFee; - this.etaInfo$ = this.etaService.getProjectedEtaObservable(this.estimate); + this.minExtraCost = nextRoundNumber(Math.max(this.estimate.cost * 2, this.estimate.txSummary.effectiveFee)); + + this.maxRateOptions = [1, 2, 4].map((multiplier, index) => { + return { + fee: this.minExtraCost * multiplier, + rate: (this.estimate.txSummary.effectiveFee + (this.minExtraCost * multiplier)) / this.estimate.txSummary.effectiveVsize, + index, + }; + }); + + this.minBidAllowed = this.minExtraCost * MIN_BID_RATIO; + this.defaultBid = this.minExtraCost * DEFAULT_BID_RATIO; + this.maxBidAllowed = this.minExtraCost * MAX_BID_RATIO; + + this.userBid = this.defaultBid; + if (this.userBid < this.minBidAllowed) { + this.userBid = this.minBidAllowed; + } else if (this.userBid > this.maxBidAllowed) { + this.userBid = this.maxBidAllowed; + } + this.cost = this.userBid + this.estimate.mempoolBaseFee + this.estimate.vsizeFee; + this.calculating = false; this.cd.markForCheck(); } }), catchError((response) => { + this.estimate = undefined; this.error = `cannot_accelerate_tx`; + this.estimateSubscription.unsubscribe(); return of(null); }) ).subscribe(); } + /** + * User changed his bid + */ + setUserBid({ fee, index }: { fee: number, index: number}): void { + if (this.estimate) { + this.selectFeeRateIndex = index; + this.userBid = Math.max(0, fee); + this.cost = this.userBid + this.estimate.mempoolBaseFee + this.estimate.vsizeFee; + } + } + + /** + * Advanced mode acceleration button clicked + */ + accelerate(): void { + if (this.isLoggedIn()) { + this.accelerateWithMempoolAccount(); + } else { + this.step = 'paymentMethod'; + } + } + + /** + * Account-based acceleration request + */ + accelerateWithMempoolAccount(): void { + if (this.accelerationSubscription) { + this.accelerationSubscription.unsubscribe(); + } + this.accelerationSubscription = this.servicesApiService.accelerate$( + this.tx.txid, + this.userBid, + this.accelerationUUID + ).subscribe({ + next: () => { + this.audioService.playSound('ascend-chime-cartoon'); + this.showSuccess = true; + this.estimateSubscription.unsubscribe(); + }, + error: (response) => { + if (response.status === 403 && response.error === 'not_available') { + this.error = 'waitlisted'; + } else { + this.error = response.error; + } + } + }); + } + /** * Square */ @@ -321,4 +447,14 @@ export class AccelerateCheckout implements OnInit, OnDestroy { this.close.emit(); }, timeout); } + + isLoggedIn(): boolean { + const auth = this.storageService.getAuth(); + return auth !== null; + } + + @HostListener('window:resize', ['$event']) + onResize(): void { + this.isMobile = window.innerWidth <= 767.98; + } } diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.html b/frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.html new file mode 100644 index 000000000..fe0718ecc --- /dev/null +++ b/frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.html @@ -0,0 +1,21 @@ +
+
+ +
+
+
+

+ {{ bar.label }} + + + +

+
+
+ {{ bar.class === 'tx' ? '' : '+' }} {{ bar.fee | number }} sat +
+
+
+
+
+
diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.scss b/frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.scss new file mode 100644 index 000000000..919fdec4a --- /dev/null +++ b/frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.scss @@ -0,0 +1,156 @@ +.fee-graph { + height: 100%; + min-width: 120px; + width: 120px; + margin-left: 4em; + margin-right: 1.5em; + + .column { + width: 100%; + height: 100%; + position: relative; + background: var(--stat-box-bg); + + .bar { + position: absolute; + bottom: 0; + left: 0; + right: 0; + min-height: 30px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + .fill { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + opacity: 0.75; + pointer-events: none; + } + + .fee { + font-size: 0.9em; + opacity: 0; + pointer-events: none; + } + + .spacer { + width: 100%; + height: 1px; + flex-grow: 1; + pointer-events: none; + } + + .line { + position: absolute; + right: 0; + top: 0; + left: -4.5em; + border-top: dashed white 1.5px; + + .fee-rate { + width: 100%; + position: absolute; + left: 0; + right: 0.2em; + font-size: 0.8em; + display: flex; + flex-direction: row-reverse; + justify-content: space-between; + margin: 0; + + .label { + margin-right: .2em; + } + + .rate .symbol { + color: white; + } + } + } + + &.tx { + .fill { + background: var(--green); + } + .line { + .fee-rate { + top: 0; + } + } + .fee { + position: absolute; + opacity: 1; + z-index: 11; + } + } + + &.target { + .fill { + background: var(--tertiary); + } + .fee { + position: absolute; + opacity: 1; + z-index: 11; + } + .line .fee-rate { + bottom: 2px; + } + } + + &.max { + cursor: pointer; + .line .fee-rate { + .label { + opacity: 0; + } + bottom: 2px; + } + &.active, &:hover { + .fill { + background: var(--primary); + } + .line { + .fee-rate .label { + opacity: 1; + } + } + } + } + + &:hover { + .fill { + z-index: 10; + } + .line { + z-index: 11; + } + .fee { + opacity: 1; + z-index: 12; + } + } + } + + &:hover > .bar:not(:hover) { + &.target, &.max { + .fee { + opacity: 0; + } + .line .fee-rate .label { + opacity: 0; + } + } + &.max { + .fill { + background: none; + } + } + } + } +} \ No newline at end of file diff --git a/frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.ts b/frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.ts new file mode 100644 index 000000000..c41cb2f87 --- /dev/null +++ b/frontend/src/app/components/accelerate-checkout/accelerate-fee-graph.component.ts @@ -0,0 +1,100 @@ +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-checkout.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() showEstimate = false; + @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; + console.log(maxRate, baseRate, baseHeight); + const bars: GraphBar[] = this.maxRateOptions.slice().reverse().map(option => { + return { + rate: option.rate, + style: this.getStyle(option.rate, maxRate, baseHeight), + class: 'max', + label: this.showEstimate ? $localize`maximum` : $localize`accelerated`, + 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: $localize`:@@bdf0e930eb22431140a2eaeacd809cc5f8ebd38c:Next Block`.toLowerCase(), + 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 }; + } +} diff --git a/frontend/src/app/components/tracker/tracker.component.html b/frontend/src/app/components/tracker/tracker.component.html index c0f77c424..faa2db793 100644 --- a/frontend/src/app/components/tracker/tracker.component.html +++ b/frontend/src/app/components/tracker/tracker.component.html @@ -117,7 +117,7 @@
@if (showAccelerationSummary && !accelerationFlowCompleted) { - + } @else { @if (tx?.acceleration && !tx.status?.confirmed) { diff --git a/frontend/src/app/components/transaction/transaction.component.html b/frontend/src/app/components/transaction/transaction.component.html index 65c859e5c..87477c5d7 100644 --- a/frontend/src/app/components/transaction/transaction.component.html +++ b/frontend/src/app/components/transaction/transaction.component.html @@ -84,17 +84,11 @@
- @if (isLoggedIn()) { -
- -
- } @else { - - - Urgent transaction? Get it confirmed faster. - - - } + + + Urgent transaction? Get it confirmed faster. + + diff --git a/frontend/src/app/components/transaction/transaction.module.ts b/frontend/src/app/components/transaction/transaction.module.ts index ac09067de..b536b3045 100644 --- a/frontend/src/app/components/transaction/transaction.module.ts +++ b/frontend/src/app/components/transaction/transaction.module.ts @@ -5,9 +5,8 @@ import { TransactionComponent } from './transaction.component'; import { SharedModule } from '../../shared/shared.module'; import { TxBowtieModule } from '../tx-bowtie-graph/tx-bowtie.module'; import { GraphsModule } from '../../graphs/graphs.module'; -import { AcceleratePreviewComponent } from '../accelerate-preview/accelerate-preview.component'; import { AccelerateCheckout } from '../accelerate-checkout/accelerate-checkout.component'; -import { AccelerateFeeGraphComponent } from '../accelerate-preview/accelerate-fee-graph.component'; +import { AccelerateFeeGraphComponent } from '../accelerate-checkout/accelerate-fee-graph.component'; import { TrackerComponent } from '../tracker/tracker.component'; import { TrackerBarComponent } from '../tracker/tracker-bar.component'; @@ -43,7 +42,6 @@ export class TransactionRoutingModule { } TransactionComponent, TrackerComponent, TrackerBarComponent, - AcceleratePreviewComponent, AccelerateCheckout, AccelerateFeeGraphComponent, ] diff --git a/frontend/src/app/services/eta.service.ts b/frontend/src/app/services/eta.service.ts index 3dc396a55..cc1436e4c 100644 --- a/frontend/src/app/services/eta.service.ts +++ b/frontend/src/app/services/eta.service.ts @@ -5,7 +5,7 @@ import { MempoolBlock } from '../interfaces/websocket.interface'; import { Transaction } from '../interfaces/electrs.interface'; import { MiningService, MiningStats } from './mining.service'; import { getUnacceleratedFeeRate } from '../shared/transaction.utils'; -import { AccelerationEstimate } from '../components/accelerate-preview/accelerate-preview.component'; +import { AccelerationEstimate } from '../components/accelerate-checkout/accelerate-checkout.component'; import { Observable, combineLatest, map, of, share, shareReplay, tap } from 'rxjs'; export interface ETA {