mirror of
https://github.com/everoddandeven/monerod-gui.git
synced 2025-01-03 09:29:36 +00:00
Add preload fix, blockchain operations implementation
This commit is contained in:
parent
08c2a5a5ee
commit
0d78976e1d
16 changed files with 766 additions and 88 deletions
|
@ -38,7 +38,8 @@
|
|||
],
|
||||
"scripts": [
|
||||
"node_modules/jquery/dist/jquery.min.js",
|
||||
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
|
||||
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
|
||||
"node_modules/bootstrap-table/dist/bootstrap-table.min.js"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss",
|
||||
|
|
10
app/main.ts
10
app/main.ts
|
@ -31,9 +31,11 @@ function createWindow(): BrowserWindow {
|
|||
width: size.width,
|
||||
height: size.height,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
allowRunningInsecureContent: (serve),
|
||||
contextIsolation: false
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
nodeIntegration: false,
|
||||
allowRunningInsecureContent: true,
|
||||
contextIsolation: true,
|
||||
devTools: true
|
||||
},
|
||||
icon: path.join(__dirname, 'assets/icons/favicon.ico')
|
||||
});
|
||||
|
@ -348,7 +350,7 @@ try {
|
|||
}
|
||||
});
|
||||
|
||||
ipcMain.on('start-monerod', (event, configFilePath: string[]) => {
|
||||
ipcMain.handle('start-monerod', (event, configFilePath: string[]) => {
|
||||
startMoneroDaemon(configFilePath);
|
||||
})
|
||||
|
||||
|
|
14
app/preload.js
Normal file
14
app/preload.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
// preload.js
|
||||
const { contextBridge, ipcRenderer } = require('electron');
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
startMonerod: (args) => {
|
||||
ipcRenderer.invoke('start-monerod', args);
|
||||
},
|
||||
onMoneroStdout: (callback) => {
|
||||
ipcRenderer.on('monero-stdout', callback);
|
||||
},
|
||||
onMoneroClose: (callback) => {
|
||||
ipcRenderer.on('monero-close', callback);
|
||||
}
|
||||
});
|
|
@ -106,12 +106,18 @@ export class DaemonService {
|
|||
constructor(private httpClient: HttpClient, private electronService: ElectronService) {
|
||||
this.openDbPromise = this.openDatabase();
|
||||
this.settings = this.loadSettings();
|
||||
const wdw = (window as any);
|
||||
|
||||
if (this.electronService.isElectron) {
|
||||
this.electronService.ipcRenderer.on('monero-close', (event, code: number | null) => {
|
||||
this.onClose();
|
||||
});
|
||||
}
|
||||
else if (wdw.electronAPI && wdw.electronAPI.onMoneroClose) {
|
||||
wdw.electronAPI.onMoneroClose((event: any, code: number) => {
|
||||
this.onClose();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private onClose(): void {
|
||||
|
@ -250,16 +256,22 @@ export class DaemonService {
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
if (!this.electronService.isElectron) {
|
||||
console.error("Could not start monero daemon: not electron app");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
this.starting = true;
|
||||
|
||||
console.log("Starting daemon");
|
||||
const settings = await this.getSettings();
|
||||
this.electronService.ipcRenderer.send('start-monerod', settings.toCommandOptions());
|
||||
|
||||
if (this.electronService.ipcRenderer) this.electronService.ipcRenderer.send('start-monerod', settings.toCommandOptions());
|
||||
else {
|
||||
const wdw = (window as any).electronAPI.startMonerod(settings.toCommandOptions());
|
||||
}
|
||||
|
||||
await this.delay(3000);
|
||||
|
||||
|
@ -348,19 +360,23 @@ export class DaemonService {
|
|||
public async getLastBlockHeader(fillPowHash: boolean = false): Promise<BlockHeader> {
|
||||
const response = await this.callRpc(new GetLastBlockHeaderRequest(fillPowHash));
|
||||
|
||||
return BlockHeader.parse(response.block_header);
|
||||
if (response.result && response.result.status == 'BUSY') {
|
||||
throw new CoreIsBusyError();
|
||||
}
|
||||
|
||||
return BlockHeader.parse(response.result.block_header);
|
||||
}
|
||||
|
||||
public async getBlockHeaderByHash(hash: string, fillPowHash: boolean = false): Promise<BlockHeader> {
|
||||
const response = await this.callRpc(new GetBlockHeaderByHashRequest(hash, fillPowHash));
|
||||
|
||||
return BlockHeader.parse(response.block_header);
|
||||
return BlockHeader.parse(response.result.block_header);
|
||||
}
|
||||
|
||||
public async getBlockHeaderByHeight(height: number, fillPowHash: boolean = false): Promise<BlockHeader> {
|
||||
const response = await this.callRpc(new GetBlockHeaderByHeightRequest(height, fillPowHash));
|
||||
|
||||
return BlockHeader.parse(response.block_header);
|
||||
return BlockHeader.parse(response.result.block_header);
|
||||
}
|
||||
|
||||
public async getBlockHeadersRange(startHeight: number, endHeight: number, fillPowHash: boolean = false): Promise<BlockHeader[]> {
|
||||
|
@ -410,7 +426,11 @@ export class DaemonService {
|
|||
this.raiseRpcError(response.error);
|
||||
}
|
||||
|
||||
const bans: any[] = response.bans;
|
||||
if (!response.result) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const bans: any[] = response.result.bans;
|
||||
const result: Ban[] = [];
|
||||
|
||||
if (bans) bans.forEach((ban: any) => result.push(Ban.parse(ban)));
|
||||
|
@ -691,6 +711,7 @@ export class DaemonService {
|
|||
throw new Error(`Could not stop daemon: ${response.status}`);
|
||||
}
|
||||
|
||||
/*
|
||||
if (this.electronService.isElectron) {
|
||||
return;
|
||||
}
|
||||
|
@ -698,6 +719,7 @@ export class DaemonService {
|
|||
this.daemonRunning = false;
|
||||
this.onDaemonStatusChanged.emit(false);
|
||||
this.onDaemonStopEnd.emit();
|
||||
*/
|
||||
}
|
||||
|
||||
public async setLimit(limitDown: number, limitUp: number): Promise<{ limitDown: number, limitUp: number }> {
|
||||
|
|
|
@ -7,7 +7,7 @@ import { ElectronService } from '../electron/electron.service';
|
|||
export class MoneroInstallerService {
|
||||
constructor(private electronService: ElectronService) {}
|
||||
|
||||
downloadMonero(downloadUrl: string, destination: string): Promise<void> {
|
||||
public downloadMonero(downloadUrl: string, destination: string): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.electronService.ipcRenderer.invoke('download-monero', downloadUrl, destination)
|
||||
.then(() => resolve())
|
||||
|
|
|
@ -1,4 +1,18 @@
|
|||
<table
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">Bans</h1>
|
||||
<div class="btn-toolbar mb-2 mb-md-0">
|
||||
<ul class="nav nav-pills m-3" id="pills-tab" role="tablist">
|
||||
@for(navbarLink of navbarLinks; track navbarLink.name) {
|
||||
<li class="nav-item mr-2" role="presentation">
|
||||
<button [class]="navbarLink.selected ? 'nav-link active btn-sm' : 'nav-link btn-sm'" [id]="navbarLink.id" data-bs-toggle="pill" [attr.data-bs-target]="navbarLink.target" type="button" role="tab" [attr.aria-controls]="navbarLink.controls" [attr.aria-selected]="navbarLink.selected" [disabled]="navbarLink.disabled">{{navbarLink.name}}</button>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div [hidden]="!daemonRunning || daemonChangingStatus">
|
||||
<table
|
||||
id="bansTable"
|
||||
data-toggle="bansTable"
|
||||
data-toolbar="#toolbar"
|
||||
|
@ -11,4 +25,9 @@
|
|||
<th data-field="seconds">Seconds</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<app-daemon-not-running></app-daemon-not-running>
|
||||
<app-daemon-stopping></app-daemon-stopping>
|
|
@ -1,7 +1,9 @@
|
|||
import { AfterViewInit, Component } from '@angular/core';
|
||||
import { AfterViewInit, Component, NgZone } from '@angular/core';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { NavbarService } from '../../shared/components/navbar/navbar.service';
|
||||
import { DaemonService } from '../../core/services/daemon/daemon.service';
|
||||
import { NavbarLink } from '../../shared/components/navbar/navbar.model';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-bans',
|
||||
|
@ -9,14 +11,33 @@ import { DaemonService } from '../../core/services/daemon/daemon.service';
|
|||
styleUrl: './bans.component.scss'
|
||||
})
|
||||
export class BansComponent implements AfterViewInit {
|
||||
public readonly navbarLinks: NavbarLink[] = [
|
||||
new NavbarLink('pills-overview-tab', '#pills-overview', 'pills-overview', true, 'Overview', true),
|
||||
new NavbarLink('pills-set-bans-tab', '#pills-set-bans', 'pills-set-bans', false, 'Set Bans', true)
|
||||
];
|
||||
public daemonRunning: boolean = false;
|
||||
public get daemonChangingStatus(): boolean {
|
||||
return this.daemonService.stopping || this.daemonService.starting;
|
||||
}
|
||||
|
||||
constructor(private router: Router, private daemonService: DaemonService, private navbarService: NavbarService) {
|
||||
constructor(private router: Router, private daemonService: DaemonService, private navbarService: NavbarService, private ngZone: NgZone) {
|
||||
this.router.events.subscribe((event) => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
if (event.url != '/bans') return;
|
||||
this.onNavigationEnd();
|
||||
}
|
||||
})
|
||||
|
||||
this.daemonService.isRunning().then((running) => {
|
||||
this.daemonRunning = running
|
||||
});
|
||||
|
||||
this.daemonService.onDaemonStatusChanged.subscribe((running: boolean) => {
|
||||
this.daemonRunning = running;
|
||||
|
||||
if (running) this.load();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
|
@ -24,15 +45,21 @@ export class BansComponent implements AfterViewInit {
|
|||
|
||||
console.log('BansComponent AFTER VIEW INIT');
|
||||
|
||||
setTimeout(() => {
|
||||
this.ngZone.run(() => {
|
||||
//const $ = require('jquery');
|
||||
//const bootstrapTable = require('bootstrap-table');
|
||||
|
||||
const $table = $('#bansTable');
|
||||
$table.bootstrapTable({});
|
||||
$table.bootstrapTable({
|
||||
|
||||
});
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
$table.bootstrapTable('showLoading');
|
||||
this.load();
|
||||
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
|
||||
private onNavigationEnd(): void {
|
||||
|
@ -50,9 +77,13 @@ export class BansComponent implements AfterViewInit {
|
|||
'host': ban.host,
|
||||
'seconds': ban.seconds
|
||||
}));
|
||||
|
||||
$table.bootstrapTable('hideLoading');
|
||||
$table.bootstrapTable('load', bans);
|
||||
|
||||
}
|
||||
|
||||
public async setBans() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,449 @@
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="daemonRunning" class="tab-content" id="pills-tabContent">
|
||||
|
||||
<div class="tab-pane fade show active" id="pills-last-block-header" role="tabpanel" aria-labelledby="pills-last-block-header-tab" tabindex="0">
|
||||
<div *ngIf="getLastBlockError != ''" class="alert alert-danger d-flex align-items-center justify-content-center text-center" role="alert">
|
||||
<h4><i class="bi bi-exclamation-triangle m-2"></i></h4>
|
||||
<div>
|
||||
{{getLastBlockError}}
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="getLastBlockError == ''" class="card p-1">
|
||||
<div class="card-header bg-primary text-white d-flex">
|
||||
<h4>Block Header Details</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if(lastBlockHeader) {
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6>Block Information</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><strong>Block Size:</strong> {{ lastBlockHeader.blockSize }} bytes</li>
|
||||
<li class="list-group-item"><strong>Block Weight:</strong> {{ lastBlockHeader.blockWeight }} units</li>
|
||||
<li class="list-group-item"><strong>Height:</strong> {{ lastBlockHeader.height }}</li>
|
||||
<li class="list-group-item"><strong>Major Version:</strong> {{ lastBlockHeader.majorVersion }}</li>
|
||||
<li class="list-group-item"><strong>Minor Version:</strong> {{ lastBlockHeader.minorVersion }}</li>
|
||||
<li class="list-group-item"><strong>Nonce:</strong> {{ lastBlockHeader.nonce }}</li>
|
||||
<li class="list-group-item"><strong>Number of Transactions:</strong> {{ lastBlockHeader.numTxes }}</li>
|
||||
<li class="list-group-item"><strong>Reward:</strong> {{ lastBlockHeader.reward }} XMR</li>
|
||||
<li class="list-group-item"><strong>Timestamp:</strong> {{ lastBlockHeader.timestamp | date:'medium' }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6>Hashes & Difficulty</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><strong>Block Hash:</strong> {{ lastBlockHeader.hash }}</li>
|
||||
<li class="list-group-item"><strong>Previous Hash:</strong> {{ lastBlockHeader.prevHash }}</li>
|
||||
<li class="list-group-item"><strong>PoW Hash:</strong> {{ lastBlockHeader.powHash }}</li>
|
||||
<li class="list-group-item"><strong>Miner Transaction Hash:</strong> {{ lastBlockHeader.minerTxHash }}</li>
|
||||
<li class="list-group-item"><strong>Cumulative Difficulty:</strong> {{ lastBlockHeader.cumulativeDifficulty }}</li>
|
||||
<li class="list-group-item"><strong>Wide Cumulative Difficulty:</strong> {{ lastBlockHeader.wideCumulativeDifficulty }}</li>
|
||||
<li class="list-group-item"><strong>Difficulty:</strong> {{ lastBlockHeader.difficulty }}</li>
|
||||
<li class="list-group-item"><strong>Wide Difficulty:</strong> {{ lastBlockHeader.wideDifficulty }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<h6>Miscellaneous</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><strong>Orphan Status:</strong> {{ lastBlockHeader.orphanStatus ? 'Yes' : 'No' }}</li>
|
||||
<li class="list-group-item"><strong>Depth:</strong> {{ lastBlockHeader.depth }}</li>
|
||||
<li class="list-group-item"><strong>Long Term Weight:</strong> {{ lastBlockHeader.longTermWeight }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@else {
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6>Block Information</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6>Hashes & Difficulty</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<h6>Miscellaneous</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-get-block" role="tabpanel" aria-labelledby="pills-get-block-tab" tabindex="0">
|
||||
<div *ngIf="getBlockError != ''" class="alert alert-danger d-flex align-items-center justify-content-center text-center" role="alert">
|
||||
<h4><i class="bi bi-exclamation-triangle m-2"></i></h4>
|
||||
<div>
|
||||
{{getBlockError}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="block" class="card">
|
||||
<div class="card-header bg-dark text-white">
|
||||
<h4>Block Details</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Placeholder mentre i dati sono in caricamento -->
|
||||
<ng-container *ngIf="block && !gettingLastBlock; else loading">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h6>Block Blob</h6>
|
||||
<p class="text-break bg-dark p-2">{{ block.blob }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dettagli del BlockHeader -->
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<h6>Block Header</h6>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><strong>Block Size:</strong> {{ block.blockHeader.blockSize }} bytes</li>
|
||||
<li class="list-group-item"><strong>Block Weight:</strong> {{ block.blockHeader.blockWeight }} units</li>
|
||||
<li class="list-group-item"><strong>Height:</strong> {{ block.blockHeader.height }}</li>
|
||||
<li class="list-group-item"><strong>Hash:</strong> {{ block.blockHeader.hash }}</li>
|
||||
<li class="list-group-item"><strong>Previous Hash:</strong> {{ block.blockHeader.prevHash }}</li>
|
||||
<li class="list-group-item"><strong>Miner Transaction Hash:</strong> {{ block.blockHeader.minerTxHash }}</li>
|
||||
<li class="list-group-item"><strong>Difficulty:</strong> {{ block.blockHeader.difficulty }}</li>
|
||||
<li class="list-group-item"><strong>Timestamp:</strong> {{ block.blockHeader.timestamp | date:'medium' }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dettagli del BlockDetails -->
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<h6>Block Additional Details</h6>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><strong>Major Version:</strong> {{ block.details.majorVersion }}</li>
|
||||
<li class="list-group-item"><strong>Minor Version:</strong> {{ block.details.minorVersion }}</li>
|
||||
<li class="list-group-item"><strong>Timestamp:</strong> {{ block.details.timestamp | date:'medium' }}</li>
|
||||
<li class="list-group-item"><strong>Previous ID:</strong> {{ block.details.prevId }}</li>
|
||||
<li class="list-group-item"><strong>Nonce:</strong> {{ block.details.nonce }}</li>
|
||||
<li class="list-group-item"><strong>Transaction Hashes:</strong>
|
||||
<ul>
|
||||
<li *ngFor="let hash of block.details.txHashes">{{ hash }}</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Placeholder di caricamento -->
|
||||
<ng-template #loading>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h6>Block Blob</h6>
|
||||
<p class="placeholder-glow bg-light p-2"><span class="placeholder col-8"></span></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<h6>Block Header</h6>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item placeholder-glow"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder-glow"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder-glow"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder-glow"><span class="placeholder col-6"></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<h6>Block Additional Details</h6>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item placeholder-glow"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder-glow"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder-glow"><span class="placeholder col-6"></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr *ngIf="block" class="my-4">
|
||||
|
||||
<div class="row g-5 p-2">
|
||||
<div class="cold-md-7 col-lg-12">
|
||||
<div class="row gy-3">
|
||||
<div class="form-check form-switch col-md-6">
|
||||
<label for="get-block-by-hash" class="form-check-label">Look up by hash</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="get-block-by-hash" [checked]="getBlockByHash" [(ngModel)]="getBlockByHash" [ngModelOptions]="{standalone: true}">
|
||||
<br>
|
||||
<small class="text-body-secondary">Get block information by hash</small>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch col-md-6">
|
||||
<label for="fill-pow-hash" class="form-check-label">Fill PoW hash</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="fill-pow-hash" [checked]="fillPoWHash" [(ngModel)]="fillPoWHash" [ngModelOptions]="{standalone: true}">
|
||||
<br>
|
||||
<small class="text-body-secondary">Add PoW hash to block header response</small>
|
||||
</div>
|
||||
|
||||
<div *ngIf="getBlockByHash" class="col-sm-6">
|
||||
<label for="get-block-hash" class="form-label">Block hash</label>
|
||||
<input type="text" class="form-control" id="get-block-hash" placeholder="" [(ngModel)]="getBlockHash" [ngModelOptions]="{standalone: true}" [disabled]="!getBlockByHash">
|
||||
<small class="text-body-secondary">Block hash</small>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!getBlockByHash" class="col-sm-3">
|
||||
<label for="get-block-height" class="form-label">Block height</label>
|
||||
<input type="number" class="form-control" id="get-block-height" placeholder="" [(ngModel)]="getBlockHeight" [ngModelOptions]="{standalone: true}" [disabled]="getBlockByHash">
|
||||
<small class="text-body-secondary">Block height</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<button *ngIf="!gettingLastBlock" class="w-100 btn btn-primary btn-lg" type="button" (click)="getBlock()">Get Block</button>
|
||||
<button *ngIf="gettingLastBlock" class="w-100 btn btn-primary btn-lg" type="button" disabled>Getting Block ...</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-get-block-header" role="tabpanel" aria-labelledby="pills-get-block-header-tab" tabindex="0">
|
||||
<div *ngIf="blockHeader" class="card p-1">
|
||||
<div class="card-header bg-primary text-white d-flex">
|
||||
<h4>Block Header Details</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if(blockHeader) {
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6>Block Information</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><strong>Block Size:</strong> {{ blockHeader.blockSize }} bytes</li>
|
||||
<li class="list-group-item"><strong>Block Weight:</strong> {{ blockHeader.blockWeight }} units</li>
|
||||
<li class="list-group-item"><strong>Height:</strong> {{ blockHeader.height }}</li>
|
||||
<li class="list-group-item"><strong>Major Version:</strong> {{ blockHeader.majorVersion }}</li>
|
||||
<li class="list-group-item"><strong>Minor Version:</strong> {{ blockHeader.minorVersion }}</li>
|
||||
<li class="list-group-item"><strong>Nonce:</strong> {{ blockHeader.nonce }}</li>
|
||||
<li class="list-group-item"><strong>Number of Transactions:</strong> {{ blockHeader.numTxes }}</li>
|
||||
<li class="list-group-item"><strong>Reward:</strong> {{ blockHeader.reward }} XMR</li>
|
||||
<li class="list-group-item"><strong>Timestamp:</strong> {{ blockHeader.timestamp | date:'medium' }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6>Hashes & Difficulty</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><strong>Block Hash:</strong> {{ blockHeader.hash }}</li>
|
||||
<li class="list-group-item"><strong>Previous Hash:</strong> {{ blockHeader.prevHash }}</li>
|
||||
<li class="list-group-item"><strong>PoW Hash:</strong> {{ blockHeader.powHash }}</li>
|
||||
<li class="list-group-item"><strong>Miner Transaction Hash:</strong> {{ blockHeader.minerTxHash }}</li>
|
||||
<li class="list-group-item"><strong>Cumulative Difficulty:</strong> {{ blockHeader.cumulativeDifficulty }}</li>
|
||||
<li class="list-group-item"><strong>Wide Cumulative Difficulty:</strong> {{ blockHeader.wideCumulativeDifficulty }}</li>
|
||||
<li class="list-group-item"><strong>Difficulty:</strong> {{ blockHeader.difficulty }}</li>
|
||||
<li class="list-group-item"><strong>Wide Difficulty:</strong> {{ blockHeader.wideDifficulty }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<h6>Miscellaneous</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><strong>Orphan Status:</strong> {{ blockHeader.orphanStatus ? 'Yes' : 'No' }}</li>
|
||||
<li class="list-group-item"><strong>Depth:</strong> {{ blockHeader.depth }}</li>
|
||||
<li class="list-group-item"><strong>Long Term Weight:</strong> {{ blockHeader.longTermWeight }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@else {
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6>Block Information</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6>Hashes & Difficulty</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-12">
|
||||
<h6>Miscellaneous</h6>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
<li class="list-group-item placeholder col-7"><span class="placeholder col-6"></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr *ngIf="blockHeader" class="my-4">
|
||||
|
||||
<div class="row g-5 p-2">
|
||||
<div class="cold-md-7 col-lg-12">
|
||||
<div class="row gy-3">
|
||||
<div class="form-check form-switch col-md-6">
|
||||
<label for="get-block-header-by-hash" class="form-check-label">Look up by hash</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="get-block-header-by-hash" [checked]="getBlockHeaderByHash" [(ngModel)]="getBlockHeaderByHash" [ngModelOptions]="{standalone: true}">
|
||||
<br>
|
||||
<small class="text-body-secondary">Get block header information by hash</small>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch col-md-6">
|
||||
<label for="fill-pow-hash" class="form-check-label">Fill PoW hash</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="fill-pow-hash" [checked]="fillPoWHash" [(ngModel)]="fillPoWHash" [ngModelOptions]="{standalone: true}">
|
||||
<br>
|
||||
<small class="text-body-secondary">Add PoW hash to block header response</small>
|
||||
</div>
|
||||
|
||||
<div *ngIf="getBlockHeaderByHash" class="col-sm-6">
|
||||
<label for="get-block-header-hash" class="form-label">Block header hash</label>
|
||||
<input type="text" class="form-control" id="get-block-header-hash" placeholder="" [(ngModel)]="getBlockHeaderHash" [ngModelOptions]="{standalone: true}" [disabled]="!getBlockHeaderByHash">
|
||||
<small class="text-body-secondary">Block header hash</small>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!getBlockHeaderByHash" class="col-sm-3">
|
||||
<label for="get-block-header-height" class="form-label">Block header height</label>
|
||||
<input type="number" class="form-control" id="get-block-header-height" placeholder="" [(ngModel)]="getBlockHeaderHeight" [ngModelOptions]="{standalone: true}" [disabled]="getBlockHeaderByHash">
|
||||
<small class="text-body-secondary">Block header height</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<button *ngIf="!gettingBlockHeader" class="w-100 btn btn-primary btn-lg" type="button" (click)="getBlockHeader()">Get Block Header</button>
|
||||
<button *ngIf="gettingBlockHeader" class="w-100 btn btn-primary btn-lg" type="button" disabled>Getting Block Header ...</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-pop-blocks" role="tabpanel" aria-labelledby="pills-pop-blocks-tab" tabindex="0">
|
||||
<div *ngIf="popBlocksError != ''" class="alert alert-danger d-flex align-items-center justify-content-center text-center" role="alert">
|
||||
<h4><i class="bi bi-exclamation-triangle m-2"></i></h4>
|
||||
<div>
|
||||
{{popBlocksError}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="popBlocksResult != undefined" class="alert alert-success d-flex align-items-center justify-content-center text-center" role="alert">
|
||||
<h4><i class="bi bi-check-circle m-2"></i></h4>
|
||||
<div>
|
||||
New blockchain height: {{popBlocksResult}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-5 p-2">
|
||||
<div class="cold-md-7 col-lg-12">
|
||||
<div class="row gy-3">
|
||||
|
||||
<div class="col-sm-6">
|
||||
<label for="pop-blocks-nblocks" class="form-label">Blocks to pop</label>
|
||||
<input type="number" class="form-control" id="pop-blocks-nblocks" placeholder="" [(ngModel)]="popBlocksNBlocks" [ngModelOptions]="{standalone: true}" [disabled]="getBlockHeaderByHash">
|
||||
<small class="text-body-secondary">Number of blocks top pop from blockchain</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<button *ngIf="!poppingBlocks" class="w-100 btn btn-primary btn-lg" type="button" (click)="popBlocks()">Pop Blocks</button>
|
||||
<button *ngIf="poppingBlocks" class="w-100 btn btn-primary btn-lg" type="button" disabled>Popping Blocks ...</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="tab-pane fade" id="pills-save-bc" role="tabpanel" aria-labelledby="pills-save-bc-tab" tabindex="0">
|
||||
<div *ngIf="saveBlockchainError != ''" class="alert alert-danger d-flex align-items-center justify-content-center text-center" role="alert">
|
||||
<h4><i class="bi bi-exclamation-triangle m-2"></i></h4>
|
||||
<div>
|
||||
{{saveBlockchainError}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="blockchainSaved" class="alert alert-success d-flex align-items-center justify-content-center text-center" role="alert">
|
||||
<h4><i class="bi bi-check-circle m-2"></i></h4>
|
||||
<div>
|
||||
Successfully saved blockchain
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info d-flex text-center" role="alert">
|
||||
<div>
|
||||
The blockchain does not need saving and is always saved when modified, however it does a sync to flush the filesystem cache onto the disk for safety purposes against Operating System or Hardware crashes.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<button *ngIf="!savingBlockchain" class="w-100 btn btn-primary btn-lg" type="button" (click)="saveBlockchain()">Save Blockchain</button>
|
||||
<button *ngIf="savingBlockchain" class="w-100 btn btn-primary btn-lg" type="button" disabled>Saving Blockchain ...</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<app-daemon-not-running></app-daemon-not-running>
|
||||
<app-daemon-stopping></app-daemon-stopping>
|
|
@ -0,0 +1,8 @@
|
|||
.card-header {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.placeholder-glow .placeholder {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
|
@ -1,38 +1,151 @@
|
|||
import { Component, NgZone } from '@angular/core';
|
||||
import { AfterViewInit, Component, NgZone } from '@angular/core';
|
||||
import { NavbarLink } from '../../shared/components/navbar/navbar.model';
|
||||
import { DaemonService } from '../../core/services/daemon/daemon.service';
|
||||
import { Block, BlockHeader } from '../../../common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-blockchain',
|
||||
templateUrl: './blockchain.component.html',
|
||||
styleUrl: './blockchain.component.scss'
|
||||
})
|
||||
export class BlockchainComponent {
|
||||
export class BlockchainComponent implements AfterViewInit {
|
||||
public readonly navbarLinks: NavbarLink[];
|
||||
public daemonRunning: boolean = false;
|
||||
public lastBlockHeader?: BlockHeader;
|
||||
public getLastBlockError: string = '';
|
||||
public block?: Block;
|
||||
public getBlockByHash: boolean = false;
|
||||
public getBlockHash: string = '';
|
||||
public getBlockHeight: number = 0;
|
||||
public fillPoWHash: boolean = false;
|
||||
public gettingLastBlock: boolean = false;
|
||||
|
||||
public gettingBlock: boolean = false;
|
||||
public blockHeader?: BlockHeader;
|
||||
public getBlockHeaderByHash: boolean = false;
|
||||
public getBlockHeaderHash: string = '';
|
||||
public getBlockHeaderHeight: number = 0;
|
||||
|
||||
public getBlockHeaderError: string = '';
|
||||
public getBlockError: string = '';
|
||||
public gettingBlockHeader: boolean = false;
|
||||
|
||||
public popBlocksNBlocks: number = 0;
|
||||
public poppingBlocks: boolean = false;
|
||||
public popBlocksError: string = '';
|
||||
public popBlocksResult?: number;
|
||||
|
||||
public savingBlockchain: boolean = false;
|
||||
public saveBlockchainError: string = '';
|
||||
public blockchainSaved: boolean = false;
|
||||
|
||||
constructor(private daemonService: DaemonService, private ngZone: NgZone) {
|
||||
this.navbarLinks = [
|
||||
new NavbarLink('pills-last-block-header-tab', '#pills-last-block-header', 'pills-last-block-header', false, 'Last Block Header', true),
|
||||
new NavbarLink('pills-last-block-header-tab', '#pills-last-block-header', 'pills-last-block-header', true, 'Last Block Header', true),
|
||||
new NavbarLink('pills-get-block-tab', '#pills-get-block', 'pills-get-block', false, 'Get Block', true),
|
||||
new NavbarLink('pills-get-block-header-tab', '#pills-get-block-header', 'pills-get-block-header', false, 'Get Block Header', true),
|
||||
new NavbarLink('pills-pop-blocks-tab', '#pills-pop-blocks', 'pills-pop-blocks', false, 'Pop Blocks', true),
|
||||
new NavbarLink('pills-save-bc-tab', '#pills-save-bc', 'pills-save-bc', false, 'Save Blockchain', true)
|
||||
]
|
||||
|
||||
this.daemonService.isRunning().then((result: boolean) => this.daemonRunning = result);
|
||||
];
|
||||
|
||||
this.daemonService.onDaemonStatusChanged.subscribe((running) => {
|
||||
this.ngZone.run(() => {
|
||||
this.daemonRunning = running;
|
||||
this.navbarLinks.forEach((link) => link.disabled = !running);
|
||||
});
|
||||
});
|
||||
|
||||
this.daemonService.isRunning().then((value: boolean) => {
|
||||
this.ngZone.run(() => {
|
||||
this.daemonRunning = value;
|
||||
this.navbarLinks.forEach((link) => link.disabled = !value);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.load();
|
||||
}
|
||||
|
||||
public async load(): Promise<void> {
|
||||
await this.getLastBlockHeader();
|
||||
}
|
||||
|
||||
private async getLastBlockHeader(): Promise<void> {
|
||||
this.gettingLastBlock = true;
|
||||
try {
|
||||
this.lastBlockHeader = await this.daemonService.getLastBlockHeader(true);
|
||||
this.getLastBlockError = '';
|
||||
}
|
||||
catch(error) {
|
||||
console.error(error);
|
||||
this.getLastBlockError = `${error}`;
|
||||
}
|
||||
this.gettingLastBlock = false;
|
||||
}
|
||||
|
||||
public async getBlock(): Promise<void> {
|
||||
this.gettingLastBlock = true;
|
||||
try {
|
||||
this.block = await this.daemonService.getBlock(this.getBlockByHash ? this.getBlockHash : this.getBlockHeight, this.fillPoWHash);
|
||||
this.getBlockError = '';
|
||||
}
|
||||
catch(error) {
|
||||
console.error(error);
|
||||
this.getBlockError = `${error}`;
|
||||
}
|
||||
|
||||
this.gettingLastBlock = false;
|
||||
|
||||
}
|
||||
|
||||
public async getBlockHeader(): Promise<void> {
|
||||
this.gettingBlockHeader = true;
|
||||
|
||||
try {
|
||||
if (this.getBlockHeaderByHash) {
|
||||
this.blockHeader = await this.daemonService.getBlockHeaderByHash(this.getBlockHeaderHash, this.fillPoWHash);
|
||||
}
|
||||
else {
|
||||
this.blockHeader = await this.daemonService.getBlockHeaderByHeight(this.getBlockHeaderHeight, this.fillPoWHash);
|
||||
}
|
||||
|
||||
this.getBlockHeaderError = '';
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
this.getBlockHeaderError = `${error}`;
|
||||
}
|
||||
|
||||
this.gettingBlockHeader = false;
|
||||
}
|
||||
|
||||
public async popBlocks(): Promise<void> {
|
||||
this.poppingBlocks = true;
|
||||
try {
|
||||
this.popBlocksResult = await this.daemonService.popBlocks(this.popBlocksNBlocks);
|
||||
this.popBlocksError = '';
|
||||
}
|
||||
catch(error) {
|
||||
console.error(error);
|
||||
this.popBlocksResult = undefined;
|
||||
this.popBlocksError = `${error}`;
|
||||
}
|
||||
this.poppingBlocks = false;
|
||||
}
|
||||
|
||||
public async saveBlockchain(): Promise<void> {
|
||||
this.savingBlockchain = true;
|
||||
|
||||
try {
|
||||
await this.daemonService.saveBc();
|
||||
this.blockchainSaved = true;
|
||||
}
|
||||
catch(error) {
|
||||
console.error(error);
|
||||
this.blockchainSaved = false;
|
||||
this.saveBlockchainError = `${error}`;
|
||||
}
|
||||
|
||||
this.savingBlockchain = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,7 @@ import { NavbarService } from '../../shared/components/navbar/navbar.service';
|
|||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { DaemonInfo } from '../../../common/DaemonInfo';
|
||||
|
||||
import * as $ from 'jquery';
|
||||
import * as bootstrapTable from 'bootstrap-table';
|
||||
|
||||
import { LogsService } from '../logs/logs.service';
|
||||
import { ElectronService } from '../../core/services';
|
||||
|
||||
|
@ -75,7 +74,7 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
this.nodeType = 'unknown';
|
||||
this.blockchainSize = '0 GB';
|
||||
this.syncProgress = '0 %';
|
||||
this.isLoading = true;
|
||||
this.isLoading = false;
|
||||
|
||||
this.navbarLinks = [
|
||||
new NavbarLink('pills-home-tab', '#pills-home', 'pills-home', true, 'Overview', true),
|
||||
|
@ -104,17 +103,37 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
|
||||
ngOnInit(): void {
|
||||
console.log('DetailComponent INIT');
|
||||
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
console.log('DetailComponent AFTER VIEW INIT');
|
||||
this.navbarService.setLinks(this.navbarLinks);
|
||||
setTimeout(() => {
|
||||
this.ngZone.run(() => {
|
||||
|
||||
const $table = $('#table');
|
||||
$table.bootstrapTable({});
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
$table.bootstrapTable('showLoading');
|
||||
/*
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
*/
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
|
||||
if (this.loadInterval != null) return;
|
||||
|
||||
this.ngZone.run(() => {
|
||||
this.load().then(() => {
|
||||
this.cards = this.createCards();
|
||||
});
|
||||
});
|
||||
|
||||
this.loadInterval = setInterval(() => {
|
||||
/*
|
||||
|
@ -124,13 +143,17 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
*/
|
||||
|
||||
if (this.stoppingDaemon) return;
|
||||
|
||||
this.ngZone.run(() => {
|
||||
|
||||
this.load().then(() => {
|
||||
this.cards = this.createCards();
|
||||
});
|
||||
}, 5000);
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
|
@ -190,13 +213,6 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
if(!this.electronService.isElectron) this.stoppingDaemon = false;
|
||||
}
|
||||
|
||||
private onNavigationEnd(): void {
|
||||
this.load().then(() => {
|
||||
//this.cards = this.createCards();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private createLoadingCards(): Card[] {
|
||||
return [
|
||||
new Card('Connection Status', this.connectionStatus, true),
|
||||
|
@ -238,6 +254,10 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
}
|
||||
|
||||
private async load(): Promise<void> {
|
||||
if (this.isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.isLoading = true;
|
||||
this.daemonRunning = await this.daemonService.isRunning();
|
||||
|
@ -251,6 +271,11 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
this.navbarService.enableLinks();
|
||||
|
||||
const $table = $('#table');
|
||||
$table.bootstrapTable({});
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
if (this.getPeers().length == 0) $table.bootstrapTable('showLoading');
|
||||
|
||||
this.syncInfo = await this.daemonService.syncInfo();
|
||||
this.height = this.syncInfo.height;
|
||||
|
@ -293,6 +318,8 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
//const blockchainPruned = false;
|
||||
this.nodeType = blockchainPruned ? 'pruned' : 'full';
|
||||
$table.bootstrapTable('load', this.getPeers());
|
||||
$table.bootstrapTable('hideLoading');
|
||||
|
||||
}
|
||||
catch(error) {
|
||||
console.error(error);
|
||||
|
|
|
@ -19,6 +19,7 @@ export class LogsComponent implements AfterViewInit {
|
|||
}
|
||||
|
||||
private scrollToBottom(): void {
|
||||
this.ngZone.run(() => {
|
||||
this.lines;
|
||||
const terminalOutput = <HTMLDivElement | null>document.getElementById('terminalOutput');
|
||||
if (terminalOutput) {
|
||||
|
@ -26,16 +27,14 @@ export class LogsComponent implements AfterViewInit {
|
|||
console.log(`scrolling from ${terminalOutput.offsetTop} to ${terminalOutput.scrollHeight}`)
|
||||
terminalOutput.scrollBy(0, terminalOutput.scrollHeight)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private onLog(): void {
|
||||
if (this.logTerminal) this.logTerminal.nativeElement.scrollTop = this.logTerminal.nativeElement.scrollHeight;
|
||||
// Scorri automaticamente in basso
|
||||
setTimeout(() => {
|
||||
this.ngZone.run(() => {
|
||||
this.scrollToBottom();
|
||||
})
|
||||
|
||||
}, 100);
|
||||
}
|
||||
|
||||
|
@ -45,6 +44,8 @@ export class LogsComponent implements AfterViewInit {
|
|||
|
||||
ngAfterViewInit(): void {
|
||||
this.navbarService.removeLinks();
|
||||
|
||||
setTimeout(() => {
|
||||
this.scrollToBottom();
|
||||
}
|
||||
}, 500); }
|
||||
}
|
||||
|
|
|
@ -11,10 +11,16 @@ export class LogsService {
|
|||
private readonly ansiRegex: RegExp = /\u001b\[[0-9;]*m/g;
|
||||
|
||||
constructor(private electronService: ElectronService, private ngZone: NgZone) {
|
||||
const wdw = (window as any);
|
||||
if (this.electronService.isElectron) {
|
||||
this.electronService.ipcRenderer.on('monero-stdout', (event, message: string) => this.log(message));
|
||||
this.electronService.ipcRenderer.on('monero-stderr', (event, message: string) => this.log(message));
|
||||
}
|
||||
else if (wdw.electronAPI && wdw.electronAPI.onMoneroStdout) {
|
||||
wdw.electronAPI.onMoneroStdout((event: any, message: string) => {
|
||||
this.log(message);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
},
|
||||
*/
|
||||
|
||||
import { ThisReceiver } from "@angular/compiler";
|
||||
|
||||
export class BlockHeader {
|
||||
public readonly blockSize: number;
|
||||
public readonly blockWeight: number;
|
||||
|
|
|
@ -4,9 +4,9 @@ export class MinerTx {
|
|||
public readonly vin: TxInput[];
|
||||
public readonly vout: TxOutput[];
|
||||
public readonly extra: number[];
|
||||
public readonly rctSignatures: RctSignatures;
|
||||
public readonly rctSignatures?: RctSignatures;
|
||||
|
||||
constructor(version: number, unlockTime: number, vin: TxInput[], vout: TxOutput[], extra: number[], rctSignatures: RctSignatures) {
|
||||
constructor(version: number, unlockTime: number, vin: TxInput[], vout: TxOutput[], extra: number[], rctSignatures?: RctSignatures) {
|
||||
this.version = version;
|
||||
this.unlockTime = unlockTime;
|
||||
this.vin = vin;
|
||||
|
@ -21,7 +21,11 @@ export class MinerTx {
|
|||
const _vin: any[] | undefined = minerTx.vin;
|
||||
const _vout: any[] | undefined = minerTx.vout;
|
||||
const extra = minerTx.extra;
|
||||
const rctSignatures = RctSignatures.parse(minerTx.rct_signatures);
|
||||
let rctSignatures;
|
||||
|
||||
if (minerTx.rct_signatures) {
|
||||
rctSignatures = RctSignatures.parse(minerTx.rct_signatures);
|
||||
}
|
||||
|
||||
const vin: TxInput[] = [];
|
||||
const vout: TxOutput[] = [];
|
||||
|
@ -93,33 +97,20 @@ export class RctSignatures {
|
|||
}
|
||||
|
||||
export class TxOutputTarget {
|
||||
public readonly taggedKey: TaggedKey;
|
||||
|
||||
constructor(taggedKey: TaggedKey)
|
||||
{
|
||||
this.taggedKey = taggedKey;
|
||||
}
|
||||
|
||||
public static parse(target: any): TxOutputTarget {
|
||||
const taggedKey = TaggedKey.parse(target.tagged_key);
|
||||
|
||||
return new TxOutputTarget(taggedKey);
|
||||
}
|
||||
}
|
||||
|
||||
export class TaggedKey {
|
||||
public readonly key: string;
|
||||
public readonly viewKey: string;
|
||||
public readonly viewTag: string;
|
||||
|
||||
constructor(key: string, viewTag: string) {
|
||||
this.key = key;
|
||||
constructor(viewKey: string, viewTag: string)
|
||||
{
|
||||
this.viewKey = viewKey;
|
||||
this.viewTag = viewTag;
|
||||
}
|
||||
|
||||
public static parse(taggedKey: any): TaggedKey {
|
||||
const key = taggedKey.key;
|
||||
const viewTag = taggedKey.view_tag;
|
||||
public static parse(target: any): TxOutputTarget {
|
||||
const viewKey = target.view_key ? target.view_key : '';
|
||||
const viewTag = target.view_tag ? target.view_tag : '';
|
||||
|
||||
return new TaggedKey(key, viewTag);
|
||||
return new TxOutputTarget(viewKey, viewTag);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,5 +53,7 @@ import 'zone.js'; // Included with Angular CLI.
|
|||
*/
|
||||
|
||||
import 'jquery';
|
||||
import * as $$ from 'jquery';
|
||||
import * as $ from 'jquery';
|
||||
import 'bootstrap-table';
|
||||
import * as bootstrapTable from 'bootstrap-table';
|
||||
//import 'bootstrap-table';
|
||||
|
|
Loading…
Reference in a new issue