From db2e293ce5f124ce71538ba6a623ba316ba45b93 Mon Sep 17 00:00:00 2001 From: softsimon Date: Mon, 13 Jul 2020 15:16:12 +0700 Subject: [PATCH] Bisq module separation. Transaction view. Block view. Blocks list. --- backend/src/api/bisq.ts | 57 +++--- backend/src/index.ts | 2 +- backend/src/routes.ts | 12 +- frontend/src/app/app.module.ts | 2 - frontend/src/app/bisq/bisq-api.service.ts | 33 ++++ .../bisq/bisq-block/bisq-block.component.html | 92 ++++++++-- .../bisq/bisq-block/bisq-block.component.scss | 10 ++ .../bisq/bisq-block/bisq-block.component.ts | 52 ++++-- .../bisq-blocks/bisq-blocks.component.html | 27 ++- .../bisq/bisq-blocks/bisq-blocks.component.ts | 43 ++++- .../bisq-transaction-details.component.html | 4 - .../bisq-transaction-details.component.ts | 2 +- .../bisq-transaction.component.html | 165 +++++++++++++----- .../bisq-transaction.component.scss | 9 + .../bisq-transaction.component.spec.ts | 25 --- .../bisq-transaction.component.ts | 36 ++-- .../bisq-transactions.component.html | 4 +- .../bisq-transactions.component.ts | 14 +- .../bisq-transfers.component.ts | 2 +- .../{interfaces => bisq}/bisq.interfaces.ts | 0 frontend/src/app/bisq/bisq.module.ts | 4 + .../app/components/block/block.component.ts | 6 +- .../transaction/transaction.component.ts | 2 +- frontend/src/app/services/api.service.ts | 19 -- frontend/src/app/shared/shared.module.ts | 3 + 25 files changed, 438 insertions(+), 187 deletions(-) create mode 100644 frontend/src/app/bisq/bisq-api.service.ts delete mode 100644 frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.spec.ts rename frontend/src/app/{interfaces => bisq}/bisq.interfaces.ts (100%) diff --git a/backend/src/api/bisq.ts b/backend/src/api/bisq.ts index e28974f8d..61a27de8d 100644 --- a/backend/src/api/bisq.ts +++ b/backend/src/api/bisq.ts @@ -21,23 +21,13 @@ class Bisq { clearTimeout(fsWait); } fsWait = setTimeout(() => { - console.log(`${filename} file changed. Reloading dump file.`); + console.log(`${filename} file change detected.`); this.loadBisqDumpFile(); }, 1000); } }); } - async loadBisqDumpFile(): Promise { - try { - const data = await this.loadData(); - await this.loadBisqBlocksDump(data); - this.buildIndex(); - } catch (e) { - console.log('loadBisqDumpFile() error.', e.message); - } - } - getTransaction(txId: string): BisqTransaction | undefined { return this.transactionsIndex[txId]; } @@ -46,43 +36,54 @@ class Bisq { return [this.transactions.slice(start, length + start), this.transactions.length]; } - getBlockTransactions(blockHash: string, start: number, length: number): [BisqTransaction[], number] { - const block = this.blocksIndex[blockHash]; - if (!block) { - return [[], -1]; - } - return [block.txs.slice(start, length + start), block.txs.length]; - } - getBlock(hash: string): BisqBlock | undefined { + console.log(hash); + console.log(this.blocksIndex[hash]); return this.blocksIndex[hash]; } + getBlocks(start: number, length: number): [BisqBlock[], number] { + return [this.blocks.slice(start, length + start), this.blocks.length]; + } + + private async loadBisqDumpFile(): Promise { + try { + const data = await this.loadData(); + await this.loadBisqBlocksDump(data); + this.buildIndex(); + } catch (e) { + console.log('loadBisqDumpFile() error.', e.message); + } + } + private buildIndex() { + const start = new Date().getTime(); + this.transactions = []; + this.transactionsIndex = {}; this.blocks.forEach((block) => { - if (this.blocksIndex[block.hash]) { - return; + if (!this.blocksIndex[block.hash]) { + this.blocksIndex[block.hash] = block; } - this.blocksIndex[block.hash] = block; block.txs.forEach((tx) => { - this.transactions.unshift(tx); + this.transactions.push(tx); this.transactionsIndex[tx.id] = tx; }); }); - console.log('Bisq data index rebuilt'); + const time = new Date().getTime() - start; + console.log('Bisq data index rebuilt in ' + time + ' ms'); } private async loadBisqBlocksDump(cacheData: string): Promise { const start = new Date().getTime(); if (cacheData && cacheData.length !== 0) { - console.log('Parsing Bisq data from dump file'); + console.log('Loading Bisq data from dump...'); const data: BisqBlocks = JSON.parse(cacheData); if (data.blocks && data.blocks.length !== this.blocks.length) { this.blocks = data.blocks; + this.blocks.reverse(); this.latestBlockHeight = data.chainHeight; - const end = new Date().getTime(); - const time = end - start; - console.log('Loaded bisq dump in ' + time + ' ms'); + const time = new Date().getTime() - start; + console.log('Bisq dump loaded in ' + time + ' ms'); } else { throw new Error(`Bisq dump didn't contain any blocks`); } diff --git a/backend/src/index.ts b/backend/src/index.ts index 2626be5fc..ae4796a37 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -94,7 +94,7 @@ class Server { this.app .get(config.API_ENDPOINT + 'bisq/tx/:txId', routes.getBisqTransaction) .get(config.API_ENDPOINT + 'bisq/block/:hash', routes.getBisqBlock) - .get(config.API_ENDPOINT + 'bisq/block/:hash/txs/:index/:length', routes.getBisqBlockTransactions) + .get(config.API_ENDPOINT + 'bisq/blocks/:index/:length', routes.getBisqBlocks) .get(config.API_ENDPOINT + 'bisq/txs/:index/:length', routes.getBisqTransactions) ; } diff --git a/backend/src/routes.ts b/backend/src/routes.ts index e2efbb4ba..271a70876 100644 --- a/backend/src/routes.ts +++ b/backend/src/routes.ts @@ -105,7 +105,7 @@ class Routes { } public getBisqBlock(req: Request, res: Response) { - const result = bisq.getBlock(req['hash']); + const result = bisq.getBlock(req.params.hash); if (result) { res.send(result); } else { @@ -113,16 +113,10 @@ class Routes { } } - public getBisqBlockTransactions(req: Request, res: Response) { - const blockHash = req.params.hash || ''; + public getBisqBlocks(req: Request, res: Response) { const index = parseInt(req.params.index, 10) || 0; const length = parseInt(req.params.length, 10) > 100 ? 100 : parseInt(req.params.length, 10) || 25; - const [transactions, count] = bisq.getBlockTransactions(blockHash, index, length); - if (count === -1) { - res.header('X-Total-Count', '0'); - res.send([]); - return; - } + const [transactions, count] = bisq.getBlocks(index, length); res.header('X-Total-Count', count.toString()); res.send(transactions); } diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 480bd6802..11d0aed61 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -23,7 +23,6 @@ import { WebsocketService } from './services/websocket.service'; import { AddressLabelsComponent } from './components/address-labels/address-labels.component'; import { MempoolBlocksComponent } from './components/mempool-blocks/mempool-blocks.component'; import { QrcodeComponent } from './components/qrcode/qrcode.component'; -import { ClipboardComponent } from './components/clipboard/clipboard.component'; import { MasterPageComponent } from './components/master-page/master-page.component'; import { AboutComponent } from './components/about/about.component'; import { TelevisionComponent } from './components/television/television.component'; @@ -66,7 +65,6 @@ import { SharedModule } from './shared/shared.module'; AddressLabelsComponent, MempoolBlocksComponent, QrcodeComponent, - ClipboardComponent, ChartistComponent, FooterComponent, FiatComponent, diff --git a/frontend/src/app/bisq/bisq-api.service.ts b/frontend/src/app/bisq/bisq-api.service.ts new file mode 100644 index 000000000..c1bf92420 --- /dev/null +++ b/frontend/src/app/bisq/bisq-api.service.ts @@ -0,0 +1,33 @@ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpResponse } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { BisqTransaction, BisqBlock } from './bisq.interfaces'; + +const API_BASE_URL = '/api/v1'; + +@Injectable({ + providedIn: 'root' +}) +export class BisqApiService { + apiBaseUrl: string; + + constructor( + private httpClient: HttpClient, + ) { } + + getTransaction$(txId: string): Observable { + return this.httpClient.get(API_BASE_URL + '/bisq/tx/' + txId); + } + + listTransactions$(start: number, length: number): Observable> { + return this.httpClient.get(API_BASE_URL + `/bisq/txs/${start}/${length}`, { observe: 'response' }); + } + + getBlock$(hash: string): Observable { + return this.httpClient.get(API_BASE_URL + '/bisq/block/' + hash); + } + + listBlocks$(start: number, length: number): Observable> { + return this.httpClient.get(API_BASE_URL + `/bisq/blocks/${start}/${length}`, { observe: 'response' }); + } +} diff --git a/frontend/src/app/bisq/bisq-block/bisq-block.component.html b/frontend/src/app/bisq/bisq-block/bisq-block.component.html index de8253b8b..f2fd3c7cd 100644 --- a/frontend/src/app/bisq/bisq-block/bisq-block.component.html +++ b/frontend/src/app/bisq/bisq-block/bisq-block.component.html @@ -6,23 +6,95 @@
- + -
- - {{ tx.id | shortenString : 16 }} - {{ tx.id }} - -
- {{ tx.time | date:'yyyy-MM-dd HH:mm' }} +
+
+
+ + + + + + + + + + +
Hash{{ block.hash | shortenString : 13 }}
Timestamp + {{ block.time | date:'yyyy-MM-dd HH:mm' }} +
+ ( ago) +
+
+
+
-
- +

+

{{ block.txs.length | number }} transactions

+ + + +
+ + {{ tx.id | shortenString : 16 }} + {{ tx.id }} + +
+ {{ tx.time | date:'yyyy-MM-dd HH:mm' }} +
+
+
+ + + +
+
+ + + + + + +
+
+
+ + + + + + + + + + +
Hash
Timestamp
+
+
+ + + + + + +
Previous hash
+
+
+
\ No newline at end of file diff --git a/frontend/src/app/bisq/bisq-block/bisq-block.component.scss b/frontend/src/app/bisq/bisq-block/bisq-block.component.scss index e69de29bb..0fc8e761e 100644 --- a/frontend/src/app/bisq/bisq-block/bisq-block.component.scss +++ b/frontend/src/app/bisq/bisq-block/bisq-block.component.scss @@ -0,0 +1,10 @@ + +.td-width { + width: 175px; +} + +@media (max-width: 767.98px) { + .td-width { + width: 140px; + } +} diff --git a/frontend/src/app/bisq/bisq-block/bisq-block.component.ts b/frontend/src/app/bisq/bisq-block/bisq-block.component.ts index c0568e9b5..c09a6658c 100644 --- a/frontend/src/app/bisq/bisq-block/bisq-block.component.ts +++ b/frontend/src/app/bisq/bisq-block/bisq-block.component.ts @@ -1,32 +1,52 @@ -import { Component, OnInit } from '@angular/core'; -import { BisqTransaction } from 'src/app/interfaces/bisq.interfaces'; -import { ApiService } from 'src/app/services/api.service'; +import { Component, OnInit, OnDestroy } from '@angular/core'; +import { BisqTransaction, BisqBlock } from 'src/app/bisq/bisq.interfaces'; +import { BisqApiService } from '../bisq-api.service'; +import { ActivatedRoute, ParamMap } from '@angular/router'; +import { Subscribable, Subscription, of } from 'rxjs'; +import { switchMap } from 'rxjs/operators'; @Component({ selector: 'app-bisq-block', templateUrl: './bisq-block.component.html', styleUrls: ['./bisq-block.component.scss'] }) -export class BisqBlockComponent implements OnInit { - bisqTransactions: BisqTransaction[]; - bisqTransactionsCount: number; - +export class BisqBlockComponent implements OnInit, OnDestroy { + block: BisqBlock; + subscription: Subscription; blockHash = ''; blockHeight = 0; + isLoading = true; + error: any; constructor( - private apiService: ApiService, + private bisqApiService: BisqApiService, + private route: ActivatedRoute, ) { } ngOnInit(): void { - this.apiService.listBisqBlockTransactions$(this.blockHash, 0, 10) - .subscribe((response) => { - this.bisqTransactionsCount = parseInt(response.headers.get('x-total-count'), 10); - this.bisqTransactions = response.body; - }); - + this.subscription = this.route.paramMap + .pipe( + switchMap((params: ParamMap) => { + this.blockHash = params.get('id') || ''; + this.isLoading = true; + if (history.state.data && history.state.data.blockHeight) { + this.blockHeight = history.state.data.blockHeight; + } + if (history.state.data && history.state.data.block) { + this.blockHeight = history.state.data.block.height; + return of(history.state.data.block); + } + return this.bisqApiService.getBlock$(this.blockHash); + }) + ) + .subscribe((block: BisqBlock) => { + this.isLoading = false; + this.blockHeight = block.height; + this.block = block; + }); } - - + ngOnDestroy() { + this.subscription.unsubscribe(); + } } diff --git a/frontend/src/app/bisq/bisq-blocks/bisq-blocks.component.html b/frontend/src/app/bisq/bisq-blocks/bisq-blocks.component.html index b2f4f2693..a5a01f8a8 100644 --- a/frontend/src/app/bisq/bisq-blocks/bisq-blocks.component.html +++ b/frontend/src/app/bisq/bisq-blocks/bisq-blocks.component.html @@ -1,5 +1,30 @@
-

Blocks

+

BSQ Blocks


+
+ + + + + + + + + + + + + + + + + + +
HashTotal Sent (BSQ)TransactionsHeightTime
{{ block.hash | shortenString : 13 }}{{ calculateTotalOutput(block) / 100 | number: '1.2-2' }}{{ block.txs.length }}{{ block.height }}{{ block.time | date:'yyyy-MM-dd HH:mm' }}
+ +
+ + +
\ No newline at end of file diff --git a/frontend/src/app/bisq/bisq-blocks/bisq-blocks.component.ts b/frontend/src/app/bisq/bisq-blocks/bisq-blocks.component.ts index 076a57140..168b9d040 100644 --- a/frontend/src/app/bisq/bisq-blocks/bisq-blocks.component.ts +++ b/frontend/src/app/bisq/bisq-blocks/bisq-blocks.component.ts @@ -1,4 +1,8 @@ import { Component, OnInit } from '@angular/core'; +import { BisqApiService } from '../bisq-api.service'; +import { switchMap } from 'rxjs/operators'; +import { Subject } from 'rxjs'; +import { BisqBlock, BisqOutput, BisqTransaction } from '../bisq.interfaces'; @Component({ selector: 'app-bisq-blocks', @@ -6,10 +10,47 @@ import { Component, OnInit } from '@angular/core'; styleUrls: ['./bisq-blocks.component.scss'] }) export class BisqBlocksComponent implements OnInit { + blocks: BisqBlock[]; + totalCount: number; + page = 1; + itemsPerPage: number; + contentSpace = window.innerHeight - (165 + 75); + fiveItemsPxSize = 250; - constructor() { } + pageSubject$ = new Subject(); + + constructor( + private bisqApiService: BisqApiService, + ) { } ngOnInit(): void { + this.itemsPerPage = Math.max(Math.round(this.contentSpace / this.fiveItemsPxSize) * 5, 10); + + this.pageSubject$ + .pipe( + switchMap((page) => this.bisqApiService.listBlocks$((page - 1) * 10, this.itemsPerPage)) + ) + .subscribe((response) => { + this.blocks = response.body; + this.totalCount = parseInt(response.headers.get('x-total-count'), 10); + }, (error) => { + console.log(error); + }); + + this.pageSubject$.next(1); } + calculateTotalOutput(block: BisqBlock): number { + return block.txs.reduce((a: number, tx: BisqTransaction) => + a + tx.outputs.reduce((acc: number, output: BisqOutput) => acc + output.bsqAmount, 0), 0 + ); + } + + trackByFn(index: number) { + return index; + } + + pageChange(page: number) { + this.pageSubject$.next(page); + } } diff --git a/frontend/src/app/bisq/bisq-transaction-details/bisq-transaction-details.component.html b/frontend/src/app/bisq/bisq-transaction-details/bisq-transaction-details.component.html index 59f412171..9f9d83673 100644 --- a/frontend/src/app/bisq/bisq-transaction-details/bisq-transaction-details.component.html +++ b/frontend/src/app/bisq/bisq-transaction-details/bisq-transaction-details.component.html @@ -11,10 +11,6 @@ Outputs {{ totalOutput / 100 | number: '1.2-2' }} BSQ - - Burnt - {{ tx.burntFee / 100 | number: '1.2-2' }} BSQ - Issuance {{ totalIssued / 100 | number: '1.2-2' }} BSQ diff --git a/frontend/src/app/bisq/bisq-transaction-details/bisq-transaction-details.component.ts b/frontend/src/app/bisq/bisq-transaction-details/bisq-transaction-details.component.ts index 927f3af20..d10d0507e 100644 --- a/frontend/src/app/bisq/bisq-transaction-details/bisq-transaction-details.component.ts +++ b/frontend/src/app/bisq/bisq-transaction-details/bisq-transaction-details.component.ts @@ -1,5 +1,5 @@ import { Component, ChangeDetectionStrategy, Input, OnChanges } from '@angular/core'; -import { BisqTransaction } from 'src/app/interfaces/bisq.interfaces'; +import { BisqTransaction } from 'src/app/bisq/bisq.interfaces'; @Component({ selector: 'app-bisq-transaction-details', diff --git a/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.html b/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.html index 96532620b..3625fcceb 100644 --- a/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.html +++ b/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.html @@ -2,64 +2,133 @@

Transaction

- + - -
+ -
-
-
+ +
+ +
+
+
+ + + + + + + +
Included in block + {{ bisqTx.blockHeight }} + ( ago) +
+
+
+ + + + + + +
Fee burnt + {{ bisqTx.burntFee / 100 | number: '1.2-2' }} BSQ +
+
+ +
+
+ +
+ +

Details

+ + + + +
+ +

Inputs & Outputs

+ + + +
+ + + + + +
+ +
+
+
+ + + + + + + +
+
+
+ + + + + + + +
+
+
+
+ +
+ +

Details

+
+ + + + + + + + + + + + + + +
+
+ +
+ +

Inputs & Outputs

+ +
+
- - + +
Included in block - {{ bisqTx.blockHeight }} - ( ago) -
-
- - - - - - - - - - - -
Fee15,436 sat ($1.40)
Fee per vByte 68.2 sat/vB -
-
-
-
- -
- -

Details

- - - - -
- -

Inputs & Outputs

- - - -
+
\ No newline at end of file diff --git a/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.scss b/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.scss index e69de29bb..35000b90e 100644 --- a/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.scss +++ b/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.scss @@ -0,0 +1,9 @@ +.td-width { + width: 175px; +} + +@media (max-width: 767.98px) { + .td-width { + width: 150px; + } +} \ No newline at end of file diff --git a/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.spec.ts b/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.spec.ts deleted file mode 100644 index 23ed00bbe..000000000 --- a/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; - -import { BisqTransactionComponent } from './bisq-transaction.component'; - -describe('BisqTransactionComponent', () => { - let component: BisqTransactionComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ BisqTransactionComponent ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(BisqTransactionComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.ts b/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.ts index 1e4ef7410..f79385940 100644 --- a/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.ts +++ b/frontend/src/app/bisq/bisq-transaction/bisq-transaction.component.ts @@ -1,36 +1,50 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, OnDestroy } from '@angular/core'; import { ActivatedRoute, ParamMap } from '@angular/router'; -import { BisqTransaction } from 'src/app/interfaces/bisq.interfaces'; -import { switchMap } from 'rxjs/operators'; -import { ApiService } from 'src/app/services/api.service'; -import { of } from 'rxjs'; +import { BisqTransaction } from 'src/app/bisq/bisq.interfaces'; +import { switchMap, map } from 'rxjs/operators'; +import { of, Observable, Subscription } from 'rxjs'; +import { StateService } from 'src/app/services/state.service'; +import { Block } from 'src/app/interfaces/electrs.interface'; +import { BisqApiService } from '../bisq-api.service'; @Component({ selector: 'app-bisq-transaction', templateUrl: './bisq-transaction.component.html', styleUrls: ['./bisq-transaction.component.scss'] }) -export class BisqTransactionComponent implements OnInit { +export class BisqTransactionComponent implements OnInit, OnDestroy { bisqTx: BisqTransaction; + latestBlock$: Observable; txId: string; + isLoading = true; + subscription: Subscription; constructor( private route: ActivatedRoute, - private apiService: ApiService, + private bisqApiService: BisqApiService, + private stateService: StateService, ) { } ngOnInit(): void { - this.route.paramMap.pipe( + this.subscription = this.route.paramMap.pipe( switchMap((params: ParamMap) => { + this.isLoading = true; this.txId = params.get('id') || ''; - if (history.state.bsqTx) { - return of(history.state.bsqTx); + if (history.state.data) { + return of(history.state.data); } - return this.apiService.getBisqTransaction$(this.txId); + return this.bisqApiService.getTransaction$(this.txId); }) ) .subscribe((tx) => { + this.isLoading = false; this.bisqTx = tx; }); + + this.latestBlock$ = this.stateService.blocks$.pipe(map((([block]) => block))); + } + + ngOnDestroy() { + this.subscription.unsubscribe(); } } diff --git a/frontend/src/app/bisq/bisq-transactions/bisq-transactions.component.html b/frontend/src/app/bisq/bisq-transactions/bisq-transactions.component.html index 8e713910a..b882f3456 100644 --- a/frontend/src/app/bisq/bisq-transactions/bisq-transactions.component.html +++ b/frontend/src/app/bisq/bisq-transactions/bisq-transactions.component.html @@ -1,5 +1,5 @@
-

Latest BSQ Transactions

+

BSQ Transactions


@@ -14,7 +14,7 @@ Block Time - + {{ tx.id | shortenString : 16 }} {{ tx.txTypeDisplayString }} {{ calculateTotalOutput(tx.outputs) / 100 | number: '1.2-2' }} diff --git a/frontend/src/app/bisq/bisq-transactions/bisq-transactions.component.ts b/frontend/src/app/bisq/bisq-transactions/bisq-transactions.component.ts index 80df5083b..232a3ca5b 100644 --- a/frontend/src/app/bisq/bisq-transactions/bisq-transactions.component.ts +++ b/frontend/src/app/bisq/bisq-transactions/bisq-transactions.component.ts @@ -1,8 +1,8 @@ import { Component, OnInit } from '@angular/core'; -import { BisqTransaction, BisqOutput } from '../../interfaces/bisq.interfaces'; +import { BisqTransaction, BisqOutput } from '../bisq.interfaces'; import { Subject } from 'rxjs'; import { switchMap } from 'rxjs/operators'; -import { ApiService } from 'src/app/services/api.service'; +import { BisqApiService } from '../bisq-api.service'; @Component({ selector: 'app-bisq-transactions', @@ -14,13 +14,13 @@ export class BisqTransactionsComponent implements OnInit { totalCount: number; page = 1; itemsPerPage: number; - contentSpace = window.innerHeight - (200 + 200); + contentSpace = window.innerHeight - (165 + 75); fiveItemsPxSize = 250; pageSubject$ = new Subject(); constructor( - private apiService: ApiService, + private bisqApiService: BisqApiService, ) { } ngOnInit(): void { @@ -28,7 +28,7 @@ export class BisqTransactionsComponent implements OnInit { this.pageSubject$ .pipe( - switchMap((page) => this.apiService.listBisqTransactions$((page - 1) * 10, this.itemsPerPage)) + switchMap((page) => this.bisqApiService.listTransactions$((page - 1) * 10, this.itemsPerPage)) ) .subscribe((response) => { this.transactions = response.body; @@ -47,4 +47,8 @@ export class BisqTransactionsComponent implements OnInit { calculateTotalOutput(outputs: BisqOutput[]): number { return outputs.reduce((acc: number, output: BisqOutput) => acc + output.bsqAmount, 0); } + + trackByFn(index: number) { + return index; + } } diff --git a/frontend/src/app/bisq/bisq-transfers/bisq-transfers.component.ts b/frontend/src/app/bisq/bisq-transfers/bisq-transfers.component.ts index 8b96a709b..8f0a76307 100644 --- a/frontend/src/app/bisq/bisq-transfers/bisq-transfers.component.ts +++ b/frontend/src/app/bisq/bisq-transfers/bisq-transfers.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core'; -import { BisqTransaction } from 'src/app/interfaces/bisq.interfaces'; +import { BisqTransaction } from 'src/app/bisq/bisq.interfaces'; @Component({ selector: 'app-bisq-transfers', diff --git a/frontend/src/app/interfaces/bisq.interfaces.ts b/frontend/src/app/bisq/bisq.interfaces.ts similarity index 100% rename from frontend/src/app/interfaces/bisq.interfaces.ts rename to frontend/src/app/bisq/bisq.interfaces.ts diff --git a/frontend/src/app/bisq/bisq.module.ts b/frontend/src/app/bisq/bisq.module.ts index dc3432a65..ca02919f9 100644 --- a/frontend/src/app/bisq/bisq.module.ts +++ b/frontend/src/app/bisq/bisq.module.ts @@ -14,6 +14,7 @@ import { faLeaf, faQuestion, faExclamationTriangle, faRocket, faRetweet, faFileA faEye, faEyeSlash, faLock, faLockOpen } from '@fortawesome/free-solid-svg-icons'; import { BisqBlocksComponent } from './bisq-blocks/bisq-blocks.component'; import { BisqExplorerComponent } from './bisq-explorer/bisq-explorer.component'; +import { BisqApiService } from './bisq-api.service'; @NgModule({ declarations: [ @@ -34,6 +35,9 @@ import { BisqExplorerComponent } from './bisq-explorer/bisq-explorer.component'; NgbPaginationModule, FontAwesomeModule, ], + providers: [ + BisqApiService, + ] }) export class BisqModule { constructor(library: FaIconLibrary) { diff --git a/frontend/src/app/components/block/block.component.ts b/frontend/src/app/components/block/block.component.ts index 9199a2e5b..7b43cf416 100644 --- a/frontend/src/app/components/block/block.component.ts +++ b/frontend/src/app/components/block/block.component.ts @@ -4,7 +4,7 @@ import { ActivatedRoute, ParamMap, Router } from '@angular/router'; import { ElectrsApiService } from '../../services/electrs-api.service'; import { switchMap, tap, debounceTime, catchError } from 'rxjs/operators'; import { Block, Transaction, Vout } from '../../interfaces/electrs.interface'; -import { of } from 'rxjs'; +import { of, Subscription } from 'rxjs'; import { StateService } from '../../services/state.service'; import { SeoService } from 'src/app/services/seo.service'; import { env } from 'src/app/app.constants'; @@ -25,6 +25,7 @@ export class BlockComponent implements OnInit, OnDestroy { isLoadingTransactions = true; error: any; blockSubsidy: number; + subscription: Subscription; fees: number; paginationMaxSize: number; page = 1; @@ -43,7 +44,7 @@ export class BlockComponent implements OnInit, OnDestroy { this.paginationMaxSize = window.matchMedia('(max-width: 700px)').matches ? 3 : 5; this.network = this.stateService.network; - this.route.paramMap + this.subscription = this.route.paramMap .pipe( switchMap((params: ParamMap) => { const blockHash: string = params.get('id') || ''; @@ -129,6 +130,7 @@ export class BlockComponent implements OnInit, OnDestroy { ngOnDestroy() { this.stateService.markBlock$.next({}); + this.subscription.unsubscribe(); } setBlockSubsidy() { diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts index 3ac6356be..495685831 100644 --- a/frontend/src/app/components/transaction/transaction.component.ts +++ b/frontend/src/app/components/transaction/transaction.component.ts @@ -10,7 +10,7 @@ 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/interfaces/bisq.interfaces'; +import { BisqTransaction } from 'src/app/bisq/bisq.interfaces'; @Component({ selector: 'app-transaction', diff --git a/frontend/src/app/services/api.service.ts b/frontend/src/app/services/api.service.ts index a938136bd..a16b5154f 100644 --- a/frontend/src/app/services/api.service.ts +++ b/frontend/src/app/services/api.service.ts @@ -3,7 +3,6 @@ import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; import { OptimizedMempoolStats } from '../interfaces/node-api.interface'; import { Observable } from 'rxjs'; import { StateService } from './state.service'; -import { BisqTransaction, BisqBlock } from '../interfaces/bisq.interfaces'; const API_BASE_URL = '{network}/api/v1'; @@ -61,22 +60,4 @@ export class ApiService { }); return this.httpClient.get(this.apiBaseUrl + '/transaction-times', { params }); } - - getBisqTransaction$(txId: string): Observable { - return this.httpClient.get(this.apiBaseUrl + '/bisq/tx/' + txId); - } - - listBisqTransactions$(start: number, length: number): Observable> { - return this.httpClient.get(this.apiBaseUrl + `/bisq/txs/${start}/${length}`, { observe: 'response' }); - } - - getBisqBlock$(hash: string): Observable { - return this.httpClient.get(this.apiBaseUrl + '/bisq/block/' + hash); - } - - listBisqBlockTransactions$(blockHash: string, start: number, length: number): Observable> { - return this.httpClient.get( - this.apiBaseUrl + `/bisq/block/${blockHash}/txs/${start}/${length}`, { observe: 'response' } - ); - } } diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index 1b116c1b5..003626b6c 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -9,6 +9,7 @@ import { ScriptpubkeyTypePipe } from './pipes/scriptpubkey-type-pipe/scriptpubke import { BytesPipe } from './pipes/bytes-pipe/bytes.pipe'; import { WuBytesPipe } from './pipes/bytes-pipe/wubytes.pipe'; import { TimeSinceComponent } from '../components/time-since/time-since.component'; +import { ClipboardComponent } from '../components/clipboard/clipboard.component'; @NgModule({ declarations: [ @@ -20,6 +21,7 @@ import { TimeSinceComponent } from '../components/time-since/time-since.componen WuBytesPipe, CeilPipe, ShortenStringPipe, + ClipboardComponent, TimeSinceComponent, ], imports: [ @@ -38,6 +40,7 @@ import { TimeSinceComponent } from '../components/time-since/time-since.componen CeilPipe, ShortenStringPipe, TimeSinceComponent, + ClipboardComponent ] }) export class SharedModule {}