diff --git a/backend/src/index.ts b/backend/src/index.ts
index 74d348ecf..439506d2b 100644
--- a/backend/src/index.ts
+++ b/backend/src/index.ts
@@ -90,8 +90,12 @@ class Server {
client['want-stats'] = parsedMessage.data.indexOf('stats') > -1;
}
- if (parsedMessage && parsedMessage.txId && /^[a-fA-F0-9]{64}$/.test(parsedMessage.txId)) {
- client['txId'] = parsedMessage.txId;
+ if (parsedMessage && parsedMessage['track-tx']) {
+ if (/^[a-fA-F0-9]{64}$/.test(parsedMessage['track-tx'])) {
+ client['track-tx'] = parsedMessage['track-tx'];
+ } else {
+ client['track-tx'] = null;
+ }
}
if (parsedMessage.action === 'init') {
@@ -139,8 +143,8 @@ class Server {
return;
}
- if (client['txId'] && txIds.indexOf(client['txId']) > -1) {
- client['txId'] = null;
+ if (client['track-tx'] && txIds.indexOf(client['track-tx']) > -1) {
+ client['track-tx'] = null;
client.send(JSON.stringify({
'block': block,
'txConfirmed': true,
diff --git a/frontend/src/app/components/address/address.component.scss b/frontend/src/app/components/address/address.component.scss
index a42c44689..5e22a9236 100644
--- a/frontend/src/app/components/address/address.component.scss
+++ b/frontend/src/app/components/address/address.component.scss
@@ -5,6 +5,7 @@
.qr-wrapper {
background-color: #FFF;
padding: 10px;
+ padding-bottom: 5px;
display: inline-block;
margin-right: 25px;
}
\ No newline at end of file
diff --git a/frontend/src/app/components/block/block.component.html b/frontend/src/app/components/block/block.component.html
index 73e8fbd33..de34b56db 100644
--- a/frontend/src/app/components/block/block.component.html
+++ b/frontend/src/app/components/block/block.component.html
@@ -1,134 +1,136 @@
-
+
diff --git a/frontend/src/app/components/blockchain/blockchain.component.ts b/frontend/src/app/components/blockchain/blockchain.component.ts
index d29849272..f47953ff5 100644
--- a/frontend/src/app/components/blockchain/blockchain.component.ts
+++ b/frontend/src/app/components/blockchain/blockchain.component.ts
@@ -10,6 +10,7 @@ import { StateService } from 'src/app/services/state.service';
})
export class BlockchainComponent implements OnInit, OnDestroy {
@Input() position: 'middle' | 'top' = 'middle';
+ @Input() markHeight: number;
txTrackingSubscription: Subscription;
blocksSubscription: Subscription;
diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts
index 73c41e14d..cc0d083e5 100644
--- a/frontend/src/app/components/search-form/search-form.component.ts
+++ b/frontend/src/app/components/search-form/search-form.component.ts
@@ -15,6 +15,8 @@ export class SearchFormComponent implements OnInit {
searchBoxPlaceholderText = 'Transaction, address, block hash...';
regexAddress = /^([a-km-zA-HJ-NP-Z1-9]{26,35}|[a-km-zA-HJ-NP-Z1-9]{80}|[a-z]{2,5}1[ac-hj-np-z02-9]{8,87})$/;
+ regexBlockhash = /^[0]{8}[a-fA-F0-9]{56}$/;
+ regexTransaction = /^[a-fA-F0-9]{64}$/;
constructor(
private formBuilder: FormBuilder,
@@ -32,8 +34,12 @@ export class SearchFormComponent implements OnInit {
if (searchText) {
if (this.regexAddress.test(searchText)) {
this.router.navigate(['/address/', searchText]);
- } else {
+ } else if (this.regexBlockhash.test(searchText)) {
+ this.router.navigate(['/block/', searchText]);
+ } else if (this.regexTransaction.test(searchText)) {
this.router.navigate(['/tx/', searchText]);
+ } else {
+ return;
}
this.searchForm.setValue({
searchText: '',
diff --git a/frontend/src/app/components/transaction/transaction.component.html b/frontend/src/app/components/transaction/transaction.component.html
index f5f7518bc..4cbbfb1cc 100644
--- a/frontend/src/app/components/transaction/transaction.component.html
+++ b/frontend/src/app/components/transaction/transaction.component.html
@@ -1,10 +1,14 @@
-
+
-
+
-
Transaction
+
@@ -51,19 +55,14 @@
- Transaction |
-
- {{ txId | shortenString }}
-
- |
+ Status |
|
Fees |
- {{ tx.fee | number }} sats ({{ conversions.USD * tx.fee / 100000000 | currency:'USD':'symbol':'1.2-2' }}) |
- {{ tx.fee / (tx.weight / 4) | number : '1.2-2' }} sat/vB |
+ {{ tx.fee | number }} sats ({{ conversions.USD * tx.fee / 100000000 | currency:'USD':'symbol':'1.2-2' }}) {{ tx.fee / (tx.weight / 4) | number : '1.2-2' }} sat/vB |
diff --git a/frontend/src/app/components/transaction/transaction.component.scss b/frontend/src/app/components/transaction/transaction.component.scss
index 78fc9a8bb..0c333589d 100644
--- a/frontend/src/app/components/transaction/transaction.component.scss
+++ b/frontend/src/app/components/transaction/transaction.component.scss
@@ -10,3 +10,15 @@
width: 40px;
}
+
+.title-block {
+ color: #FFF;
+ padding-left: 10px;
+ padding-top: 13px;
+ padding-bottom: 3px;
+ border-top: 5px solid #FFF;
+}
+
+.title-block > h1 {
+ margin: 0;
+}
diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts
index 1b3d83326..08b0f2142 100644
--- a/frontend/src/app/components/transaction/transaction.component.ts
+++ b/frontend/src/app/components/transaction/transaction.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, OnDestroy } from '@angular/core';
import { ElectrsApiService } from '../../services/electrs-api.service';
import { ActivatedRoute, ParamMap } from '@angular/router';
import { switchMap } from 'rxjs/operators';
@@ -12,7 +12,7 @@ import { WebsocketService } from '../../services/websocket.service';
templateUrl: './transaction.component.html',
styleUrls: ['./transaction.component.scss']
})
-export class TransactionComponent implements OnInit {
+export class TransactionComponent implements OnInit, OnDestroy {
tx: Transaction;
txId: string;
isLoadingTx = true;
@@ -51,7 +51,7 @@ export class TransactionComponent implements OnInit {
window.scrollTo(0, 0);
if (!tx.status.confirmed) {
- this.websocketService.startTrackTx(tx.txid);
+ this.websocketService.startTrackTransaction(tx.txid);
}
},
(error) => {
@@ -75,4 +75,8 @@ export class TransactionComponent implements OnInit {
};
});
}
+
+ ngOnDestroy() {
+ this.websocketService.startTrackTransaction('stop');
+ }
}
diff --git a/frontend/src/app/interfaces/websocket.interface.ts b/frontend/src/app/interfaces/websocket.interface.ts
index 6d69e1315..852ba6bf9 100644
--- a/frontend/src/app/interfaces/websocket.interface.ts
+++ b/frontend/src/app/interfaces/websocket.interface.ts
@@ -4,13 +4,14 @@ export interface WebsocketResponse {
block?: Block;
blocks?: Block[];
conversions?: any;
- txId?: string;
txConfirmed?: boolean;
historicalDate?: string;
mempoolInfo?: MempoolInfo;
vBytesPerSecond?: number;
action?: string;
data?: string[];
+ 'track-tx'?: string;
+ 'track-address'?: string;
}
export interface MempoolBlock {
diff --git a/frontend/src/app/services/websocket.service.ts b/frontend/src/app/services/websocket.service.ts
index fa4373ddf..47d2405d3 100644
--- a/frontend/src/app/services/websocket.service.ts
+++ b/frontend/src/app/services/websocket.service.ts
@@ -16,6 +16,7 @@ export class WebsocketService {
private goneOffline = false;
private lastWant: string[] | null = null;
private trackingTxId: string | null = null;
+ private trackingAddress: string | null = null;
constructor(
private stateService: StateService,
@@ -86,7 +87,10 @@ export class WebsocketService {
this.want(this.lastWant);
}
if (this.trackingTxId) {
- this.startTrackTx(this.trackingTxId);
+ this.startTrackTransaction(this.trackingTxId);
+ }
+ if (this.trackingAddress) {
+ this.startTrackTransaction(this.trackingAddress);
}
this.stateService.isOffline$.next(false);
}
@@ -99,11 +103,16 @@ export class WebsocketService {
});
}
- startTrackTx(txId: string) {
- this.websocketSubject.next({ txId });
+ startTrackTransaction(txId: string) {
+ this.websocketSubject.next({ 'track-tx': txId });
this.trackingTxId = txId;
}
+ startTrackAddress(address: string) {
+ this.websocketSubject.next({ 'track-address': address });
+ this.trackingAddress = address;
+ }
+
fetchStatistics(historicalDate: string) {
this.websocketSubject.next({ historicalDate });
}