diff --git a/frontend/src/app/components/transaction/transaction-raw.component.html b/frontend/src/app/components/transaction/transaction-raw.component.html
index 3bd8ee6d2..35701889b 100644
--- a/frontend/src/app/components/transaction/transaction-raw.component.html
+++ b/frontend/src/app/components/transaction/transaction-raw.component.html
@@ -30,7 +30,6 @@
+
-
+
This transaction is stored locally in your browser. Broadcast it to add it to the mempool.
+
+ Redirecting to transaction page...
+
-
+
+
@if (!hasPrevouts) {
diff --git a/frontend/src/app/components/transaction/transaction-raw.component.scss b/frontend/src/app/components/transaction/transaction-raw.component.scss
index 5bbe5601e..a4b386cee 100644
--- a/frontend/src/app/components/transaction/transaction-raw.component.scss
+++ b/frontend/src/app/components/transaction/transaction-raw.component.scss
@@ -191,4 +191,12 @@
.no-cursor {
cursor: default !important;
pointer-events: none;
+}
+
+.btn-broadcast {
+ margin-left: 5px;
+ @media (max-width: 567px) {
+ margin-left: 0;
+ margin-top: 5px;
+ }
}
\ No newline at end of file
diff --git a/frontend/src/app/components/transaction/transaction-raw.component.ts b/frontend/src/app/components/transaction/transaction-raw.component.ts
index 5ce170e12..2e4dd4868 100644
--- a/frontend/src/app/components/transaction/transaction-raw.component.ts
+++ b/frontend/src/app/components/transaction/transaction-raw.component.ts
@@ -3,7 +3,7 @@ import { Transaction, Vout } from '@interfaces/electrs.interface';
import { StateService } from '../../services/state.service';
import { Filter, toFilters } from '../../shared/filters.utils';
import { decodeRawTransaction, getTransactionFlags, addInnerScriptsToVin, countSigops } from '../../shared/transaction.utils';
-import { firstValueFrom, Subscription } from 'rxjs';
+import { catchError, firstValueFrom, Subscription, switchMap, tap, throwError, timer } from 'rxjs';
import { WebsocketService } from '../../services/websocket.service';
import { ActivatedRoute, Router } from '@angular/router';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
@@ -36,6 +36,7 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
isLoadingBroadcast: boolean;
errorBroadcast: string;
successBroadcast: boolean;
+ broadcastSubscription: Subscription;
isMobile: boolean;
@ViewChild('graphContainer')
@@ -82,7 +83,7 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.resetState();
this.isLoading = true;
try {
- const { tx, hex } = decodeRawTransaction(this.pushTxForm.get('txRaw').value, this.stateService.network);
+ const { tx, hex } = decodeRawTransaction(this.pushTxForm.get('txRaw').value.trim(), this.stateService.network);
await this.fetchPrevouts(tx);
await this.fetchCpfpInfo(tx);
this.processTransaction(tx, hex);
@@ -207,18 +208,22 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
});
}
- async postTx(): Promise
{
+ postTx(): void {
this.isLoadingBroadcast = true;
this.errorBroadcast = null;
- return new Promise((resolve, reject) => {
- this.apiService.postTransaction$(this.rawHexTransaction)
- .subscribe((result) => {
+
+ this.broadcastSubscription = this.apiService.postTransaction$(this.rawHexTransaction).pipe(
+ tap((txid: string) => {
this.isLoadingBroadcast = false;
this.successBroadcast = true;
- this.transaction.txid = result;
- resolve(result);
- },
- (error) => {
+ this.transaction.txid = txid;
+ }),
+ switchMap((txid: string) =>
+ timer(2000).pipe(
+ tap(() => this.router.navigate([this.relativeUrlPipe.transform('/tx/' + txid)])),
+ )
+ ),
+ catchError((error) => {
if (typeof error.error === 'string') {
const matchText = error.error.replace(/\\/g, '').match('"message":"(.*?)"');
this.errorBroadcast = 'Failed to broadcast transaction, reason: ' + (matchText && matchText[1] || error.error);
@@ -226,9 +231,9 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.errorBroadcast = 'Failed to broadcast transaction, reason: ' + error.message;
}
this.isLoadingBroadcast = false;
- reject(this.error);
- });
- });
+ return throwError(() => error);
+ })
+ ).subscribe();
}
resetState() {
@@ -253,6 +258,7 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.missingPrevouts = [];
this.stateService.markBlock$.next({});
this.mempoolBlocksSubscription?.unsubscribe();
+ this.broadcastSubscription?.unsubscribe();
}
resetForm() {
@@ -308,6 +314,7 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.mempoolBlocksSubscription?.unsubscribe();
this.flowPrefSubscription?.unsubscribe();
this.stateService.markBlock$.next({});
+ this.broadcastSubscription?.unsubscribe();
}
}