diff --git a/frontend/src/app/components/tracker/tracker-bar.component.ts b/frontend/src/app/components/tracker/tracker-bar.component.ts index 26f2e705b..bb073f557 100644 --- a/frontend/src/app/components/tracker/tracker-bar.component.ts +++ b/frontend/src/app/components/tracker/tracker-bar.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; -export type TrackerStage = 'waiting' | 'pending' | 'soon' | 'next' | 'confirmed'; +export type TrackerStage = 'waiting' | 'pending' | 'soon' | 'next' | 'confirmed' | 'replaced'; @Component({ selector: 'app-tracker-bar', diff --git a/frontend/src/app/components/tracker/tracker.component.html b/frontend/src/app/components/tracker/tracker.component.html index 5f5f62a1e..81188eaf9 100644 --- a/frontend/src/app/components/tracker/tracker.component.html +++ b/frontend/src/app/components/tracker/tracker.component.html @@ -43,9 +43,16 @@
-
- -
+ @if (replaced) { + + } @else { +
+ +
+ }
@if (tx && !tx.status?.confirmed && mempoolPosition?.block != null) {
@@ -143,6 +150,12 @@
Your transaction is confirmed! } + @case ('replaced') { +
+ +
+ Your transaction has been replaced by a newer version! + } } } } diff --git a/frontend/src/app/components/tracker/tracker.component.scss b/frontend/src/app/components/tracker/tracker.component.scss index ac9992926..ffa6208b7 100644 --- a/frontend/src/app/components/tracker/tracker.component.scss +++ b/frontend/src/app/components/tracker/tracker.component.scss @@ -187,4 +187,12 @@ padding: 0.5em; background: var(--primary); color: white; + cursor: pointer; +} + +.alert-replaced { + background: var(--danger); + margin: 1em 0.5em; + padding: 0.5em; + border-radius: 0.5em; } \ No newline at end of file diff --git a/frontend/src/app/components/tracker/tracker.component.ts b/frontend/src/app/components/tracker/tracker.component.ts index 6000e2f10..4c91db5cc 100644 --- a/frontend/src/app/components/tracker/tracker.component.ts +++ b/frontend/src/app/components/tracker/tracker.component.ts @@ -76,6 +76,7 @@ export class TrackerComponent implements OnInit, OnDestroy { currencyChangeSubscription: Subscription; rbfTransaction: undefined | Transaction; replaced: boolean = false; + latestReplacement: string; rbfReplaces: string[]; rbfInfo: RbfTree; cpfpInfo: CpfpInfo | null; @@ -218,6 +219,9 @@ export class TrackerComponent implements OnInit, OnDestroy { ).subscribe((rbfResponse) => { this.rbfInfo = rbfResponse?.replacements; this.rbfReplaces = rbfResponse?.replaces || null; + if (this.rbfInfo) { + this.latestReplacement = this.rbfInfo.tx.txid; + } }); this.fetchCachedTxSubscription = this.fetchCachedTx$ @@ -350,7 +354,9 @@ export class TrackerComponent implements OnInit, OnDestroy { this.tx.acceleratedBy = txPosition.position?.acceleratedBy; } - if (txPosition.position?.block === 0) { + if (this.replaced) { + this.trackerStage = 'replaced'; + } else if (txPosition.position?.block === 0) { this.trackerStage = 'next'; } else if (txPosition.position?.block < 3){ this.trackerStage = 'soon'; @@ -520,6 +526,10 @@ export class TrackerComponent implements OnInit, OnDestroy { } this.rbfTransaction = rbfTransaction; this.replaced = true; + this.trackerStage = 'replaced'; + if (!this.rbfInfo) { + this.latestReplacement = this.rbfTransaction.txid; + } this.stateService.markBlock$.next({}); if (rbfTransaction && !this.tx) { @@ -663,6 +673,7 @@ export class TrackerComponent implements OnInit, OnDestroy { this.isLoadingTx = true; this.rbfTransaction = undefined; this.replaced = false; + this.latestReplacement = ''; this.transactionTime = -1; this.cpfpInfo = null; this.adjustedVsize = null; diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index 777ca7180..3b56d3510 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -4,7 +4,7 @@ import { NgbCollapseModule, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstra import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome'; import { faFilter, faAngleDown, faAngleUp, faAngleRight, faAngleLeft, faBolt, faChartArea, faCogs, faCubes, faHammer, faDatabase, faExchangeAlt, faInfoCircle, faLink, faList, faSearch, faCaretUp, faCaretDown, faTachometerAlt, faThList, faTint, faTv, faClock, faAngleDoubleDown, faSortUp, faAngleDoubleUp, faChevronDown, - faFileAlt, faRedoAlt, faArrowAltCircleRight, faExternalLinkAlt, faBook, faListUl, faDownload, faQrcode, faArrowRightArrowLeft, faArrowsRotate, faCircleLeft, faFastForward, faWallet, faUserClock, faWrench, faUserFriends, faQuestionCircle, faHistory, faSignOutAlt, faKey, faSuitcase, faIdCardAlt, faNetworkWired, faUserCheck, faCircleCheck, faUserCircle, faCheck, faRocket, faScaleBalanced, faHourglassStart, faHourglassHalf, faHourglassEnd, faWandMagicSparkles, faFaucetDrip } from '@fortawesome/free-solid-svg-icons'; + faFileAlt, faRedoAlt, faArrowAltCircleRight, faExternalLinkAlt, faBook, faListUl, faDownload, faQrcode, faArrowRightArrowLeft, faArrowsRotate, faCircleLeft, faFastForward, faWallet, faUserClock, faWrench, faUserFriends, faQuestionCircle, faHistory, faSignOutAlt, faKey, faSuitcase, faIdCardAlt, faNetworkWired, faUserCheck, faCircleCheck, faUserCircle, faCheck, faRocket, faScaleBalanced, faHourglassStart, faHourglassHalf, faHourglassEnd, faWandMagicSparkles, faFaucetDrip, faTimeline } from '@fortawesome/free-solid-svg-icons'; import { InfiniteScrollModule } from 'ngx-infinite-scroll'; import { MenuComponent } from '../components/menu/menu.component'; import { PreviewTitleComponent } from '../components/master-page-preview/preview-title.component'; @@ -438,5 +438,6 @@ export class SharedModule { library.addIcons(faHourglassEnd); library.addIcons(faWandMagicSparkles); library.addIcons(faFaucetDrip); + library.addIcons(faTimeline); } }