Bisq stats page.
BSQ prices.
This commit is contained in:
parent
b7376fbd8d
commit
ca0cf23d66
@ -1,6 +1,8 @@
|
|||||||
const config = require('../../mempool-config.json');
|
const config = require('../../mempool-config.json');
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { BisqBlocks, BisqBlock, BisqTransaction, BisqStats } from '../interfaces';
|
import * as request from 'request';
|
||||||
|
import { BisqBlocks, BisqBlock, BisqTransaction, BisqStats, BisqTrade } from '../interfaces';
|
||||||
|
import { Common } from './common';
|
||||||
|
|
||||||
class Bisq {
|
class Bisq {
|
||||||
private blocks: BisqBlock[] = [];
|
private blocks: BisqBlock[] = [];
|
||||||
@ -15,6 +17,8 @@ class Bisq {
|
|||||||
unspent_txos: 0,
|
unspent_txos: 0,
|
||||||
spent_txos: 0,
|
spent_txos: 0,
|
||||||
};
|
};
|
||||||
|
private price: number = 0;
|
||||||
|
private priceUpdateCallbackFunction: ((price: number) => void) | undefined;
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
@ -22,7 +26,7 @@ class Bisq {
|
|||||||
this.loadBisqDumpFile();
|
this.loadBisqDumpFile();
|
||||||
|
|
||||||
let fsWait: NodeJS.Timeout | null = null;
|
let fsWait: NodeJS.Timeout | null = null;
|
||||||
fs.watch(config.BSQ_BLOCKS_DATA_PATH, (event, filename) => {
|
fs.watch(config.BSQ_BLOCKS_DATA_PATH, (event: string, filename: string) => {
|
||||||
if (filename) {
|
if (filename) {
|
||||||
if (fsWait) {
|
if (fsWait) {
|
||||||
clearTimeout(fsWait);
|
clearTimeout(fsWait);
|
||||||
@ -33,6 +37,9 @@ class Bisq {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setInterval(this.updatePrice.bind(this), 1000 * 60 * 60);
|
||||||
|
this.updatePrice();
|
||||||
}
|
}
|
||||||
|
|
||||||
getTransaction(txId: string): BisqTransaction | undefined {
|
getTransaction(txId: string): BisqTransaction | undefined {
|
||||||
@ -59,6 +66,26 @@ class Bisq {
|
|||||||
return this.stats;
|
return this.stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setPriceCallbackFunction(fn: (price: number) => void) {
|
||||||
|
this.priceUpdateCallbackFunction = fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private updatePrice() {
|
||||||
|
request('https://markets.bisq.network/api/trades/?market=bsq_btc', { json: true }, (err, res, trades: BisqTrade[]) => {
|
||||||
|
if (err) { return console.log(err); }
|
||||||
|
|
||||||
|
const prices: number[] = [];
|
||||||
|
trades.forEach((trade) => {
|
||||||
|
prices.push(parseFloat(trade.price) * 100000000);
|
||||||
|
});
|
||||||
|
prices.sort((a, b) => a - b);
|
||||||
|
this.price = Common.median(prices);
|
||||||
|
if (this.priceUpdateCallbackFunction) {
|
||||||
|
this.priceUpdateCallbackFunction(this.price);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async loadBisqDumpFile(): Promise<void> {
|
private async loadBisqDumpFile(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const data = await this.loadData();
|
const data = await this.loadData();
|
||||||
|
@ -12,6 +12,7 @@ import { Common } from './common';
|
|||||||
class WebsocketHandler {
|
class WebsocketHandler {
|
||||||
private wss: WebSocket.Server | undefined;
|
private wss: WebSocket.Server | undefined;
|
||||||
private nativeAssetId = '6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d';
|
private nativeAssetId = '6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d';
|
||||||
|
private extraInitProperties = {};
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
@ -19,6 +20,10 @@ class WebsocketHandler {
|
|||||||
this.wss = wss;
|
this.wss = wss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setExtraInitProperties(property: string, value: any) {
|
||||||
|
this.extraInitProperties[property] = value;
|
||||||
|
}
|
||||||
|
|
||||||
setupConnectionHandling() {
|
setupConnectionHandling() {
|
||||||
if (!this.wss) {
|
if (!this.wss) {
|
||||||
throw new Error('WebSocket.Server is not set');
|
throw new Error('WebSocket.Server is not set');
|
||||||
@ -84,6 +89,7 @@ class WebsocketHandler {
|
|||||||
'mempool-blocks': mempoolBlocks.getMempoolBlocks(),
|
'mempool-blocks': mempoolBlocks.getMempoolBlocks(),
|
||||||
'git-commit': backendInfo.gitCommitHash,
|
'git-commit': backendInfo.gitCommitHash,
|
||||||
'hostname': backendInfo.hostname,
|
'hostname': backendInfo.hostname,
|
||||||
|
...this.extraInitProperties
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ class Server {
|
|||||||
|
|
||||||
if (config.BISQ_ENABLED) {
|
if (config.BISQ_ENABLED) {
|
||||||
bisq.startBisqService();
|
bisq.startBisqService();
|
||||||
|
bisq.setPriceCallbackFunction((price) => websocketHandler.setExtraInitProperties('bsq-price', price));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.server.listen(config.HTTP_PORT, () => {
|
this.server.listen(config.HTTP_PORT, () => {
|
||||||
|
@ -312,3 +312,13 @@ interface SpentInfo {
|
|||||||
inputIndex: number;
|
inputIndex: number;
|
||||||
txId: string;
|
txId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface BisqTrade {
|
||||||
|
direction: string;
|
||||||
|
price: string;
|
||||||
|
amount: string;
|
||||||
|
volume: string;
|
||||||
|
payment_method: string;
|
||||||
|
trade_id: string;
|
||||||
|
trade_date: number;
|
||||||
|
}
|
||||||
|
@ -31,7 +31,6 @@ import { BlockchainBlocksComponent } from './components/blockchain-blocks/blockc
|
|||||||
import { BlockchainComponent } from './components/blockchain/blockchain.component';
|
import { BlockchainComponent } from './components/blockchain/blockchain.component';
|
||||||
import { FooterComponent } from './components/footer/footer.component';
|
import { FooterComponent } from './components/footer/footer.component';
|
||||||
import { AudioService } from './services/audio.service';
|
import { AudioService } from './services/audio.service';
|
||||||
import { FiatComponent } from './fiat/fiat.component';
|
|
||||||
import { MempoolBlockComponent } from './components/mempool-block/mempool-block.component';
|
import { MempoolBlockComponent } from './components/mempool-block/mempool-block.component';
|
||||||
import { FeeDistributionGraphComponent } from './components/fee-distribution-graph/fee-distribution-graph.component';
|
import { FeeDistributionGraphComponent } from './components/fee-distribution-graph/fee-distribution-graph.component';
|
||||||
import { TimespanComponent } from './components/timespan/timespan.component';
|
import { TimespanComponent } from './components/timespan/timespan.component';
|
||||||
@ -65,7 +64,6 @@ import { SharedModule } from './shared/shared.module';
|
|||||||
MempoolBlocksComponent,
|
MempoolBlocksComponent,
|
||||||
ChartistComponent,
|
ChartistComponent,
|
||||||
FooterComponent,
|
FooterComponent,
|
||||||
FiatComponent,
|
|
||||||
MempoolBlockComponent,
|
MempoolBlockComponent,
|
||||||
FeeDistributionGraphComponent,
|
FeeDistributionGraphComponent,
|
||||||
MempoolGraphComponent,
|
MempoolGraphComponent,
|
||||||
|
@ -18,15 +18,15 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Total received</td>
|
<td>Total received</td>
|
||||||
<td>{{ totalReceived / 100 }} BSQ</td>
|
<td>{{ totalReceived / 100 | number: '1.2-2' }} BSQ</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Total sent</td>
|
<td>Total sent</td>
|
||||||
<td>{{ totalSent / 100 }} BSQ</td>
|
<td>{{ totalSent / 100 | number: '1.2-2' }} BSQ</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Final balance</td>
|
<td>Final balance</td>
|
||||||
<td>{{ (totalReceived - totalSent) / 100 }} BSQ</td>
|
<td>{{ (totalReceived - totalSent) / 100 | number: '1.2-2' }} BSQ</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -58,7 +58,7 @@
|
|||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-bisq-transfers [tx]="tx"></app-bisq-transfers>
|
<app-bisq-transfers [tx]="tx" [showConfirmations]="true"></app-bisq-transfers>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-bisq-transfers [tx]="tx"></app-bisq-transfers>
|
<app-bisq-transfers [tx]="tx" [showConfirmations]="true"></app-bisq-transfers>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@ -4,47 +4,52 @@
|
|||||||
|
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
|
||||||
<table class="table table-borderless table-striped">
|
<div class="row">
|
||||||
<thead>
|
<div class="col-sm">
|
||||||
<th>Property</th>
|
<table class="table table-borderless table-striped">
|
||||||
<th>Value</th>
|
<thead>
|
||||||
</thead>
|
<th>Property</th>
|
||||||
<tbody *ngIf="!isLoading; else loadingTemplate">
|
<th>Value</th>
|
||||||
<tr>
|
</thead>
|
||||||
<td class="td-width">Existing amount</td>
|
<tbody *ngIf="!isLoading; else loadingTemplate">
|
||||||
<td>{{ (stats.minted - stats.burnt) / 100 | number: '1.2-2' }} BSQ</td>
|
<tr>
|
||||||
</tr>
|
<td class="td-width">Existing amount</td>
|
||||||
<tr>
|
<td>{{ (stats.minted - stats.burnt) / 100 | number: '1.2-2' }} BSQ</td>
|
||||||
<td>Minted amount</td>
|
</tr>
|
||||||
<td>{{ stats.minted | number: '1.2-2' }} BSQ</td>
|
<tr>
|
||||||
</tr>
|
<td>Minted amount</td>
|
||||||
<tr>
|
<td>{{ stats.minted | number: '1.2-2' }} BSQ</td>
|
||||||
<td>Burnt amount</td>
|
</tr>
|
||||||
<td>{{ stats.burnt | number: '1.2-2' }} BSQ</td>
|
<tr>
|
||||||
</tr>
|
<td>Burnt amount</td>
|
||||||
<tr>
|
<td>{{ stats.burnt | number: '1.2-2' }} BSQ</td>
|
||||||
<td>Addresses</td>
|
</tr>
|
||||||
<td>{{ stats.addresses | number }}</td>
|
<tr>
|
||||||
</tr>
|
<td>Addresses</td>
|
||||||
<tr>
|
<td>{{ stats.addresses | number }}</td>
|
||||||
<td>Unspent TXOs</td>
|
</tr>
|
||||||
<td>{{ stats.unspent_txos | number }}</td>
|
<tr>
|
||||||
</tr>
|
<td>Unspent TXOs</td>
|
||||||
<tr>
|
<td>{{ stats.unspent_txos | number }}</td>
|
||||||
<td>Spent TXOs</td>
|
</tr>
|
||||||
<td>{{ stats.spent_txos | number }}</td>
|
<tr>
|
||||||
</tr>
|
<td>Spent TXOs</td>
|
||||||
<tr>
|
<td>{{ stats.spent_txos | number }}</td>
|
||||||
<td>Price</td>
|
</tr>
|
||||||
<td></td>
|
<tr>
|
||||||
</tr>
|
<td>Price</td>
|
||||||
<tr>
|
<td><app-fiat [value]="price"></app-fiat></td>
|
||||||
<td>Market cap</td>
|
</tr>
|
||||||
<td></td>
|
<tr>
|
||||||
</tr>
|
<td>Market cap</td>
|
||||||
</tbody>
|
<td><app-fiat [value]="price * (stats.minted - stats.burnt) / 100 "></app-fiat></td>
|
||||||
</table>
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-sm"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-template #loadingTemplate>
|
<ng-template #loadingTemplate>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
.td-width {
|
.td-width {
|
||||||
width: 300px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 767.98px) {
|
@media (max-width: 767.98px) {
|
||||||
@ -7,7 +7,3 @@
|
|||||||
width: 175px;
|
width: 175px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.skeleton-loader {
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
import { BisqApiService } from '../bisq-api.service';
|
import { BisqApiService } from '../bisq-api.service';
|
||||||
import { BisqStats } from '../bisq.interfaces';
|
import { BisqStats } from '../bisq.interfaces';
|
||||||
import { SeoService } from 'src/app/services/seo.service';
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
|
import { StateService } from 'src/app/services/state.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bisq-stats',
|
selector: 'app-bisq-stats',
|
||||||
@ -11,15 +12,22 @@ import { SeoService } from 'src/app/services/seo.service';
|
|||||||
export class BisqStatsComponent implements OnInit {
|
export class BisqStatsComponent implements OnInit {
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
stats: BisqStats;
|
stats: BisqStats;
|
||||||
|
price: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private bisqApiService: BisqApiService,
|
private bisqApiService: BisqApiService,
|
||||||
private seoService: SeoService,
|
private seoService: SeoService,
|
||||||
|
private stateService: StateService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit() {
|
||||||
this.seoService.setTitle('BSQ Statistics', false);
|
this.seoService.setTitle('BSQ Statistics', false);
|
||||||
|
|
||||||
|
this.stateService.bsqPrice$
|
||||||
|
.subscribe((bsqPrice) => {
|
||||||
|
this.price = bsqPrice;
|
||||||
|
});
|
||||||
|
|
||||||
this.bisqApiService.getStats$()
|
this.bisqApiService.getStats$()
|
||||||
.subscribe((stats) => {
|
.subscribe((stats) => {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="td-width">Fee burnt</td>
|
<td class="td-width">Fee burnt</td>
|
||||||
<td>
|
<td>
|
||||||
{{ bisqTx.burntFee / 100 | number: '1.2-2' }} BSQ
|
{{ bisqTx.burntFee / 100 | number: '1.2-2' }} BSQ (<app-bsq-amount [bsq]="bisqTx.burntFee" [forceFiat]="true" [green]="true"></app-bsq-amount>)
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -17,6 +17,7 @@ export class BisqTransactionComponent implements OnInit, OnDestroy {
|
|||||||
bisqTx: BisqTransaction;
|
bisqTx: BisqTransaction;
|
||||||
latestBlock$: Observable<Block>;
|
latestBlock$: Observable<Block>;
|
||||||
txId: string;
|
txId: string;
|
||||||
|
price: number;
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
subscription: Subscription;
|
subscription: Subscription;
|
||||||
|
|
||||||
@ -46,6 +47,11 @@ export class BisqTransactionComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.latestBlock$ = this.stateService.blocks$.pipe(map((([block]) => block)));
|
this.latestBlock$ = this.stateService.blocks$.pipe(map((([block]) => block)));
|
||||||
|
|
||||||
|
this.stateService.bsqPrice$
|
||||||
|
.subscribe((bsqPrice) => {
|
||||||
|
this.price = bsqPrice;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right nowrap">
|
<td class="text-right nowrap">
|
||||||
{{ input.bsqAmount / 100 | number: '1.2-2' }} BSQ
|
<app-bsq-amount [bsq]="input.bsqAmount"></app-bsq-amount>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -42,7 +42,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right nowrap">
|
<td class="text-right nowrap">
|
||||||
{{ output.bsqAmount / 100 | number: '1.2-2' }} BSQ
|
<app-bsq-amount [bsq]="output.bsqAmount"></app-bsq-amount>
|
||||||
</td>
|
</td>
|
||||||
<td class="pl-1 arrow-td">
|
<td class="pl-1 arrow-td">
|
||||||
<i *ngIf="!output.spentInfo; else spent" class="arrow green"></i>
|
<i *ngIf="!output.spentInfo; else spent" class="arrow green"></i>
|
||||||
@ -57,4 +57,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="float-left mt-2-5" *ngIf="showConfirmations && tx.burntFee">
|
||||||
|
Fee: {{ tx.burntFee / 100 | number: '1.2-2' }} BSQ (<app-bsq-amount [bsq]="tx.burntFee" [forceFiat]="true" [green]="true"></app-bsq-amount>)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="float-right">
|
||||||
|
<span *ngIf="showConfirmations && latestBlock$ | async as latestBlock">
|
||||||
|
<button type="button" class="btn btn-sm btn-success mt-2">{{ latestBlock.height - tx.blockHeight + 1 }} confirmation<ng-container *ngIf="latestBlock.height - tx.blockHeight + 1 > 1">s</ng-container></button>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
<button type="button" class="btn btn-sm btn-primary mt-2" (click)="switchCurrency()">
|
||||||
|
<app-bsq-amount [bsq]="totalOutput"></app-bsq-amount>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
@ -1,5 +1,9 @@
|
|||||||
import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core';
|
import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges } from '@angular/core';
|
||||||
import { BisqTransaction } from 'src/app/bisq/bisq.interfaces';
|
import { BisqTransaction } from 'src/app/bisq/bisq.interfaces';
|
||||||
|
import { StateService } from 'src/app/services/state.service';
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { Block } from 'src/app/interfaces/electrs.interface';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bisq-transfers',
|
selector: 'app-bisq-transfers',
|
||||||
@ -7,13 +11,32 @@ import { BisqTransaction } from 'src/app/bisq/bisq.interfaces';
|
|||||||
styleUrls: ['./bisq-transfers.component.scss'],
|
styleUrls: ['./bisq-transfers.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class BisqTransfersComponent {
|
export class BisqTransfersComponent implements OnInit, OnChanges {
|
||||||
@Input() tx: BisqTransaction;
|
@Input() tx: BisqTransaction;
|
||||||
|
@Input() showConfirmations = false;
|
||||||
|
|
||||||
constructor() { }
|
totalOutput: number;
|
||||||
|
latestBlock$: Observable<Block>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private stateService: StateService,
|
||||||
|
) { }
|
||||||
|
|
||||||
trackByIndexFn(index: number) {
|
trackByIndexFn(index: number) {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.latestBlock$ = this.stateService.blocks$.pipe(map(([block]) => block));
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges() {
|
||||||
|
this.totalOutput = this.tx.outputs.filter((output) => output.isVerified).reduce((acc, output) => acc + output.bsqAmount, 0);;
|
||||||
|
}
|
||||||
|
|
||||||
|
switchCurrency() {
|
||||||
|
const oldvalue = !this.stateService.viewFiat$.value;
|
||||||
|
this.stateService.viewFiat$.next(oldvalue);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import { BisqExplorerComponent } from './bisq-explorer/bisq-explorer.component';
|
|||||||
import { BisqApiService } from './bisq-api.service';
|
import { BisqApiService } from './bisq-api.service';
|
||||||
import { BisqAddressComponent } from './bisq-address/bisq-address.component';
|
import { BisqAddressComponent } from './bisq-address/bisq-address.component';
|
||||||
import { BisqStatsComponent } from './bisq-stats/bisq-stats.component';
|
import { BisqStatsComponent } from './bisq-stats/bisq-stats.component';
|
||||||
|
import { BsqAmountComponent } from './bsq-amount/bsq-amount.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -31,6 +32,7 @@ import { BisqStatsComponent } from './bisq-stats/bisq-stats.component';
|
|||||||
BisqExplorerComponent,
|
BisqExplorerComponent,
|
||||||
BisqAddressComponent,
|
BisqAddressComponent,
|
||||||
BisqStatsComponent,
|
BisqStatsComponent,
|
||||||
|
BsqAmountComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
<ng-container *ngIf="(forceFiat || (viewFiat$ | async)) && (conversions$ | async) as conversions; else viewFiatVin">
|
||||||
|
<span [class.green-color]="green">{{ conversions.USD * bsq / 100 * (bsqPrice$ | async) / 100000000 | currency:'USD':'symbol':'1.2-2' }}</span>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #viewFiatVin>
|
||||||
|
{{ bsq / 100 | number : digitsInfo }} BSQ
|
||||||
|
</ng-template>
|
@ -0,0 +1,3 @@
|
|||||||
|
.green-color {
|
||||||
|
color: #3bcc49;
|
||||||
|
}
|
30
frontend/src/app/bisq/bsq-amount/bsq-amount.component.ts
Normal file
30
frontend/src/app/bisq/bsq-amount/bsq-amount.component.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core';
|
||||||
|
import { StateService } from 'src/app/services/state.service';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-bsq-amount',
|
||||||
|
templateUrl: './bsq-amount.component.html',
|
||||||
|
styleUrls: ['./bsq-amount.component.scss'],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
})
|
||||||
|
export class BsqAmountComponent implements OnInit {
|
||||||
|
conversions$: Observable<any>;
|
||||||
|
viewFiat$: Observable<boolean>;
|
||||||
|
bsqPrice$: Observable<number>;
|
||||||
|
|
||||||
|
@Input() bsq: number;
|
||||||
|
@Input() digitsInfo = '1.2-2';
|
||||||
|
@Input() forceFiat = false;
|
||||||
|
@Input() green = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private stateService: StateService,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.viewFiat$ = this.stateService.viewFiat$.asObservable();
|
||||||
|
this.conversions$ = this.stateService.conversions$.asObservable();
|
||||||
|
this.bsqPrice$ = this.stateService.bsqPrice$;
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ export class StateService {
|
|||||||
networkChanged$ = new ReplaySubject<string>(1);
|
networkChanged$ = new ReplaySubject<string>(1);
|
||||||
blocks$ = new ReplaySubject<[Block, boolean, boolean]>(env.KEEP_BLOCKS_AMOUNT);
|
blocks$ = new ReplaySubject<[Block, boolean, boolean]>(env.KEEP_BLOCKS_AMOUNT);
|
||||||
conversions$ = new ReplaySubject<any>(1);
|
conversions$ = new ReplaySubject<any>(1);
|
||||||
|
bsqPrice$ = new ReplaySubject<number>(1);
|
||||||
mempoolStats$ = new ReplaySubject<MemPoolState>(1);
|
mempoolStats$ = new ReplaySubject<MemPoolState>(1);
|
||||||
mempoolBlocks$ = new ReplaySubject<MempoolBlock[]>(1);
|
mempoolBlocks$ = new ReplaySubject<MempoolBlock[]>(1);
|
||||||
txReplaced$ = new Subject<Transaction>();
|
txReplaced$ = new Subject<Transaction>();
|
||||||
|
@ -99,6 +99,10 @@ export class WebsocketService {
|
|||||||
this.stateService.mempoolBlocks$.next(response['mempool-blocks']);
|
this.stateService.mempoolBlocks$.next(response['mempool-blocks']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response['bsq-price']) {
|
||||||
|
this.stateService.bsqPrice$.next(response['bsq-price']);
|
||||||
|
}
|
||||||
|
|
||||||
if (response['git-commit']) {
|
if (response['git-commit']) {
|
||||||
if (!this.latestGitCommit) {
|
if (!this.latestGitCommit) {
|
||||||
this.latestGitCommit = response['git-commit'];
|
this.latestGitCommit = response['git-commit'];
|
||||||
|
@ -11,6 +11,7 @@ import { WuBytesPipe } from './pipes/bytes-pipe/wubytes.pipe';
|
|||||||
import { TimeSinceComponent } from '../components/time-since/time-since.component';
|
import { TimeSinceComponent } from '../components/time-since/time-since.component';
|
||||||
import { ClipboardComponent } from '../components/clipboard/clipboard.component';
|
import { ClipboardComponent } from '../components/clipboard/clipboard.component';
|
||||||
import { QrcodeComponent } from '../components/qrcode/qrcode.component';
|
import { QrcodeComponent } from '../components/qrcode/qrcode.component';
|
||||||
|
import { FiatComponent } from '../fiat/fiat.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -25,6 +26,7 @@ import { QrcodeComponent } from '../components/qrcode/qrcode.component';
|
|||||||
ClipboardComponent,
|
ClipboardComponent,
|
||||||
TimeSinceComponent,
|
TimeSinceComponent,
|
||||||
QrcodeComponent,
|
QrcodeComponent,
|
||||||
|
FiatComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@ -44,6 +46,7 @@ import { QrcodeComponent } from '../components/qrcode/qrcode.component';
|
|||||||
TimeSinceComponent,
|
TimeSinceComponent,
|
||||||
ClipboardComponent,
|
ClipboardComponent,
|
||||||
QrcodeComponent,
|
QrcodeComponent,
|
||||||
|
FiatComponent,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class SharedModule {}
|
export class SharedModule {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user