Address index and api.
Address view.
This commit is contained in:
parent
db2e293ce5
commit
432fb9cd66
@ -3,11 +3,11 @@ import * as fs from 'fs';
|
|||||||
import { BisqBlocks, BisqBlock, BisqTransaction } from '../interfaces';
|
import { BisqBlocks, BisqBlock, BisqTransaction } from '../interfaces';
|
||||||
|
|
||||||
class Bisq {
|
class Bisq {
|
||||||
private latestBlockHeight = 0;
|
|
||||||
private blocks: BisqBlock[] = [];
|
private blocks: BisqBlock[] = [];
|
||||||
private transactions: BisqTransaction[] = [];
|
private transactions: BisqTransaction[] = [];
|
||||||
private transactionsIndex: { [txId: string]: BisqTransaction } = {};
|
private transactionIndex: { [txId: string]: BisqTransaction } = {};
|
||||||
private blocksIndex: { [hash: string]: BisqBlock } = {};
|
private blockIndex: { [hash: string]: BisqBlock } = {};
|
||||||
|
private addressIndex: { [address: string]: BisqTransaction[] } = {};
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ class Bisq {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getTransaction(txId: string): BisqTransaction | undefined {
|
getTransaction(txId: string): BisqTransaction | undefined {
|
||||||
return this.transactionsIndex[txId];
|
return this.transactionIndex[txId];
|
||||||
}
|
}
|
||||||
|
|
||||||
getTransactions(start: number, length: number): [BisqTransaction[], number] {
|
getTransactions(start: number, length: number): [BisqTransaction[], number] {
|
||||||
@ -37,9 +37,11 @@ class Bisq {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getBlock(hash: string): BisqBlock | undefined {
|
getBlock(hash: string): BisqBlock | undefined {
|
||||||
console.log(hash);
|
return this.blockIndex[hash];
|
||||||
console.log(this.blocksIndex[hash]);
|
}
|
||||||
return this.blocksIndex[hash];
|
|
||||||
|
getAddress(hash: string): BisqTransaction[] {
|
||||||
|
return this.addressIndex[hash];
|
||||||
}
|
}
|
||||||
|
|
||||||
getBlocks(start: number, length: number): [BisqBlock[], number] {
|
getBlocks(start: number, length: number): [BisqBlock[], number] {
|
||||||
@ -59,16 +61,42 @@ class Bisq {
|
|||||||
private buildIndex() {
|
private buildIndex() {
|
||||||
const start = new Date().getTime();
|
const start = new Date().getTime();
|
||||||
this.transactions = [];
|
this.transactions = [];
|
||||||
this.transactionsIndex = {};
|
this.transactionIndex = {};
|
||||||
|
this.addressIndex = {};
|
||||||
|
|
||||||
this.blocks.forEach((block) => {
|
this.blocks.forEach((block) => {
|
||||||
if (!this.blocksIndex[block.hash]) {
|
/* Build block index */
|
||||||
this.blocksIndex[block.hash] = block;
|
if (!this.blockIndex[block.hash]) {
|
||||||
|
this.blockIndex[block.hash] = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Build transactions index */
|
||||||
block.txs.forEach((tx) => {
|
block.txs.forEach((tx) => {
|
||||||
this.transactions.push(tx);
|
this.transactions.push(tx);
|
||||||
this.transactionsIndex[tx.id] = tx;
|
this.transactionIndex[tx.id] = tx;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* Build address index */
|
||||||
|
this.transactions.forEach((tx) => {
|
||||||
|
tx.inputs.forEach((input) => {
|
||||||
|
if (!this.addressIndex[input.address]) {
|
||||||
|
this.addressIndex[input.address] = [];
|
||||||
|
}
|
||||||
|
if (this.addressIndex[input.address].indexOf(tx) === -1) {
|
||||||
|
this.addressIndex[input.address].push(tx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tx.outputs.forEach((output) => {
|
||||||
|
if (!this.addressIndex[output.address]) {
|
||||||
|
this.addressIndex[output.address] = [];
|
||||||
|
}
|
||||||
|
if (this.addressIndex[output.address].indexOf(tx) === -1) {
|
||||||
|
this.addressIndex[output.address].push(tx);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const time = new Date().getTime() - start;
|
const time = new Date().getTime() - start;
|
||||||
console.log('Bisq data index rebuilt in ' + time + ' ms');
|
console.log('Bisq data index rebuilt in ' + time + ' ms');
|
||||||
}
|
}
|
||||||
@ -81,7 +109,6 @@ class Bisq {
|
|||||||
if (data.blocks && data.blocks.length !== this.blocks.length) {
|
if (data.blocks && data.blocks.length !== this.blocks.length) {
|
||||||
this.blocks = data.blocks;
|
this.blocks = data.blocks;
|
||||||
this.blocks.reverse();
|
this.blocks.reverse();
|
||||||
this.latestBlockHeight = data.chainHeight;
|
|
||||||
const time = new Date().getTime() - start;
|
const time = new Date().getTime() - start;
|
||||||
console.log('Bisq dump loaded in ' + time + ' ms');
|
console.log('Bisq dump loaded in ' + time + ' ms');
|
||||||
} else {
|
} else {
|
||||||
|
@ -95,6 +95,7 @@ class Server {
|
|||||||
.get(config.API_ENDPOINT + 'bisq/tx/:txId', routes.getBisqTransaction)
|
.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', routes.getBisqBlock)
|
||||||
.get(config.API_ENDPOINT + 'bisq/blocks/:index/:length', routes.getBisqBlocks)
|
.get(config.API_ENDPOINT + 'bisq/blocks/:index/:length', routes.getBisqBlocks)
|
||||||
|
.get(config.API_ENDPOINT + 'bisq/address/:address', routes.getBisqAddress)
|
||||||
.get(config.API_ENDPOINT + 'bisq/txs/:index/:length', routes.getBisqTransactions)
|
.get(config.API_ENDPOINT + 'bisq/txs/:index/:length', routes.getBisqTransactions)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -120,6 +120,15 @@ class Routes {
|
|||||||
res.header('X-Total-Count', count.toString());
|
res.header('X-Total-Count', count.toString());
|
||||||
res.send(transactions);
|
res.send(transactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getBisqAddress(req: Request, res: Response) {
|
||||||
|
const result = bisq.getAddress(req.params.address.substr(1));
|
||||||
|
if (result) {
|
||||||
|
res.send(result);
|
||||||
|
} else {
|
||||||
|
res.status(404).send('Bisq address not found');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new Routes();
|
export default new Routes();
|
||||||
|
@ -22,7 +22,6 @@ import { LatestBlocksComponent } from './components/latest-blocks/latest-blocks.
|
|||||||
import { WebsocketService } from './services/websocket.service';
|
import { WebsocketService } from './services/websocket.service';
|
||||||
import { AddressLabelsComponent } from './components/address-labels/address-labels.component';
|
import { AddressLabelsComponent } from './components/address-labels/address-labels.component';
|
||||||
import { MempoolBlocksComponent } from './components/mempool-blocks/mempool-blocks.component';
|
import { MempoolBlocksComponent } from './components/mempool-blocks/mempool-blocks.component';
|
||||||
import { QrcodeComponent } from './components/qrcode/qrcode.component';
|
|
||||||
import { MasterPageComponent } from './components/master-page/master-page.component';
|
import { MasterPageComponent } from './components/master-page/master-page.component';
|
||||||
import { AboutComponent } from './components/about/about.component';
|
import { AboutComponent } from './components/about/about.component';
|
||||||
import { TelevisionComponent } from './components/television/television.component';
|
import { TelevisionComponent } from './components/television/television.component';
|
||||||
@ -64,7 +63,6 @@ import { SharedModule } from './shared/shared.module';
|
|||||||
TimespanComponent,
|
TimespanComponent,
|
||||||
AddressLabelsComponent,
|
AddressLabelsComponent,
|
||||||
MempoolBlocksComponent,
|
MempoolBlocksComponent,
|
||||||
QrcodeComponent,
|
|
||||||
ChartistComponent,
|
ChartistComponent,
|
||||||
FooterComponent,
|
FooterComponent,
|
||||||
FiatComponent,
|
FiatComponent,
|
||||||
|
106
frontend/src/app/bisq/bisq-address/bisq-address.component.html
Normal file
106
frontend/src/app/bisq/bisq-address/bisq-address.component.html
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<div class="container-xl">
|
||||||
|
<h1 style="float: left;">Bisq Address</h1>
|
||||||
|
<a [routerLink]="['/address/' | relativeUrl, addressString]" style="line-height: 56px; margin-left: 10px;">
|
||||||
|
<span class="d-inline d-lg-none">{{ addressString | shortenString : 24 }}</span>
|
||||||
|
<span class="d-none d-lg-inline">{{ addressString }}</span>
|
||||||
|
</a>
|
||||||
|
<app-clipboard [text]="addressString"></app-clipboard>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
|
||||||
|
<ng-template [ngIf]="!isLoadingAddress && !error">
|
||||||
|
<div class="box">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<table class="table table-borderless table-striped">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Total received</td>
|
||||||
|
<td>{{ totalReceived / 100 }} BSQ</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Total sent</td>
|
||||||
|
<td>{{ totalSent / 100 }} BSQ</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Final balance</td>
|
||||||
|
<td>{{ (totalReceived - totalSent) / 100 }} BSQ</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="w-100 d-block d-md-none"></div>
|
||||||
|
<div class="col qrcode-col">
|
||||||
|
<div class="qr-wrapper">
|
||||||
|
<app-qrcode [data]="addressString"></app-qrcode>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<h2>{{ transactions.length | number }} transactions</h2>
|
||||||
|
|
||||||
|
<ng-template ngFor let-tx [ngForOf]="transactions">
|
||||||
|
|
||||||
|
<div class="header-bg box" style="padding: 10px; margin-bottom: 10px;">
|
||||||
|
<a [routerLink]="['/tx/' | relativeUrl, tx.id]" [state]="{ data: tx }">
|
||||||
|
<span style="float: left;" class="d-block d-md-none">{{ tx.id | shortenString : 16 }}</span>
|
||||||
|
<span style="float: left;" class="d-none d-md-block">{{ tx.id }}</span>
|
||||||
|
</a>
|
||||||
|
<div class="float-right">
|
||||||
|
{{ tx.time | date:'yyyy-MM-dd HH:mm' }}
|
||||||
|
</div>
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<app-bisq-transfers [tx]="tx"></app-bisq-transfers>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template [ngIf]="isLoadingAddress && !error">
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<table class="table table-borderless table-striped">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><span class="skeleton-loader"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><span class="skeleton-loader"></span></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><span class="skeleton-loader"></span></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="w-100 d-block d-md-none"></div>
|
||||||
|
<div class="col">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<ng-template [ngIf]="error">
|
||||||
|
<div class="text-center">
|
||||||
|
Error loading address data.
|
||||||
|
<br>
|
||||||
|
<i>{{ error.error }}</i>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
@ -0,0 +1,23 @@
|
|||||||
|
.qr-wrapper {
|
||||||
|
background-color: #FFF;
|
||||||
|
padding: 10px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 576px) {
|
||||||
|
.qrcode-col {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width: 575.98px) {
|
||||||
|
.qrcode-col {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qrcode-col > div {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
}
|
82
frontend/src/app/bisq/bisq-address/bisq-address.component.ts
Normal file
82
frontend/src/app/bisq/bisq-address/bisq-address.component.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||||
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
|
import { switchMap, filter, catchError } from 'rxjs/operators';
|
||||||
|
import { ParamMap, ActivatedRoute } from '@angular/router';
|
||||||
|
import { Subscription, of } from 'rxjs';
|
||||||
|
import { BisqTransaction } from '../bisq.interfaces';
|
||||||
|
import { BisqApiService } from '../bisq-api.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-bisq-address',
|
||||||
|
templateUrl: './bisq-address.component.html',
|
||||||
|
styleUrls: ['./bisq-address.component.scss']
|
||||||
|
})
|
||||||
|
export class BisqAddressComponent implements OnInit, OnDestroy {
|
||||||
|
transactions: BisqTransaction[];
|
||||||
|
addressString: string;
|
||||||
|
isLoadingAddress = true;
|
||||||
|
error: any;
|
||||||
|
mainSubscription: Subscription;
|
||||||
|
|
||||||
|
totalReceived = 0;
|
||||||
|
totalSent = 0;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private seoService: SeoService,
|
||||||
|
private bisqApiService: BisqApiService,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.mainSubscription = this.route.paramMap
|
||||||
|
.pipe(
|
||||||
|
switchMap((params: ParamMap) => {
|
||||||
|
this.error = undefined;
|
||||||
|
this.isLoadingAddress = true;
|
||||||
|
this.transactions = null;
|
||||||
|
document.body.scrollTo(0, 0);
|
||||||
|
this.addressString = params.get('id') || '';
|
||||||
|
this.seoService.setTitle('Address: ' + this.addressString, true);
|
||||||
|
|
||||||
|
return this.bisqApiService.getAddress$(this.addressString)
|
||||||
|
.pipe(
|
||||||
|
catchError((err) => {
|
||||||
|
this.isLoadingAddress = false;
|
||||||
|
this.error = err;
|
||||||
|
console.log(err);
|
||||||
|
return of(null);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
filter((transactions) => transactions !== null)
|
||||||
|
)
|
||||||
|
.subscribe((transactions: BisqTransaction[]) => {
|
||||||
|
this.transactions = transactions;
|
||||||
|
this.updateChainStats();
|
||||||
|
this.isLoadingAddress = false;
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
console.log(error);
|
||||||
|
this.error = error;
|
||||||
|
this.isLoadingAddress = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateChainStats() {
|
||||||
|
const shortenedAddress = this.addressString.substr(1);
|
||||||
|
|
||||||
|
this.totalSent = this.transactions.reduce((acc, tx) =>
|
||||||
|
acc + tx.inputs
|
||||||
|
.filter((input) => input.address === shortenedAddress)
|
||||||
|
.reduce((a, input) => a + input.bsqAmount, 0), 0);
|
||||||
|
|
||||||
|
this.totalReceived = this.transactions.reduce((acc, tx) =>
|
||||||
|
acc + tx.outputs
|
||||||
|
.filter((output) => output.address === shortenedAddress)
|
||||||
|
.reduce((a, output) => a + output.bsqAmount, 0), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.mainSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
@ -30,4 +30,8 @@ export class BisqApiService {
|
|||||||
listBlocks$(start: number, length: number): Observable<HttpResponse<BisqBlock[]>> {
|
listBlocks$(start: number, length: number): Observable<HttpResponse<BisqBlock[]>> {
|
||||||
return this.httpClient.get<BisqBlock[]>(API_BASE_URL + `/bisq/blocks/${start}/${length}`, { observe: 'response' });
|
return this.httpClient.get<BisqBlock[]>(API_BASE_URL + `/bisq/blocks/${start}/${length}`, { observe: 'response' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAddress$(address: string): Observable<BisqTransaction[]> {
|
||||||
|
return this.httpClient.get<BisqTransaction[]>(API_BASE_URL + '/bisq/address/' + address);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div class="container-xl">
|
<div class="container-xl">
|
||||||
|
|
||||||
<div class="title-block">
|
<div class="title-block">
|
||||||
<h1>Block <ng-template [ngIf]="blockHeight"><a [routerLink]="['/block/' | relativeUrl, blockHash]">{{ blockHeight }}</a></ng-template></h1>
|
<h1>Bisq Block <ng-template [ngIf]="blockHeight"><a [routerLink]="['/block/' | relativeUrl, blockHash]">{{ blockHeight }}</a></ng-template></h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { BisqBlockComponent } from './bisq-block.component';
|
|
||||||
|
|
||||||
describe('BisqBlockComponent', () => {
|
|
||||||
let component: BisqBlockComponent;
|
|
||||||
let fixture: ComponentFixture<BisqBlockComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [ BisqBlockComponent ]
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(BisqBlockComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -4,6 +4,7 @@ import { BisqApiService } from '../bisq-api.service';
|
|||||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
import { Subscribable, Subscription, of } from 'rxjs';
|
import { Subscribable, Subscription, of } from 'rxjs';
|
||||||
import { switchMap } from 'rxjs/operators';
|
import { switchMap } from 'rxjs/operators';
|
||||||
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bisq-block',
|
selector: 'app-bisq-block',
|
||||||
@ -21,6 +22,7 @@ export class BisqBlockComponent implements OnInit, OnDestroy {
|
|||||||
constructor(
|
constructor(
|
||||||
private bisqApiService: BisqApiService,
|
private bisqApiService: BisqApiService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
|
private seoService: SeoService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -28,6 +30,7 @@ export class BisqBlockComponent implements OnInit, OnDestroy {
|
|||||||
.pipe(
|
.pipe(
|
||||||
switchMap((params: ParamMap) => {
|
switchMap((params: ParamMap) => {
|
||||||
this.blockHash = params.get('id') || '';
|
this.blockHash = params.get('id') || '';
|
||||||
|
document.body.scrollTo(0, 0);
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
if (history.state.data && history.state.data.blockHeight) {
|
if (history.state.data && history.state.data.blockHeight) {
|
||||||
this.blockHeight = history.state.data.blockHeight;
|
this.blockHeight = history.state.data.blockHeight;
|
||||||
@ -42,6 +45,7 @@ export class BisqBlockComponent implements OnInit, OnDestroy {
|
|||||||
.subscribe((block: BisqBlock) => {
|
.subscribe((block: BisqBlock) => {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
this.blockHeight = block.height;
|
this.blockHeight = block.height;
|
||||||
|
this.seoService.setTitle('Block: #' + block.height + ': ' + block.hash, true);
|
||||||
this.block = block;
|
this.block = block;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="container-xl">
|
<div class="container-xl">
|
||||||
<h2 style="float: left;">BSQ Blocks</h2>
|
<h2 style="float: left;">Bisq Blocks</h2>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
@ -3,6 +3,7 @@ import { BisqApiService } from '../bisq-api.service';
|
|||||||
import { switchMap } from 'rxjs/operators';
|
import { switchMap } from 'rxjs/operators';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { BisqBlock, BisqOutput, BisqTransaction } from '../bisq.interfaces';
|
import { BisqBlock, BisqOutput, BisqTransaction } from '../bisq.interfaces';
|
||||||
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bisq-blocks',
|
selector: 'app-bisq-blocks',
|
||||||
@ -21,9 +22,11 @@ export class BisqBlocksComponent implements OnInit {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private bisqApiService: BisqApiService,
|
private bisqApiService: BisqApiService,
|
||||||
|
private seoService: SeoService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.seoService.setTitle('Blocks', true);
|
||||||
this.itemsPerPage = Math.max(Math.round(this.contentSpace / this.fiveItemsPxSize) * 5, 10);
|
this.itemsPerPage = Math.max(Math.round(this.contentSpace / this.fiveItemsPxSize) * 5, 10);
|
||||||
|
|
||||||
this.pageSubject$
|
this.pageSubject$
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<div class="container-xl">
|
<div class="container-xl">
|
||||||
|
|
||||||
<h1 class="float-left mr-3 mb-md-3">Transaction</h1>
|
<h1 class="float-left mr-3 mb-md-3">Bisq Transaction</h1>
|
||||||
|
|
||||||
<ng-template [ngIf]="!isLoading" [ngIfElse]="isLoadingTmpl">
|
<ng-template [ngIf]="!isLoading" [ngIfElse]="isLoadingTmpl">
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import { of, Observable, Subscription } from 'rxjs';
|
|||||||
import { StateService } from 'src/app/services/state.service';
|
import { StateService } from 'src/app/services/state.service';
|
||||||
import { Block } from 'src/app/interfaces/electrs.interface';
|
import { Block } from 'src/app/interfaces/electrs.interface';
|
||||||
import { BisqApiService } from '../bisq-api.service';
|
import { BisqApiService } from '../bisq-api.service';
|
||||||
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bisq-transaction',
|
selector: 'app-bisq-transaction',
|
||||||
@ -23,13 +24,16 @@ export class BisqTransactionComponent implements OnInit, OnDestroy {
|
|||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private bisqApiService: BisqApiService,
|
private bisqApiService: BisqApiService,
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
|
private seoService: SeoService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.subscription = this.route.paramMap.pipe(
|
this.subscription = this.route.paramMap.pipe(
|
||||||
switchMap((params: ParamMap) => {
|
switchMap((params: ParamMap) => {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
document.body.scrollTo(0, 0);
|
||||||
this.txId = params.get('id') || '';
|
this.txId = params.get('id') || '';
|
||||||
|
this.seoService.setTitle('Transaction: ' + this.txId, true);
|
||||||
if (history.state.data) {
|
if (history.state.data) {
|
||||||
return of(history.state.data);
|
return of(history.state.data);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<div class="container-xl">
|
<div class="container-xl">
|
||||||
<h2 style="float: left;">BSQ Transactions</h2>
|
<h2 style="float: left;">Bisq Transactions</h2>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
@ -3,6 +3,7 @@ import { BisqTransaction, BisqOutput } from '../bisq.interfaces';
|
|||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { switchMap } from 'rxjs/operators';
|
import { switchMap } from 'rxjs/operators';
|
||||||
import { BisqApiService } from '../bisq-api.service';
|
import { BisqApiService } from '../bisq-api.service';
|
||||||
|
import { SeoService } from 'src/app/services/seo.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-bisq-transactions',
|
selector: 'app-bisq-transactions',
|
||||||
@ -21,9 +22,12 @@ export class BisqTransactionsComponent implements OnInit {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private bisqApiService: BisqApiService,
|
private bisqApiService: BisqApiService,
|
||||||
|
private seoService: SeoService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
this.seoService.setTitle('Transactions', true);
|
||||||
|
|
||||||
this.itemsPerPage = Math.max(Math.round(this.contentSpace / this.fiveItemsPxSize) * 5, 10);
|
this.itemsPerPage = Math.max(Math.round(this.contentSpace / this.fiveItemsPxSize) * 5, 10);
|
||||||
|
|
||||||
this.pageSubject$
|
this.pageSubject$
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a [routerLink]="['/address/' | relativeUrl, input.address]" title="{{ input.address }}">
|
<a [routerLink]="['/address/' | relativeUrl, 'B' + input.address]" title="B{{ input.address }}">
|
||||||
<span class="d-block d-lg-none">B{{ input.address | shortenString : 16 }}</span>
|
<span class="d-block d-lg-none">B{{ input.address | shortenString : 16 }}</span>
|
||||||
<span class="d-none d-lg-block">B{{ input.address | shortenString : 35 }}</span>
|
<span class="d-none d-lg-block">B{{ input.address | shortenString : 35 }}</span>
|
||||||
</a>
|
</a>
|
||||||
@ -36,7 +36,7 @@
|
|||||||
<ng-template ngFor let-output [ngForOf]="tx.outputs" [ngForTrackBy]="trackByIndexFn">
|
<ng-template ngFor let-output [ngForOf]="tx.outputs" [ngForTrackBy]="trackByIndexFn">
|
||||||
<tr *ngIf="output.isVerified && output.opReturn === undefined">
|
<tr *ngIf="output.isVerified && output.opReturn === undefined">
|
||||||
<td>
|
<td>
|
||||||
<a [routerLink]="['/address/' | relativeUrl, output.address]" title="{{ output.address }}">
|
<a [routerLink]="['/address/' | relativeUrl, 'B' + output.address]" title="B{{ output.address }}">
|
||||||
<span class="d-block d-lg-none">B{{ output.address | shortenString : 16 }}</span>
|
<span class="d-block d-lg-none">B{{ output.address | shortenString : 16 }}</span>
|
||||||
<span class="d-none d-lg-block">B{{ output.address | shortenString : 35 }}</span>
|
<span class="d-none d-lg-block">B{{ output.address | shortenString : 35 }}</span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -15,6 +15,7 @@ import { faLeaf, faQuestion, faExclamationTriangle, faRocket, faRetweet, faFileA
|
|||||||
import { BisqBlocksComponent } from './bisq-blocks/bisq-blocks.component';
|
import { BisqBlocksComponent } from './bisq-blocks/bisq-blocks.component';
|
||||||
import { BisqExplorerComponent } from './bisq-explorer/bisq-explorer.component';
|
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';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -27,6 +28,7 @@ import { BisqApiService } from './bisq-api.service';
|
|||||||
BisqTransfersComponent,
|
BisqTransfersComponent,
|
||||||
BisqBlocksComponent,
|
BisqBlocksComponent,
|
||||||
BisqExplorerComponent,
|
BisqExplorerComponent,
|
||||||
|
BisqAddressComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
@ -7,6 +7,7 @@ import { BisqTransactionComponent } from './bisq-transaction/bisq-transaction.co
|
|||||||
import { BisqBlockComponent } from './bisq-block/bisq-block.component';
|
import { BisqBlockComponent } from './bisq-block/bisq-block.component';
|
||||||
import { BisqBlocksComponent } from './bisq-blocks/bisq-blocks.component';
|
import { BisqBlocksComponent } from './bisq-blocks/bisq-blocks.component';
|
||||||
import { BisqExplorerComponent } from './bisq-explorer/bisq-explorer.component';
|
import { BisqExplorerComponent } from './bisq-explorer/bisq-explorer.component';
|
||||||
|
import { BisqAddressComponent } from './bisq-address/bisq-address.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -32,7 +33,7 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'address/:id',
|
path: 'address/:id',
|
||||||
component: AddressComponent
|
component: BisqAddressComponent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'about',
|
path: 'about',
|
||||||
|
@ -18,14 +18,9 @@ export class SeoService {
|
|||||||
|
|
||||||
setTitle(newTitle: string, prependNetwork = false) {
|
setTitle(newTitle: string, prependNetwork = false) {
|
||||||
let networkName = '';
|
let networkName = '';
|
||||||
if (prependNetwork) {
|
if (prependNetwork && this.network !== '') {
|
||||||
if (this.network === 'liquid') {
|
networkName = this.network.substr(0, 1).toUpperCase() + this.network.substr(1) + ' ';
|
||||||
networkName = 'Liquid ';
|
|
||||||
} else if (this.network === 'testnet') {
|
|
||||||
networkName = 'Testnet ';
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.titleService.setTitle(networkName + newTitle + ' - ' + this.defaultTitle);
|
this.titleService.setTitle(networkName + newTitle + ' - ' + this.defaultTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import { BytesPipe } from './pipes/bytes-pipe/bytes.pipe';
|
|||||||
import { WuBytesPipe } from './pipes/bytes-pipe/wubytes.pipe';
|
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';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -23,6 +24,7 @@ import { ClipboardComponent } from '../components/clipboard/clipboard.component'
|
|||||||
ShortenStringPipe,
|
ShortenStringPipe,
|
||||||
ClipboardComponent,
|
ClipboardComponent,
|
||||||
TimeSinceComponent,
|
TimeSinceComponent,
|
||||||
|
QrcodeComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
@ -40,7 +42,8 @@ import { ClipboardComponent } from '../components/clipboard/clipboard.component'
|
|||||||
CeilPipe,
|
CeilPipe,
|
||||||
ShortenStringPipe,
|
ShortenStringPipe,
|
||||||
TimeSinceComponent,
|
TimeSinceComponent,
|
||||||
ClipboardComponent
|
ClipboardComponent,
|
||||||
|
QrcodeComponent,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class SharedModule {}
|
export class SharedModule {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user