diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index 7ff1e770b..5b3680f3d 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -3,7 +3,7 @@ import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { ReactiveFormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-import { NgbButtonsModule, NgbTooltipModule, NgbPaginationModule, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgbButtonsModule, NgbPaginationModule, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { AppRoutingModule } from './app-routing.module';
@@ -79,7 +79,6 @@ import { SharedModule } from './shared/shared.module';
ReactiveFormsModule,
BrowserAnimationsModule,
NgbButtonsModule,
- NgbTooltipModule,
NgbPaginationModule,
NgbDropdownModule,
InfiniteScrollModule,
diff --git a/frontend/src/app/components/transaction/transaction.component.html b/frontend/src/app/components/transaction/transaction.component.html
index 60d4f1954..79128f8ea 100644
--- a/frontend/src/app/components/transaction/transaction.component.html
+++ b/frontend/src/app/components/transaction/transaction.component.html
@@ -51,7 +51,12 @@
After |
-
+
+ Features |
+
+
+ |
+
@@ -68,9 +73,7 @@
{{ tx.fee / (tx.weight / 4) | number : '1.1-1' }} sat/vB
- Optimal
- Overpaid {{ overpaidTimes }}x
- Overpaid {{ overpaidTimes }}x
+
|
@@ -124,7 +127,12 @@
-
+
+ Features |
+
+
+ |
+
@@ -260,15 +268,3 @@
-
-
-
- Features |
-
- SegWit
- SegWit
- SegWit
- RBF
- |
-
-
\ 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 495685831..d71f87031 100644
--- a/frontend/src/app/components/transaction/transaction.component.ts
+++ b/frontend/src/app/components/transaction/transaction.component.ts
@@ -9,7 +9,6 @@ import { WebsocketService } from '../../services/websocket.service';
import { AudioService } from 'src/app/services/audio.service';
import { ApiService } from 'src/app/services/api.service';
import { SeoService } from 'src/app/services/seo.service';
-import { calcSegwitFeeGains } from 'src/app/bitcoin.utils';
import { BisqTransaction } from 'src/app/bisq/bisq.interfaces';
@Component({
@@ -21,9 +20,6 @@ export class TransactionComponent implements OnInit, OnDestroy {
network = '';
tx: Transaction;
txId: string;
- feeRating: number;
- overpaidTimes: number;
- medianFeeNeeded: number;
txInBlockIndex: number;
isLoadingTx = true;
error: any = undefined;
@@ -31,14 +27,7 @@ export class TransactionComponent implements OnInit, OnDestroy {
latestBlock: Block;
transactionTime = -1;
subscription: Subscription;
- segwitGains = {
- realizedGains: 0,
- potentialBech32Gains: 0,
- potentialP2shGains: 0,
- };
- isRbfTransaction: boolean;
rbfTransaction: undefined | Transaction;
- bisqTx: BisqTransaction;
constructor(
private route: ActivatedRoute,
@@ -89,8 +78,6 @@ export class TransactionComponent implements OnInit, OnDestroy {
this.error = undefined;
this.waitingForTransaction = false;
this.setMempoolBlocksSubscription();
- this.segwitGains = calcSegwitFeeGains(tx);
- this.isRbfTransaction = tx.vin.some((v) => v.sequence < 0xfffffffe);
if (!tx.status.confirmed) {
this.websocketService.startTrackTransaction(tx.txid);
@@ -100,8 +87,6 @@ export class TransactionComponent implements OnInit, OnDestroy {
} else {
this.getTransactionTime();
}
- } else {
- this.findBlockAndSetFeeRating();
}
if (this.tx.status.confirmed) {
this.stateService.markBlock$.next({ blockHeight: tx.status.block_height });
@@ -127,7 +112,6 @@ export class TransactionComponent implements OnInit, OnDestroy {
};
this.stateService.markBlock$.next({ blockHeight: block.height });
this.audioService.playSound('magic');
- this.findBlockAndSetFeeRating();
}
});
@@ -171,42 +155,12 @@ export class TransactionComponent implements OnInit, OnDestroy {
});
}
- findBlockAndSetFeeRating() {
- this.stateService.blocks$
- .pipe(
- filter(([block]) => block.height === this.tx.status.block_height),
- take(1)
- )
- .subscribe(([block]) => {
- const feePervByte = this.tx.fee / (this.tx.weight / 4);
- this.medianFeeNeeded = Math.round(block.feeRange[Math.round(block.feeRange.length * 0.5)]);
-
- // Block not filled
- if (block.weight < 4000000 * 0.95) {
- this.medianFeeNeeded = 1;
- }
-
- this.overpaidTimes = Math.round(feePervByte / this.medianFeeNeeded);
-
- if (feePervByte <= this.medianFeeNeeded || this.overpaidTimes < 2) {
- this.feeRating = 1;
- } else {
- this.feeRating = 2;
- if (this.overpaidTimes > 10) {
- this.feeRating = 3;
- }
- }
- });
- }
-
resetTransaction() {
this.error = undefined;
this.tx = null;
- this.feeRating = undefined;
this.waitingForTransaction = false;
this.isLoadingTx = true;
this.rbfTransaction = undefined;
- this.bisqTx = undefined;
this.transactionTime = -1;
document.body.scrollTo(0, 0);
this.leaveTransaction();
diff --git a/frontend/src/app/components/tx-features/tx-features.component.html b/frontend/src/app/components/tx-features/tx-features.component.html
new file mode 100644
index 000000000..20513614d
--- /dev/null
+++ b/frontend/src/app/components/tx-features/tx-features.component.html
@@ -0,0 +1,4 @@
+SegWit
+SegWit
+SegWit
+RBF
diff --git a/frontend/src/app/components/tx-features/tx-features.component.scss b/frontend/src/app/components/tx-features/tx-features.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/frontend/src/app/components/tx-features/tx-features.component.ts b/frontend/src/app/components/tx-features/tx-features.component.ts
new file mode 100644
index 000000000..0c3711499
--- /dev/null
+++ b/frontend/src/app/components/tx-features/tx-features.component.ts
@@ -0,0 +1,27 @@
+import { Component, ChangeDetectionStrategy, OnChanges, Input } from '@angular/core';
+import { calcSegwitFeeGains } from 'src/app/bitcoin.utils';
+import { Transaction } from 'src/app/interfaces/electrs.interface';
+
+@Component({
+ selector: 'app-tx-features',
+ templateUrl: './tx-features.component.html',
+ styleUrls: ['./tx-features.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class TxFeaturesComponent implements OnChanges {
+ @Input() tx: Transaction;
+
+ segwitGains = {
+ realizedGains: 0,
+ potentialBech32Gains: 0,
+ potentialP2shGains: 0,
+ };
+ isRbfTransaction: boolean;
+
+ constructor() { }
+
+ ngOnChanges() {
+ this.segwitGains = calcSegwitFeeGains(this.tx);
+ this.isRbfTransaction = this.tx.vin.some((v) => v.sequence < 0xfffffffe);
+ }
+}
diff --git a/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.html b/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.html
new file mode 100644
index 000000000..bd2a4221f
--- /dev/null
+++ b/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.html
@@ -0,0 +1,3 @@
+Optimal
+Overpaid {{ overpaidTimes }}x
+Overpaid {{ overpaidTimes }}x
\ No newline at end of file
diff --git a/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.scss b/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.ts b/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.ts
new file mode 100644
index 000000000..32ca9b258
--- /dev/null
+++ b/frontend/src/app/components/tx-fee-rating/tx-fee-rating.component.ts
@@ -0,0 +1,64 @@
+import { Component, ChangeDetectionStrategy, OnChanges, Input, OnInit, ChangeDetectorRef } from '@angular/core';
+import { Transaction, Block } from 'src/app/interfaces/electrs.interface';
+import { StateService } from 'src/app/services/state.service';
+
+@Component({
+ selector: 'app-tx-fee-rating',
+ templateUrl: './tx-fee-rating.component.html',
+ styleUrls: ['./tx-fee-rating.component.scss'],
+})
+export class TxFeeRatingComponent implements OnInit, OnChanges {
+ @Input() tx: Transaction;
+
+ medianFeeNeeded: number;
+ overpaidTimes: number;
+ feeRating: number;
+
+ blocks: Block[] = [];
+
+ constructor(
+ private stateService: StateService,
+ ) { }
+
+ ngOnInit() {
+ this.stateService.blocks$.subscribe(([block]) => {
+ this.blocks.push(block);
+ if (this.tx.status.confirmed && this.tx.status.block_height === block.height) {
+ this.calculateRatings(block);
+ }
+ });
+ }
+
+ ngOnChanges() {
+ this.feeRating = undefined;
+ if (!this.tx.status.confirmed) {
+ return;
+ }
+
+ const foundBlock = this.blocks.find((b) => b.height === this.tx.status.block_height);
+ if (foundBlock) {
+ this.calculateRatings(foundBlock);
+ }
+ }
+
+ calculateRatings(block: Block) {
+ const feePervByte = this.tx.fee / (this.tx.weight / 4);
+ this.medianFeeNeeded = Math.round(block.feeRange[Math.round(block.feeRange.length * 0.5)]);
+
+ // Block not filled
+ if (block.weight < 4000000 * 0.95) {
+ this.medianFeeNeeded = 1;
+ }
+
+ this.overpaidTimes = Math.round(feePervByte / this.medianFeeNeeded);
+
+ if (feePervByte <= this.medianFeeNeeded || this.overpaidTimes < 2) {
+ this.feeRating = 1;
+ } else {
+ this.feeRating = 2;
+ if (this.overpaidTimes > 10) {
+ this.feeRating = 3;
+ }
+ }
+ }
+}
diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts
index 274f898c7..9c27e80dd 100644
--- a/frontend/src/app/shared/shared.module.ts
+++ b/frontend/src/app/shared/shared.module.ts
@@ -12,10 +12,18 @@ import { TimeSinceComponent } from '../components/time-since/time-since.componen
import { ClipboardComponent } from '../components/clipboard/clipboard.component';
import { QrcodeComponent } from '../components/qrcode/qrcode.component';
import { FiatComponent } from '../fiat/fiat.component';
-import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgbNavModule, NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap';
+import { TxFeaturesComponent } from '../components/tx-features/tx-features.component';
+import { TxFeeRatingComponent } from '../components/tx-fee-rating/tx-fee-rating.component';
@NgModule({
declarations: [
+ ClipboardComponent,
+ TimeSinceComponent,
+ QrcodeComponent,
+ FiatComponent,
+ TxFeaturesComponent,
+ TxFeeRatingComponent,
ScriptpubkeyTypePipe,
RelativeUrlPipe,
Hex2asciiPipe,
@@ -24,14 +32,11 @@ import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
WuBytesPipe,
CeilPipe,
ShortenStringPipe,
- ClipboardComponent,
- TimeSinceComponent,
- QrcodeComponent,
- FiatComponent,
],
imports: [
CommonModule,
NgbNavModule,
+ NgbTooltipModule,
],
providers: [
VbytesPipe,
@@ -39,6 +44,13 @@ import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
exports: [
NgbNavModule,
CommonModule,
+ NgbTooltipModule,
+ TimeSinceComponent,
+ ClipboardComponent,
+ QrcodeComponent,
+ FiatComponent,
+ TxFeaturesComponent,
+ TxFeeRatingComponent,
ScriptpubkeyTypePipe,
RelativeUrlPipe,
Hex2asciiPipe,
@@ -47,10 +59,6 @@ import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
WuBytesPipe,
CeilPipe,
ShortenStringPipe,
- TimeSinceComponent,
- ClipboardComponent,
- QrcodeComponent,
- FiatComponent,
]
})
export class SharedModule {}