@@ -39,19 +43,21 @@
-
-
-
-
- This transaction is stored locally in your browser. Broadcast it to add it to the mempool.
-
-
- Redirecting to transaction page...
-
-
-
-
-
+ @if (!isCoinbase) {
+
+
+
+
+ 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.ts b/frontend/src/app/components/transaction/transaction-raw.component.ts
index 2e4dd4868..a4d20b040 100644
--- a/frontend/src/app/components/transaction/transaction-raw.component.ts
+++ b/frontend/src/app/components/transaction/transaction-raw.component.ts
@@ -36,7 +36,9 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
isLoadingBroadcast: boolean;
errorBroadcast: string;
successBroadcast: boolean;
+ isCoinbase: boolean;
broadcastSubscription: Subscription;
+ fragmentSubscription: Subscription;
isMobile: boolean;
@ViewChild('graphContainer')
@@ -77,6 +79,21 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.pushTxForm = this.formBuilder.group({
txRaw: ['', Validators.required],
});
+
+ this.fragmentSubscription = this.route.fragment.subscribe((fragment) => {
+ if (fragment) {
+ const params = new URLSearchParams(fragment);
+ const hex = params.get('hex');
+ if (hex) {
+ this.pushTxForm.get('txRaw').setValue(hex);
+ this.decodeTransaction();
+ }
+ const offline = params.get('offline');
+ if (offline) {
+ this.offlineMode = offline === 'true';
+ }
+ }
+ });
}
async decodeTransaction(): Promise {
@@ -184,6 +201,14 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.transaction = tx;
this.rawHexTransaction = hex;
+ this.isCoinbase = this.transaction.vin[0].is_coinbase;
+
+ // Update URL fragment with hex data
+ this.router.navigate([], {
+ fragment: this.getCurrentFragments(),
+ replaceUrl: true
+ });
+
this.transaction.flags = getTransactionFlags(this.transaction, this.cpfpInfo, null, null, this.stateService.network);
this.filters = this.transaction.flags ? toFilters(this.transaction.flags).filter(f => f.txPage) : [];
if (this.transaction.sigops >= 0) {
@@ -256,6 +281,7 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.filters = [];
this.hasPrevouts = false;
this.missingPrevouts = [];
+ this.offlineMode = false;
this.stateService.markBlock$.next({});
this.mempoolBlocksSubscription?.unsubscribe();
this.broadcastSubscription?.unsubscribe();
@@ -264,6 +290,10 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
resetForm() {
this.resetState();
this.pushTxForm.get('txRaw').setValue('');
+ this.router.navigate([], {
+ fragment: '',
+ replaceUrl: true
+ });
}
@HostListener('window:resize', ['$event'])
@@ -306,8 +336,24 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.graphHeight = Math.min(360, this.maxInOut * 80);
}
+ getCurrentFragments() {
+ // build a fragment param string from current state
+ const params = new URLSearchParams();
+ if (this.offlineMode) {
+ params.set('offline', 'true');
+ }
+ if (this.rawHexTransaction) {
+ params.set('hex', this.rawHexTransaction);
+ }
+ return params.toString();
+ }
+
onOfflineModeChange(e): void {
this.offlineMode = !e.target.checked;
+ this.router.navigate([], {
+ fragment: this.getCurrentFragments(),
+ replaceUrl: true
+ });
}
ngOnDestroy(): void {
@@ -315,6 +361,7 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
this.flowPrefSubscription?.unsubscribe();
this.stateService.markBlock$.next({});
this.broadcastSubscription?.unsubscribe();
+ this.fragmentSubscription?.unsubscribe();
}
}