ETA |
diff --git a/frontend/src/app/components/transaction/transaction.component.scss b/frontend/src/app/components/transaction/transaction.component.scss
index 2208909ef..47c8baa4a 100644
--- a/frontend/src/app/components/transaction/transaction.component.scss
+++ b/frontend/src/app/components/transaction/transaction.component.scss
@@ -204,4 +204,10 @@
.txids {
width: 60%;
}
+}
+
+.tx-list {
+ .alert-link {
+ display: block;
+ }
}
\ No newline at end of file
diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts
index b32be6a8e..7e1ae525e 100644
--- a/frontend/src/app/components/transaction/transaction.component.ts
+++ b/frontend/src/app/components/transaction/transaction.component.ts
@@ -40,15 +40,21 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
transactionTime = -1;
subscription: Subscription;
fetchCpfpSubscription: Subscription;
+ fetchRbfSubscription: Subscription;
+ fetchCachedTxSubscription: Subscription;
txReplacedSubscription: Subscription;
blocksSubscription: Subscription;
queryParamsSubscription: Subscription;
urlFragmentSubscription: Subscription;
fragmentParams: URLSearchParams;
rbfTransaction: undefined | Transaction;
+ replaced: boolean = false;
+ rbfReplaces: string[];
cpfpInfo: CpfpInfo | null;
showCpfpDetails = false;
fetchCpfp$ = new Subject();
+ fetchRbfHistory$ = new Subject();
+ fetchCachedTx$ = new Subject();
now = new Date().getTime();
timeAvg$: Observable;
liquidUnblinding = new LiquidUnblinding();
@@ -159,6 +165,49 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
this.cpfpInfo = cpfpInfo;
});
+ this.fetchRbfSubscription = this.fetchRbfHistory$
+ .pipe(
+ switchMap((txId) =>
+ this.apiService
+ .getRbfHistory$(txId)
+ ),
+ catchError(() => {
+ return of([]);
+ })
+ ).subscribe((replaces) => {
+ this.rbfReplaces = replaces;
+ });
+
+ this.fetchCachedTxSubscription = this.fetchCachedTx$
+ .pipe(
+ switchMap((txId) =>
+ this.apiService
+ .getRbfCachedTx$(txId)
+ ),
+ catchError(() => {
+ return of(null);
+ })
+ ).subscribe((tx) => {
+ if (!tx) {
+ return;
+ }
+
+ this.tx = tx;
+ if (tx.fee === undefined) {
+ this.tx.fee = 0;
+ }
+ this.tx.feePerVsize = tx.fee / (tx.weight / 4);
+ this.isLoadingTx = false;
+ this.error = undefined;
+ this.waitingForTransaction = false;
+ this.graphExpanded = false;
+ this.setupGraph();
+
+ if (!this.tx?.status?.confirmed) {
+ this.fetchRbfHistory$.next(this.tx.txid);
+ }
+ });
+
this.subscription = this.route.paramMap
.pipe(
switchMap((params: ParamMap) => {
@@ -272,6 +321,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
} else {
this.fetchCpfp$.next(this.tx.txid);
}
+ this.fetchRbfHistory$.next(this.tx.txid);
}
setTimeout(() => { this.applyFragment(); }, 0);
},
@@ -303,6 +353,10 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
}
this.rbfTransaction = rbfTransaction;
this.cacheService.setTxCache([this.rbfTransaction]);
+ this.replaced = true;
+ if (rbfTransaction && !this.tx) {
+ this.fetchCachedTx$.next(this.txId);
+ }
});
this.queryParamsSubscription = this.route.queryParams.subscribe((params) => {
@@ -368,8 +422,10 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
this.waitingForTransaction = false;
this.isLoadingTx = true;
this.rbfTransaction = undefined;
+ this.replaced = false;
this.transactionTime = -1;
this.cpfpInfo = null;
+ this.rbfReplaces = [];
this.showCpfpDetails = false;
document.body.scrollTo(0, 0);
this.leaveTransaction();
@@ -435,6 +491,8 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
ngOnDestroy() {
this.subscription.unsubscribe();
this.fetchCpfpSubscription.unsubscribe();
+ this.fetchRbfSubscription.unsubscribe();
+ this.fetchCachedTxSubscription.unsubscribe();
this.txReplacedSubscription.unsubscribe();
this.blocksSubscription.unsubscribe();
this.queryParamsSubscription.unsubscribe();
diff --git a/frontend/src/app/services/api.service.ts b/frontend/src/app/services/api.service.ts
index f813959e3..6eff41f61 100644
--- a/frontend/src/app/services/api.service.ts
+++ b/frontend/src/app/services/api.service.ts
@@ -5,7 +5,7 @@ import { CpfpInfo, OptimizedMempoolStats, AddressInformation, LiquidPegs, ITrans
import { Observable } from 'rxjs';
import { StateService } from './state.service';
import { WebsocketResponse } from '../interfaces/websocket.interface';
-import { Outspend } from '../interfaces/electrs.interface';
+import { Outspend, Transaction } from '../interfaces/electrs.interface';
@Injectable({
providedIn: 'root'
@@ -119,6 +119,14 @@ export class ApiService {
return this.httpClient.get(this.apiBaseUrl + this.apiBasePath + '/api/v1/validate-address/' + address);
}
+ getRbfHistory$(txid: string): Observable {
+ return this.httpClient.get(this.apiBaseUrl + this.apiBasePath + '/api/v1/tx/' + txid + '/replaces');
+ }
+
+ getRbfCachedTx$(txid: string): Observable {
+ return this.httpClient.get(this.apiBaseUrl + this.apiBasePath + '/api/v1/tx/' + txid + '/cached');
+ }
+
listLiquidPegsMonth$(): Observable {
return this.httpClient.get(this.apiBaseUrl + this.apiBasePath + '/api/v1/liquid/pegs/month');
}
|