mirror of
https://github.com/everoddandeven/monerod-gui.git
synced 2025-01-08 20:09:44 +00:00
Settings implementation
This commit is contained in:
parent
334a124a4a
commit
80e8a283f4
61 changed files with 1307 additions and 104 deletions
10
angular.json
10
angular.json
|
@ -36,16 +36,16 @@
|
|||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss",
|
||||
"node_modules/bootstrap-icons/font/bootstrap-icons.css",
|
||||
"node_modules/bootstrap-table/dist/bootstrap-table.min.css"
|
||||
],
|
||||
"scripts": [
|
||||
"node_modules/jquery/dist/jquery.min.js",
|
||||
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
|
||||
"node_modules/bootstrap-table/dist/bootstrap-table.js"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss",
|
||||
"node_modules/bootstrap-icons/font/bootstrap-icons.css",
|
||||
"node_modules/bootstrap-table/dist/bootstrap-table.min.css"
|
||||
],
|
||||
"customWebpackConfig": {
|
||||
"path": "./angular.webpack.js",
|
||||
"replaceDuplicatePlugins": true
|
||||
|
|
87
app/main.ts
87
app/main.ts
|
@ -1,7 +1,11 @@
|
|||
import {app, BrowserWindow, screen} from 'electron';
|
||||
import {app, BrowserWindow, ipcMain, screen} from 'electron';
|
||||
import { ChildProcess, ChildProcessWithoutNullStreams, exec, spawn } from 'child_process';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
|
||||
const monerodFilePath: string = "/home/sidney/Documenti/monero-x86_64-linux-gnu-v0.18.3.4/monerod";
|
||||
|
||||
let win: BrowserWindow | null = null;
|
||||
const args = process.argv.slice(1),
|
||||
serve = args.some(val => val === '--serve');
|
||||
|
@ -19,7 +23,7 @@ function createWindow(): BrowserWindow {
|
|||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
allowRunningInsecureContent: (serve),
|
||||
contextIsolation: false,
|
||||
contextIsolation: false
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -53,6 +57,81 @@ function createWindow(): BrowserWindow {
|
|||
return win;
|
||||
}
|
||||
|
||||
function execMoneroDaemon(configFilePath: string): ChildProcess {
|
||||
const monerodPath = path.resolve(__dirname, 'path/to/monerod'); // Percorso del binario di monerod
|
||||
//const command = `"${monerodPath}" --config-file "${configFilePath}"`;
|
||||
const command = `/home/sidney/Documenti/monero-x86_64-linux-gnu-v0.18.3.4/monerod --testnet --fast-block-sync 1 --prune-blockchain --sync-pruned-blocks --confirm-external-bind --max-concurrency 1 --log-level 1 --rpc-access-control-origins=*`;
|
||||
|
||||
const monerodProcess = exec(command, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.error(`Errore durante l'avvio di monerod: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stderr) {
|
||||
console.error(`stderr: ${stderr}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`stdout: ${stdout}`);
|
||||
});
|
||||
|
||||
// Gestisci l'output in tempo reale
|
||||
if (monerodProcess.stdout == null) {
|
||||
throw new Error("No stdout for monero process")
|
||||
}
|
||||
|
||||
if (monerodProcess.stderr == null) {
|
||||
throw new Error("No stderr for monero process");
|
||||
}
|
||||
|
||||
monerodProcess.stdout.on('data', (data) => {
|
||||
console.log(`monerod stdout: ${data}`);
|
||||
});
|
||||
|
||||
monerodProcess.stderr.on('data', (data) => {
|
||||
console.error(`monerod stderr: ${data}`);
|
||||
});
|
||||
|
||||
return monerodProcess;
|
||||
}
|
||||
|
||||
function startMoneroDaemon(configFilePath: string): ChildProcessWithoutNullStreams {
|
||||
const monerodPath = path.resolve(__dirname, monerodFilePath);
|
||||
|
||||
const args = [
|
||||
'--testnet',
|
||||
'--fast-block-sync', '1',
|
||||
'--prune-blockchain',
|
||||
'--sync-pruned-blocks',
|
||||
'--confirm-external-bind',
|
||||
'--max-concurrency', '1',
|
||||
'--log-level', '1',
|
||||
'--rpc-access-control-origins=*'
|
||||
];
|
||||
|
||||
// Avvia il processo usando spawn
|
||||
const monerodProcess = spawn(monerodPath, args);
|
||||
|
||||
// Gestisci l'output di stdout in streaming
|
||||
monerodProcess.stdout.on('data', (data) => {
|
||||
console.log(`monerod stdout: ${data}`);
|
||||
// Puoi anche inviare i log all'interfaccia utente tramite IPC
|
||||
});
|
||||
|
||||
// Gestisci gli errori in stderr
|
||||
monerodProcess.stderr.on('data', (data) => {
|
||||
console.error(`monerod stderr: ${data}`);
|
||||
});
|
||||
|
||||
// Gestisci la chiusura del processo
|
||||
monerodProcess.on('close', (code) => {
|
||||
console.log(`monerod chiuso con codice: ${code}`);
|
||||
});
|
||||
|
||||
return monerodProcess;
|
||||
}
|
||||
|
||||
try {
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
|
@ -77,6 +156,10 @@ try {
|
|||
}
|
||||
});
|
||||
|
||||
ipcMain.on('start-monerod', (event, configFilePath) => {
|
||||
startMoneroDaemon(configFilePath);
|
||||
})
|
||||
|
||||
} catch (e) {
|
||||
// Catch Error
|
||||
// throw e;
|
||||
|
|
|
@ -5,6 +5,7 @@ import { PageNotFoundComponent } from './shared/components';
|
|||
import { HomeRoutingModule } from './home/home-routing.module';
|
||||
import { DetailRoutingModule } from './detail/detail-routing.module';
|
||||
import { HardForkInfoRoutingModule } from './hard-fork-info/hard-fork-info-routing.module';
|
||||
import { SettingsModule } from './settings/settings.module';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
|
@ -23,7 +24,8 @@ const routes: Routes = [
|
|||
RouterModule.forRoot(routes, {}),
|
||||
HomeRoutingModule,
|
||||
DetailRoutingModule,
|
||||
HardForkInfoRoutingModule
|
||||
HardForkInfoRoutingModule,
|
||||
SettingsModule
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
|
|
|
@ -16,6 +16,7 @@ import { DetailModule } from './detail/detail.module';
|
|||
|
||||
import { AppComponent } from './app.component';
|
||||
import { SidebarComponent } from "./sidebar/sidebar.component";
|
||||
import { LoadComponent } from "./load/load.component";
|
||||
import { BansModule } from './bans/bans.module';
|
||||
import { NavbarComponent } from "./navbar/navbar.component";
|
||||
import { MiningModule } from './mining/mining.module';
|
||||
|
@ -44,7 +45,8 @@ const httpLoaderFactory = (http: HttpClient): TranslateHttpLoader => new Transl
|
|||
}
|
||||
}),
|
||||
SidebarComponent,
|
||||
NavbarComponent
|
||||
NavbarComponent,
|
||||
LoadComponent
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
|
|
|
@ -20,17 +20,19 @@ export class BansComponent implements AfterViewInit {
|
|||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
console.log('BansComponent AFTER VIEW INIT');
|
||||
this.navbarService.removeNavbarLinks();
|
||||
|
||||
setTimeout(() => {
|
||||
const $table = $('#bansTable');
|
||||
$table.bootstrapTable({});
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
this.load();
|
||||
|
||||
}, 500);
|
||||
console.log('BansComponent AFTER VIEW INIT');
|
||||
|
||||
setTimeout(() => {
|
||||
const $table = $('#bansTable');
|
||||
$table.bootstrapTable({});
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
this.load();
|
||||
|
||||
}, 500);
|
||||
}
|
||||
|
||||
private onNavigationEnd(): void {
|
||||
|
|
|
@ -16,7 +16,8 @@ import {
|
|||
PruneBlockchainRequest,
|
||||
CalculatePoWHashRequest,
|
||||
FlushCacheRequest,
|
||||
GetMinerDataRequest
|
||||
GetMinerDataRequest,
|
||||
EmptyRpcRequest
|
||||
} from '../../../../common/request';
|
||||
import { BlockTemplate } from '../../../../common/BlockTemplate';
|
||||
import { GeneratedBlocks } from '../../../../common/GeneratedBlocks';
|
||||
|
@ -34,23 +35,65 @@ import { RelayTxRequest } from '../../../../common/request/RelayTxRequest';
|
|||
import { TxBacklogEntry } from '../../../../common/TxBacklogEntry';
|
||||
import { BlockchainPruneInfo } from '../../../../common/BlockchainPruneInfo';
|
||||
import { MinerData } from '../../../../common/MinerData';
|
||||
import { CoreIsBusyError } from '../../../../common/error';
|
||||
import { ElectronService } from '../electron/electron.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DaemonService {
|
||||
private readonly configFilePath: string = './config';
|
||||
private url: string = "http://127.0.0.1:28081";
|
||||
//private url: string = "http://node2.monerodevs.org:28089";
|
||||
//private url: string = "https://testnet.xmr.ditatompel.com";
|
||||
//private url: string = "https://xmr.yemekyedim.com:18081";
|
||||
//private url: string = "https://moneronode.org:18081";
|
||||
|
||||
private readonly headers: { [key: string]: string } = {
|
||||
'Content-Type': 'application/json'
|
||||
"Access-Control-Allow-Headers": "*", // this will allow all CORS requests
|
||||
"Access-Control-Allow-Methods": 'POST,GET' // this states the allowed methods
|
||||
};
|
||||
|
||||
constructor(private httpClient: HttpClient) { }
|
||||
constructor(private httpClient: HttpClient, private electronService: ElectronService) { }
|
||||
|
||||
private async callJsonRpc(params: JsonRPCRequest): Promise<{ [key: string]: any }> {
|
||||
return await firstValueFrom<{ [key: string]: any }>(this.httpClient.post(`${this.url}/json_rpc`, params.toDictionary(), this.headers));
|
||||
}
|
||||
|
||||
public async startDaemon(): Promise<void> {
|
||||
if (await this.isRunning()) {
|
||||
console.warn("Daemon already running");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.electronService.isElectron) {
|
||||
console.error("Could not start monero daemon: not electron app");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Starting daemon");
|
||||
|
||||
this.electronService.ipcRenderer.send('start-monerod', this.configFilePath);
|
||||
|
||||
console.log("Daemon started");
|
||||
|
||||
setTimeout(() => {
|
||||
}, 500)
|
||||
}
|
||||
|
||||
public async isRunning(): Promise<boolean> {
|
||||
try {
|
||||
const response = await this.callJsonRpc(new EmptyRpcRequest());
|
||||
console.log(response);
|
||||
return true;
|
||||
}
|
||||
catch(error) {
|
||||
console.error(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async getBlockCount(): Promise<BlockCount> {
|
||||
const response = await this.callJsonRpc(new GetBlockCountRequest());
|
||||
|
||||
|
@ -147,10 +190,15 @@ export class DaemonService {
|
|||
|
||||
public async getBans(): Promise<Ban[]> {
|
||||
const response = await this.callJsonRpc(new GetBansRequest());
|
||||
|
||||
if (response.error) {
|
||||
this.raiseRpcError(response.error);
|
||||
}
|
||||
|
||||
const bans: any[] = response.bans;
|
||||
const result: Ban[] = [];
|
||||
|
||||
bans.forEach((ban: any) => result.push(Ban.parse(ban)));
|
||||
if (bans) bans.forEach((ban: any) => result.push(Ban.parse(ban)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -249,8 +297,24 @@ export class DaemonService {
|
|||
public async getMinerData(): Promise<MinerData> {
|
||||
const response = await this.callJsonRpc(new GetMinerDataRequest());
|
||||
|
||||
if (response.error) {
|
||||
this.raiseRpcError(response.error);
|
||||
}
|
||||
|
||||
return MinerData.parse(response.result);
|
||||
}
|
||||
|
||||
private raiseRpcError(error: { code: number, message: string }): void {
|
||||
|
||||
if (error.code == -9) {
|
||||
throw new CoreIsBusyError();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Error(error.message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
<div class="tab-content" id="pills-tabContent">
|
||||
<app-load [show]="loading"></app-load>
|
||||
|
||||
<div class="tab-content" id="pills-tabContent" [hidden]="loading">
|
||||
<div class="tab-pane fade show active" id="pills-home" role="tabpanel" aria-labelledby="pills-home-tab" tabindex="0">
|
||||
<div class="row d-flex">
|
||||
|
||||
<div *ngIf="!daemonRunning" class="h-100 p-5 text-bg-dark rounded-3 m-4">
|
||||
<h2>Daemon not running</h2>
|
||||
<p>Start monero daemon</p>
|
||||
<button class="btn btn-outline-light" type="button" (click)="startDaemon()"><i class="bi bi-play-fill"></i> Start</button>
|
||||
</div>
|
||||
|
||||
@for(card of cards; track card.header) {
|
||||
<div class="card text-bg-dark m-3 text-center" style="max-width: 18rem;">
|
||||
<div class="card-header">{{card.header}}</div>
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { Component, OnInit, AfterViewInit } from '@angular/core';
|
||||
import { Component, OnInit, AfterViewInit, NgZone } from '@angular/core';
|
||||
import { DaemonService } from '../core/services/daemon/daemon.service';
|
||||
import * as jquery from 'jquery';
|
||||
import * as bootstrapTable from 'bootstrap-table'
|
||||
import { SyncInfo } from '../../common/SyncInfo';
|
||||
import { Peer } from '../../common/Peer';
|
||||
import { NavbarLink } from '../navbar/navbar.model';
|
||||
|
@ -16,6 +14,7 @@ import { DaemonInfo } from '../../common/DaemonInfo';
|
|||
})
|
||||
export class DetailComponent implements OnInit, AfterViewInit {
|
||||
|
||||
public daemonRunning: boolean;
|
||||
private syncInfo?: SyncInfo;
|
||||
private daemonInfo?: DaemonInfo;
|
||||
private readonly navbarLinks: NavbarLink[];
|
||||
|
@ -37,9 +36,16 @@ export class DetailComponent implements OnInit, AfterViewInit {
|
|||
private nodeType: string;
|
||||
private syncProgress: string;
|
||||
|
||||
private isLoading: boolean;
|
||||
|
||||
public get loading(): boolean {
|
||||
return this.isLoading;
|
||||
}
|
||||
|
||||
public cards: Card[];
|
||||
|
||||
constructor(private router: Router,private daemonService: DaemonService, private navbarService: NavbarService) {
|
||||
constructor(private router: Router,private daemonService: DaemonService, private navbarService: NavbarService, private ngZone: NgZone) {
|
||||
this.daemonRunning = false;
|
||||
this.syncStatus = 'Not synced';
|
||||
this.height = 0;
|
||||
this.targetHeight = 0;
|
||||
|
@ -55,6 +61,7 @@ export class DetailComponent implements OnInit, AfterViewInit {
|
|||
this.nodeType = 'unknown';
|
||||
this.blockchainSize = '0 GB';
|
||||
this.syncProgress = '0 %';
|
||||
this.isLoading = true;
|
||||
|
||||
this.navbarLinks = [
|
||||
new NavbarLink('pills-home-tab', '#pills-home', 'pills-home', true, 'Overview'),
|
||||
|
@ -77,27 +84,42 @@ export class DetailComponent implements OnInit, AfterViewInit {
|
|||
|
||||
ngAfterViewInit(): void {
|
||||
console.log('DetailComponent AFTER VIEW INIT');
|
||||
this.navbarService.setNavbarLinks(this.navbarLinks);
|
||||
|
||||
setTimeout(() => {
|
||||
const $table = $('#table');
|
||||
$table.bootstrapTable({});
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
this.Load();
|
||||
this.ngZone.run(() => {
|
||||
const $table = $('#table');
|
||||
$table.bootstrapTable({});
|
||||
$table.bootstrapTable('refreshOptions', {
|
||||
classes: 'table table-bordered table-hover table-dark table-striped'
|
||||
});
|
||||
this.load();
|
||||
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
|
||||
}, 500);
|
||||
public async startDaemon(): Promise<void> {
|
||||
if (this.daemonRunning) {
|
||||
console.warn("Daemon already running");
|
||||
return;
|
||||
}
|
||||
|
||||
await this.daemonService.startDaemon();
|
||||
this.daemonRunning = await this.daemonService.isRunning();
|
||||
}
|
||||
|
||||
private onNavigationEnd(): void {
|
||||
this.Load().then(() => {
|
||||
this.load().then(() => {
|
||||
this.cards = this.createCards();
|
||||
this.navbarService.setNavbarLinks(this.navbarLinks);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private createCards(): Card[] {
|
||||
if (!this.daemonRunning) {
|
||||
return []
|
||||
}
|
||||
return [
|
||||
new Card('Connection Status', this.connectionStatus),
|
||||
new Card('Network Type', this.networkType),
|
||||
|
@ -114,50 +136,64 @@ export class DetailComponent implements OnInit, AfterViewInit {
|
|||
];
|
||||
}
|
||||
|
||||
public async Load(): Promise<void> {
|
||||
const $table = $('#table');
|
||||
private async load(): Promise<void> {
|
||||
try {
|
||||
this.isLoading = true;
|
||||
this.daemonRunning = await this.daemonService.isRunning();
|
||||
|
||||
if (!this.daemonRunning) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $table = $('#table');
|
||||
|
||||
this.syncInfo = await this.daemonService.syncInfo();
|
||||
this.height = this.syncInfo.height;
|
||||
this.targetHeight = this.syncInfo.targetHeight;
|
||||
this.nextNeededPruningSeed = this.syncInfo.nextNeededPruningSeed;
|
||||
|
||||
if (this.height > 0 && this.targetHeight == 0) {
|
||||
this.targetHeight = this.height;
|
||||
this.syncStatus = 'Daemon synced';
|
||||
}
|
||||
else if (this.height > 0 && this.targetHeight > 0 && this.height == this.targetHeight) {
|
||||
this.syncStatus = 'Daemon synced';
|
||||
}
|
||||
|
||||
this.overview = this.syncInfo.overview;
|
||||
|
||||
const blockCount = await this.daemonService.getBlockCount();
|
||||
|
||||
this.blockCount = blockCount.count;
|
||||
|
||||
const version = await this.daemonService.getVersion();
|
||||
|
||||
this.version = `${version.version}`;
|
||||
|
||||
this.daemonInfo = await this.daemonService.getInfo();
|
||||
|
||||
const capacity: number = this.daemonInfo.freeSpace + this.daemonInfo.databaseSize;
|
||||
const diskUsage = parseInt(`${this.daemonInfo.databaseSize * 100 / capacity}`);
|
||||
const blockchainSize = (this.daemonInfo.databaseSize / 1000 / 1000 / 1000).toFixed(2);
|
||||
this.blockchainSize = `${blockchainSize} GB`;
|
||||
this.diskUsage = `${diskUsage} %`;
|
||||
this.networkType = this.daemonInfo.nettype;
|
||||
this.connectionStatus = this.daemonInfo.offline ? 'offline' : 'online';
|
||||
this.txCount = this.daemonInfo.txCount;
|
||||
this.poolSize = this.daemonInfo.txPoolSize;
|
||||
this.version = this.daemonInfo.version;
|
||||
this.syncProgress = `${(this.height*100/this.targetHeight).toFixed(2)} %`;
|
||||
|
||||
//const blockchainPruned = await this.isBlockchainPruned();
|
||||
const blockchainPruned = false;
|
||||
this.nodeType = blockchainPruned ? 'pruned' : 'full';
|
||||
$table.bootstrapTable('load', this.getPeers());
|
||||
}
|
||||
catch(error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
this.syncInfo = await this.daemonService.syncInfo();
|
||||
this.height = this.syncInfo.height;
|
||||
this.targetHeight = this.syncInfo.targetHeight;
|
||||
this.nextNeededPruningSeed = this.syncInfo.nextNeededPruningSeed;
|
||||
|
||||
if (this.height > 0 && this.targetHeight == 0) {
|
||||
this.targetHeight = this.height;
|
||||
this.syncStatus = 'Daemon synced';
|
||||
}
|
||||
else if (this.height > 0 && this.targetHeight > 0 && this.height == this.targetHeight) {
|
||||
this.syncStatus = 'Daemon synced';
|
||||
}
|
||||
|
||||
this.overview = this.syncInfo.overview;
|
||||
|
||||
const blockCount = await this.daemonService.getBlockCount();
|
||||
|
||||
this.blockCount = blockCount.count;
|
||||
|
||||
const version = await this.daemonService.getVersion();
|
||||
|
||||
this.version = `${version.version}`;
|
||||
|
||||
this.daemonInfo = await this.daemonService.getInfo();
|
||||
|
||||
const capacity: number = this.daemonInfo.freeSpace + this.daemonInfo.databaseSize;
|
||||
const diskUsage = parseInt(`${this.daemonInfo.databaseSize * 100 / capacity}`);
|
||||
const blockchainSize = (this.daemonInfo.databaseSize / 1000 / 1000 / 1000).toFixed(2);
|
||||
this.blockchainSize = `${blockchainSize} GB`;
|
||||
this.diskUsage = `${diskUsage} %`;
|
||||
this.networkType = this.daemonInfo.nettype;
|
||||
this.connectionStatus = this.daemonInfo.offline ? 'offline' : 'online';
|
||||
this.txCount = this.daemonInfo.txCount;
|
||||
this.poolSize = this.daemonInfo.txPoolSize;
|
||||
this.version = this.daemonInfo.version;
|
||||
this.syncProgress = `${(this.height*100/this.targetHeight).toFixed(2)} %`;
|
||||
|
||||
//const blockchainPruned = await this.isBlockchainPruned();
|
||||
const blockchainPruned = false;
|
||||
this.nodeType = blockchainPruned ? 'pruned' : 'full';
|
||||
$table.bootstrapTable('load', this.getPeers());
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
public async isBlockchainPruned(): Promise<boolean> {
|
||||
|
|
|
@ -5,9 +5,10 @@ import { DetailRoutingModule } from './detail-routing.module';
|
|||
|
||||
import { DetailComponent } from './detail.component';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { LoadComponent } from "../load/load.component";
|
||||
|
||||
@NgModule({
|
||||
declarations: [DetailComponent],
|
||||
imports: [CommonModule, SharedModule, DetailRoutingModule]
|
||||
imports: [CommonModule, SharedModule, DetailRoutingModule, LoadComponent]
|
||||
})
|
||||
export class DetailModule {}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { AfterViewInit, Component } from '@angular/core';
|
||||
import { DaemonService } from '../core/services/daemon/daemon.service';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { NavbarService } from '../navbar/navbar.service';
|
||||
|
@ -8,7 +8,7 @@ import { NavbarService } from '../navbar/navbar.service';
|
|||
templateUrl: './hard-fork-info.component.html',
|
||||
styleUrl: './hard-fork-info.component.scss'
|
||||
})
|
||||
export class HardForkInfoComponent {
|
||||
export class HardForkInfoComponent implements AfterViewInit {
|
||||
public cards: Card[];
|
||||
private earliestHeight: number;
|
||||
private enabled: boolean;
|
||||
|
@ -36,10 +36,13 @@ export class HardForkInfoComponent {
|
|||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.navbarService.removeNavbarLinks();
|
||||
}
|
||||
|
||||
private onNavigationEnd(): void {
|
||||
this.load().then(() => {
|
||||
this.cards = this.createCards();
|
||||
this.navbarService.removeNavbarLinks();
|
||||
});
|
||||
|
||||
}
|
||||
|
|
9
src/app/load/load.component.html
Normal file
9
src/app/load/load.component.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
<div *ngIf="show" class="row g-5 m-2">
|
||||
<div class="col-md-7 col-lg-10 flex-fill">
|
||||
<div class="d-flex justify-content-center m-5">
|
||||
<div class="spinner-border" style="width: 3rem; height: 3rem;" role="status">
|
||||
<span class="sr-only"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
0
src/app/load/load.component.scss
Normal file
0
src/app/load/load.component.scss
Normal file
23
src/app/load/load.component.spec.ts
Normal file
23
src/app/load/load.component.spec.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoadComponent } from './load.component';
|
||||
|
||||
describe('LoadComponent', () => {
|
||||
let component: LoadComponent;
|
||||
let fixture: ComponentFixture<LoadComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [LoadComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(LoadComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
15
src/app/load/load.component.ts
Normal file
15
src/app/load/load.component.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { NgIf } from '@angular/common';
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-load',
|
||||
standalone: true,
|
||||
imports: [NgIf],
|
||||
templateUrl: './load.component.html',
|
||||
styleUrl: './load.component.scss'
|
||||
})
|
||||
export class LoadComponent {
|
||||
|
||||
@Input() public show: boolean = false;
|
||||
|
||||
}
|
|
@ -6,6 +6,7 @@ import { NavigationEnd, Router } from '@angular/router';
|
|||
import { NavbarLink } from '../navbar/navbar.model';
|
||||
import { MineableTxBacklog } from '../../common/MineableTxBacklog';
|
||||
import { Chain } from '../../common/Chain';
|
||||
import { CoreIsBusyError } from '../../common/error';
|
||||
|
||||
@Component({
|
||||
selector: 'app-mining',
|
||||
|
@ -15,7 +16,7 @@ import { Chain } from '../../common/Chain';
|
|||
export class MiningComponent implements AfterViewInit {
|
||||
|
||||
private readonly navbarLinks: NavbarLink[];
|
||||
|
||||
private coreBusy: boolean;
|
||||
private minerData?: MinerData;
|
||||
|
||||
private majorVersion: number;
|
||||
|
@ -40,6 +41,7 @@ export class MiningComponent implements AfterViewInit {
|
|||
this.alreadyGeneratedCoins = 0;
|
||||
this.alternateChains = [];
|
||||
this.cards = [];
|
||||
this.coreBusy = false;
|
||||
|
||||
this.navbarLinks = [
|
||||
new NavbarLink('pills-miner-data-tab', '#pills-miner-data', 'miner-data', true, 'Miner Data'),
|
||||
|
@ -57,6 +59,7 @@ export class MiningComponent implements AfterViewInit {
|
|||
|
||||
ngAfterViewInit(): void {
|
||||
console.log('DetailComponent AFTER VIEW INIT');
|
||||
this.navbarService.setNavbarLinks(this.navbarLinks);
|
||||
|
||||
setTimeout(() => {
|
||||
const $table = $('#chainsTable');
|
||||
|
@ -72,28 +75,39 @@ export class MiningComponent implements AfterViewInit {
|
|||
private onNavigationEnd(): void {
|
||||
this.load().then(() => {
|
||||
this.cards = this.createCards();
|
||||
this.navbarService.setNavbarLinks(this.navbarLinks)
|
||||
});
|
||||
}
|
||||
|
||||
private async load(): Promise<void> {
|
||||
this.minerData = await this.daemonService.getMinerData();
|
||||
try {
|
||||
this.minerData = await this.daemonService.getMinerData();
|
||||
this.majorVersion = this.minerData.majorVersion;
|
||||
this.height = this.minerData.height;
|
||||
this.prevId = this.minerData.prevId;
|
||||
this.seedHash = this.minerData.seedHash;
|
||||
this.difficulty = this.minerData.difficulty;
|
||||
this.medianWeight = this.minerData.medianWeight;
|
||||
this.alreadyGeneratedCoins = this.minerData.alreadyGeneratedCoins;
|
||||
|
||||
this.majorVersion = this.minerData.majorVersion;
|
||||
this.height = this.minerData.height;
|
||||
this.prevId = this.minerData.prevId;
|
||||
this.seedHash = this.minerData.seedHash;
|
||||
this.difficulty = this.minerData.difficulty;
|
||||
this.medianWeight = this.minerData.medianWeight;
|
||||
this.alreadyGeneratedCoins = this.minerData.alreadyGeneratedCoins;
|
||||
this.alternateChains = await this.daemonService.getAlternateChains();
|
||||
|
||||
this.alternateChains = await this.daemonService.getAlternateChains();
|
||||
|
||||
const $table = $('#chainsTable');
|
||||
$table.bootstrapTable('load', this.getChains());
|
||||
const $table = $('#chainsTable');
|
||||
$table.bootstrapTable('load', this.getChains());
|
||||
}
|
||||
catch(error) {
|
||||
if (error instanceof CoreIsBusyError) {
|
||||
this.coreBusy = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private createCards(): Card[] {
|
||||
if (this.coreBusy) {
|
||||
return [
|
||||
new Card('Error', 'Core is busy')
|
||||
]
|
||||
}
|
||||
return [
|
||||
new Card('Major Fork Version', `${this.majorVersion}`),
|
||||
new Card('Current block height', `${this.height}`),
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<ul class="nav nav-pills" id="pills-tab" role="tablist">
|
||||
@for(navbarLink of navbarLinks; track navbarLink.name) {
|
||||
<li class="nav-item" role="presentation">
|
||||
<li class="nav-item mr-2" role="presentation">
|
||||
<button [class]="navbarLink.selected ? 'nav-link active' : 'nav-link'" [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">{{navbarLink.name}}</button>
|
||||
</li>
|
||||
}
|
||||
|
|
16
src/app/settings/settings-routing.module.ts
Normal file
16
src/app/settings/settings-routing.module.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { SettingsComponent } from './settings.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'settings',
|
||||
component: SettingsComponent
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class SettingsRoutingModule { }
|
380
src/app/settings/settings.component.html
Normal file
380
src/app/settings/settings.component.html
Normal file
|
@ -0,0 +1,380 @@
|
|||
<div class="tab-content" id="pills-settings-tabContent">
|
||||
<div class="tab-pane fade show active" id="pills-rpc" role="tabpanel" aria-labelledby="pills-rpc-tab" tabindex="0">
|
||||
<div class="row g-5 m-2">
|
||||
<div class="col-md-7 col-lg-10">
|
||||
<h4 class="mb-3">General</h4>
|
||||
<div class="row gy-3">
|
||||
|
||||
<div class="form-check form-switch col-md-6">
|
||||
<label for="offline" class="form-check-label">Offline</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="offline">
|
||||
<br>
|
||||
<small class="text-body-secondary">Do not listen for peers, nor connect to any</small>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch col-md-6">
|
||||
<label for="public-node" class="form-check-label">Public node</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="public-node">
|
||||
<br>
|
||||
<small class="text-body-secondary">Allow other users to use the node as a remote (restricted RPC mode, view-only commands) and advertise it over P2P</small>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch col-md-6">
|
||||
<label for="restricted-rpc" class="form-check-label">Restricted RPC</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="restricted-rpc">
|
||||
<br>
|
||||
<small class="text-body-secondary">Restrict RPC to view-only commands and do not return privacy sensitive data in RPC calls</small>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch col-md-6">
|
||||
<label for="confirm-external-bind" class="form-check-label">Confirm external bind</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="confirm-external-bind">
|
||||
<br>
|
||||
<small class="text-body-secondary">Confirm Bind IP is not a loopback (local) IP</small>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch col-md-6">
|
||||
<label for="rpc-ignore-ipv4" class="form-check-label">Ignore IPv4</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-ignore-ipv4">
|
||||
<br>
|
||||
<small class="text-body-secondary">Ignore unsuccessful IPv4 bind for RPC</small>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch col-md-6">
|
||||
<label for="disable-rpc-ban" class="form-check-label">Disable ban</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="disable-rpc-ban">
|
||||
<br>
|
||||
<small class="text-body-secondary">Do not ban hosts on RPC errors</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="rpc-bind-ip" class="form-label">Bind IP</label>
|
||||
<input type="text" class="form-control" id="rpc-bind-ip" placeholder="127.0.0.1">
|
||||
<small class="text-body-secondary">Specify IP to bind RPC server</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="rpc-bind-port" class="form-label">Bind port</label>
|
||||
<input type="number" class="form-control" id="rpc-bind-port" placeholder="18081">
|
||||
<small class="text-body-secondary">18081 for mainnet, 28081 for testnet, 38081 for stagenet</small>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<label for="rpc-login-user" class="form-label">Username</label>
|
||||
<input type="text" class="form-control" id="rpc-login-user" placeholder="" value="">
|
||||
<small class="text-body-secondary">Specify username required for RPC server</small>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<label for="rpc-login-password" class="form-label">Password</label>
|
||||
<input type="password" class="form-control" id="rpc-login-password" placeholder="" value="">
|
||||
<small class="text-body-secondary">Specify password required for RPC server</small>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12">
|
||||
<label for="rpc-access-control-origins" class="form-label">Access control origins</label>
|
||||
<input type="text" class="form-control" id="rpc-access-control-origins" placeholder="" value="">
|
||||
<small class="text-body-secondary">Specify a comma separated list of origins to allow cross origin resource sharing</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<div class="row g-3">
|
||||
<h4 class="mb-3">IPv6</h4>
|
||||
|
||||
<div class="form-check form-switch col-md-12">
|
||||
<label for="rpc-use-ipv6" class="form-check-label">Enabled</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-use-ipv6">
|
||||
<br>
|
||||
<small class="text-body-secondary">Allow IPv6 for RPC</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="rpc-bind-ipv6-address" class="form-label">Bind IPv6 address</label>
|
||||
<input type="text" class="form-control" id="rpc-bind-ipv6-address" placeholder="::1">
|
||||
<small class="text-body-secondary">Specify IPv6 address to bind RPC server</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="rpc-restricted-bind-ipv6-address" class="form-label">Restricted bind IPv6 address</label>
|
||||
<input type="text" class="form-control" id="rpc-restricted-bind-ipv6-address" placeholder="::1">
|
||||
<small class="text-body-secondary">Specify IPv6 address to bind restricted RPC server</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<div class="row g-3">
|
||||
<h4 class="mb-3">ZMQ</h4>
|
||||
|
||||
<div class="form-check form-switch col-md-12">
|
||||
<label for="enable-zmq" class="form-check-label">Enabled</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="enable-zmq">
|
||||
<br>
|
||||
<small class="text-body-secondary">Enable ZMQ RPC Server</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="zmq-rpc-bind-ip" class="form-label">Bind IP</label>
|
||||
<input type="text" class="form-control" id="zmq-rpc-bind-ip" placeholder="127.0.0.1">
|
||||
<small class="text-body-secondary">IP for ZMQ RPC Server to listen on</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="zmq-rpc-bind-port" class="form-label">Bind port</label>
|
||||
<input type="number" class="form-control" id="zmq-rpc-bind-port" placeholder="18082">
|
||||
<small class="text-body-secondary">18082 for mainnet, 28082 for testnet, 38082 for stagenet</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="zmq-pub" class="form-label">ZMQ Pub</label>
|
||||
<input type="text" class="form-control" id="zmq-pub" placeholder="tcp://ip:port or ipc://path">
|
||||
<small class="text-body-secondary">Address for ZMQ Pub</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<div class="row g-3">
|
||||
<h4 class="mb-3">Payment</h4>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label for="rpc-payment-address" class="form-label">Address</label>
|
||||
<input type="text" class="form-control" id="rpc-payment-address">
|
||||
<small class="text-body-secondary">Restrict RPC to clients sending micropayment to this address</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="rpc-payment-difficulty" class="form-label">Difficulty</label>
|
||||
<input type="number" class="form-control" id="rpc-payment-difficulty" placeholder="1000">
|
||||
<small class="text-body-secondary">Restrict RPC to clients sending micropayment at this difficulty</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="rpc-payment-credits" class="form-label">Credits</label>
|
||||
<input type="number" class="form-control" id="rpc-payment-credits" placeholder="100">
|
||||
<small class="text-body-secondary">Restrict RPC to clients sending micropayment, yelds that many credits per payment</small>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch col-md-6">
|
||||
<label for="rpc-payment-allow-free-loopback" class="form-check-label">Allow free loopback</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-payment-allow-free-loopback">
|
||||
<br>
|
||||
<small class="text-body-secondary">Allow free access from the loopback address (ie, the local host)</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<div class="row g-3">
|
||||
<h4 class="mb-3">SSL</h4>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label for="rpc-ssl" class="form-label">SSL Mode</label>
|
||||
<select class="form-select" id="rpc-ssl">
|
||||
<option value="autodetect">Autodetect</option>
|
||||
<option value="enabled">Enabled</option>
|
||||
<option value="disabled">Disabled</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-check form-switch col-md-4">
|
||||
<label for="rpc-ssl-allow-chained" class="form-check-label">Allow chained</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-ssl-allow-chained">
|
||||
<br>
|
||||
<small class="text-body-secondary">Allow user chain certificates</small>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch col-md-4">
|
||||
<label for="rpc-ssl-allow-any-cert" class="form-check-label">Allow any cert</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="rpc-ssl-allow-any-cert">
|
||||
<br>
|
||||
<small class="text-body-secondary">Allow any peer certificate</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label for="rpc-ssl-private-key" class="form-label">Private key</label>
|
||||
<input type="file" class="form-control" id="rpc-ssl-private-key">
|
||||
<small class="text-body-secondary">Path to a PEM format private key</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label for="rpc-ssl-certificate" class="form-label">Certificate</label>
|
||||
<input type="file" class="form-control" id="rpc-ssl-certificate">
|
||||
<small class="text-body-secondary">Path to a PEM format certificate</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12">
|
||||
<label for="rpc-ssl-ca-certificates" class="form-label">CA Certificates</label>
|
||||
<input type="file" class="form-control" id="rpc-ssl-ca-certificates">
|
||||
<small class="text-body-secondary">Path to file containing concatenated PEM format certificate(s) to replace system CA(s)</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-blockchain" role="tabpanel" aria-labelledby="pills-blockchain-tab" tabindex="0">
|
||||
<div class="row g-5 m-2">
|
||||
<div class="col-md-7 col-lg-10">
|
||||
<h4 class="mb-3">Bootstrap Daemon</h4>
|
||||
<form class="needs-validation" novalidate="">
|
||||
<div class="row g-3">
|
||||
|
||||
<div class="col-12">
|
||||
<label for="address" class="form-label">Address</label>
|
||||
<input type="text" class="form-control" id="address" placeholder="Use 'auto' to enable automatic discovering and switching">
|
||||
<small class="text-body-secondary">URL of a bootstrap remote daemon that the connected wallets can use while this daemon is still not fully synced.</small>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<label for="firstName" class="form-label">Username</label>
|
||||
<input type="text" class="form-control" id="firstName" placeholder="" value="">
|
||||
<small class="text-body-secondary">Specify username for the bootstrap daemon login</small>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6">
|
||||
<label for="lastName" class="form-label">Password</label>
|
||||
<input type="password" class="form-control" id="lastName" placeholder="" value="">
|
||||
<small class="text-body-secondary">Specify password for the bootstrap daemon login</small>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<label for="bootstrap-daemon-proxy" class="form-label">Proxy</label>
|
||||
<input type="text" class="form-control" id="bootstrap-daemon-proxy" placeholder="ip:port">
|
||||
<small class="text-body-secondary">Socks proxy to use for bootstrap daemon connection</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<div class="row g-3">
|
||||
<h4 class="mb-3">Synchronization</h4>
|
||||
|
||||
<div class="form-check form-switch col-md-12">
|
||||
<label for="sync-enabled" class="form-check-label">Enabled</label>
|
||||
<input class="form-control form-check-input" type="checkbox" role="switch" id="sync-enabled" checked>
|
||||
<br>
|
||||
<small class="text-body-secondary">Synchronize the blockchain with other peers</small>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label for="block-sync-size" class="form-label">Block sync size</label>
|
||||
<input type="number" class="form-control" id="block-sync-size" placeholder="" value="0">
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label for="block-download-max-size" class="form-label">Block download max size</label>
|
||||
<input type="number" class="form-control" id="block-download-max-size" placeholder="" value="0">
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<label for="db-sync-mode" class="form-label">Database sync mode</label>
|
||||
<input type="text" class="form-control" id="db-sync-mode" placeholder="fast:async:250000000bytes">
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="same-address">
|
||||
<label class="form-check-label" for="same-address">Prune blockchain</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="save-info">
|
||||
<label class="form-check-label" for="save-info">Sync pruned blocks</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="fast-block-sync">
|
||||
<label class="form-check-label" for="fast-block-sync">Fast block sync</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="relay-fluffy-blocks" checked>
|
||||
<label class="form-check-label" for="fast-block-sync">Relay fluffy blocks</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="keep-alt-blocks">
|
||||
<label class="form-check-label" for="keep-alt-block">Keep alternative blocks on restart</label>
|
||||
</div>
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
<h4 class="mb-3">Network type</h4>
|
||||
|
||||
<div class="my-3">
|
||||
<div class="form-check">
|
||||
<input id="credit" name="paymentMethod" type="radio" class="form-check-input" checked="" required="">
|
||||
<label class="form-check-label" for="credit">mainnet</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input id="debit" name="paymentMethod" type="radio" class="form-check-input" required="">
|
||||
<label class="form-check-label" for="debit">testnet</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input id="paypal" name="paymentMethod" type="radio" class="form-check-input" required="">
|
||||
<label class="form-check-label" for="paypal">stagenet</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="row gy-3">
|
||||
<div class="col-md-6">
|
||||
<label for="cc-name" class="form-label">Name on card</label>
|
||||
<input type="text" class="form-control" id="cc-name" placeholder="" required="">
|
||||
<small class="text-body-secondary">Full name as displayed on card</small>
|
||||
<div class="invalid-feedback">
|
||||
Name on card is required
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label for="cc-number" class="form-label">Credit card number</label>
|
||||
<input type="text" class="form-control" id="cc-number" placeholder="" required="">
|
||||
<div class="invalid-feedback">
|
||||
Credit card number is required
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label for="cc-expiration" class="form-label">Expiration</label>
|
||||
<input type="text" class="form-control" id="cc-expiration" placeholder="" required="">
|
||||
<div class="invalid-feedback">
|
||||
Expiration date required
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<label for="cc-cvv" class="form-label">CVV</label>
|
||||
<input type="text" class="form-control" id="cc-cvv" placeholder="" required="">
|
||||
<div class="invalid-feedback">
|
||||
Security code required
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
|
||||
<hr class="my-4">
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="my-4">
|
||||
|
||||
<button class="w-50 btn btn-primary btn-lg" type="submit">Save</button>
|
||||
|
||||
</div>
|
0
src/app/settings/settings.component.scss
Normal file
0
src/app/settings/settings.component.scss
Normal file
23
src/app/settings/settings.component.spec.ts
Normal file
23
src/app/settings/settings.component.spec.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SettingsComponent } from './settings.component';
|
||||
|
||||
describe('SettingsComponent', () => {
|
||||
let component: SettingsComponent;
|
||||
let fixture: ComponentFixture<SettingsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [SettingsComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(SettingsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
257
src/app/settings/settings.component.ts
Normal file
257
src/app/settings/settings.component.ts
Normal file
|
@ -0,0 +1,257 @@
|
|||
import { AfterViewInit, Component } from '@angular/core';
|
||||
import { NavbarService } from '../navbar/navbar.service';
|
||||
import { NavigationEnd, NavigationStart, Router } from '@angular/router';
|
||||
import { NavbarLink } from '../navbar/navbar.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings',
|
||||
templateUrl: './settings.component.html',
|
||||
styleUrl: './settings.component.scss'
|
||||
})
|
||||
export class SettingsComponent implements AfterViewInit {
|
||||
|
||||
private readonly navbarLinks: NavbarLink[];
|
||||
|
||||
constructor(private router: Router, private navbarService: NavbarService) {
|
||||
|
||||
this.navbarLinks = [
|
||||
new NavbarLink('pills-rpc-tab', '#pills-rpc', 'pills-rpc', true, 'RPC'),
|
||||
new NavbarLink('pills-p2p-tab', '#pills-p2p', 'pills-p2p', false, 'P2P'),
|
||||
new NavbarLink('pills-blockchain-tab', '#pills-blockchain', 'pills-blockchain', false, 'Blockchain'),
|
||||
new NavbarLink('pills-mining-tab', '#pills-mining', 'pills-mining', false, 'Mining'),
|
||||
new NavbarLink('pills-log-tab', '#pills-log', 'pills-log', false, 'Logs')
|
||||
];
|
||||
|
||||
this.router.events.subscribe((event) => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
if (event.url != '/settings') return;
|
||||
this.onNavigationEnd();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.navbarService.setNavbarLinks(this.navbarLinks);
|
||||
}
|
||||
|
||||
private onNavigationEnd(): void {
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
* --log-file arg (=/home/sidney/.bitmonero/bitmonero.log, /home/sidney/.bitmonero/testnet/bitmonero.log if 'testnet', /home/sidney/.bitmonero/stagenet/bitmonero.log if 'stagenet')
|
||||
Specify log file
|
||||
--log-level arg
|
||||
--max-log-file-size arg (=104850000) Specify maximum log file size [B]
|
||||
--max-log-files arg (=50) Specify maximum number of rotated log
|
||||
files to be saved (no limit by setting
|
||||
to 0)
|
||||
--max-concurrency arg (=0) Max number of threads to use for a
|
||||
parallel job
|
||||
--proxy arg Network communication through proxy:
|
||||
<socks-ip:port> i.e. "127.0.0.1:9050"
|
||||
--proxy-allow-dns-leaks Allow DNS leaks outside of proxy
|
||||
--public-node Allow other users to use the node as a
|
||||
remote (restricted RPC mode, view-only
|
||||
commands) and advertise it over P2P
|
||||
--zmq-rpc-bind-ip arg (=127.0.0.1) IP for ZMQ RPC server to listen on
|
||||
--zmq-rpc-bind-port arg (=18082, 28082 if 'testnet', 38082 if 'stagenet')
|
||||
Port for ZMQ RPC server to listen on
|
||||
--zmq-pub arg Address for ZMQ pub - tcp://ip:port or
|
||||
ipc://path
|
||||
--no-zmq Disable ZMQ RPC server
|
||||
--data-dir arg (=/home/sidney/.bitmonero, /home/sidney/.bitmonero/testnet if 'testnet', /home/sidney/.bitmonero/stagenet if 'stagenet')
|
||||
Specify data directory
|
||||
--test-drop-download For net tests: in download, discard ALL
|
||||
blocks instead checking/saving them
|
||||
(very fast)
|
||||
--test-drop-download-height arg (=0) Like test-drop-download but discards
|
||||
only after around certain height
|
||||
--testnet Run on testnet. The wallet must be
|
||||
launched with --testnet flag.
|
||||
--stagenet Run on stagenet. The wallet must be
|
||||
launched with --stagenet flag.
|
||||
--regtest Run in a regression testing mode.
|
||||
--keep-fakechain Don't delete any existing database when
|
||||
in fakechain mode.
|
||||
--fixed-difficulty arg (=0) Fixed difficulty used for testing.
|
||||
--enforce-dns-checkpointing checkpoints from DNS server will be
|
||||
enforced
|
||||
--prep-blocks-threads arg (=4) Max number of threads to use when
|
||||
preparing block hashes in groups.
|
||||
--fast-block-sync arg (=1) Sync up most of the way by using
|
||||
embedded, known block hashes.
|
||||
--show-time-stats arg (=0) Show time-stats when processing
|
||||
blocks/txs and disk synchronization.
|
||||
--block-sync-size arg (=0) How many blocks to sync at once during
|
||||
chain synchronization (0 = adaptive).
|
||||
--check-updates arg (=notify) Check for new versions of monero:
|
||||
[disabled|notify|download|update]
|
||||
--fluffy-blocks Relay blocks as fluffy blocks
|
||||
(obsolete, now default)
|
||||
--no-fluffy-blocks Relay blocks as normal blocks
|
||||
--test-dbg-lock-sleep arg (=0) Sleep time in ms, defaults to 0 (off),
|
||||
used to debug before/after locking
|
||||
mutex. Values 100 to 1000 are good for
|
||||
tests.
|
||||
--offline Do not listen for peers, nor connect to
|
||||
any
|
||||
--disable-dns-checkpoints Do not retrieve checkpoints from DNS
|
||||
--block-download-max-size arg (=0) Set maximum size of block download
|
||||
queue in bytes (0 for default)
|
||||
--sync-pruned-blocks Allow syncing from nodes with only
|
||||
pruned blocks
|
||||
--max-txpool-weight arg (=648000000) Set maximum txpool weight in bytes.
|
||||
--block-notify arg Run a program for each new block, '%s'
|
||||
will be replaced by the block hash
|
||||
--prune-blockchain Prune blockchain
|
||||
--reorg-notify arg Run a program for each reorg, '%s' will
|
||||
be replaced by the split height, '%h'
|
||||
will be replaced by the new blockchain
|
||||
height, '%n' will be replaced by the
|
||||
number of new blocks in the new chain,
|
||||
and '%d' will be replaced by the number
|
||||
of blocks discarded from the old chain
|
||||
--block-rate-notify arg Run a program when the block rate
|
||||
undergoes large fluctuations. This
|
||||
might be a sign of large amounts of
|
||||
hash rate going on and off the Monero
|
||||
network, and thus be of potential
|
||||
interest in predicting attacks. %t will
|
||||
be replaced by the number of minutes
|
||||
for the observation window, %b by the
|
||||
number of blocks observed within that
|
||||
window, and %e by the number of blocks
|
||||
that was expected in that window. It is
|
||||
suggested that this notification is
|
||||
used to automatically increase the
|
||||
number of confirmations required before
|
||||
a payment is acted upon.
|
||||
--keep-alt-blocks Keep alternative blocks on restart
|
||||
--extra-messages-file arg Specify file for extra messages to
|
||||
include into coinbase transactions
|
||||
--start-mining arg Specify wallet address to mining for
|
||||
--mining-threads arg Specify mining threads count
|
||||
--bg-mining-enable enable background mining
|
||||
--bg-mining-ignore-battery if true, assumes plugged in when unable
|
||||
to query system power status
|
||||
--bg-mining-min-idle-interval arg Specify min lookback interval in
|
||||
seconds for determining idle state
|
||||
--bg-mining-idle-threshold arg Specify minimum avg idle percentage
|
||||
over lookback interval
|
||||
--bg-mining-miner-target arg Specify maximum percentage cpu use by
|
||||
miner(s)
|
||||
--db-sync-mode arg (=fast:async:250000000bytes)
|
||||
Specify sync option, using format
|
||||
[safe|fast|fastest]:[sync|async]:[<nblo
|
||||
cks_per_sync>[blocks]|<nbytes_per_sync>
|
||||
[bytes]].
|
||||
--db-salvage Try to salvage a blockchain database if
|
||||
it seems corrupted
|
||||
--p2p-bind-ip arg (=0.0.0.0) Interface for p2p network protocol
|
||||
(IPv4)
|
||||
--p2p-bind-ipv6-address arg (=::) Interface for p2p network protocol
|
||||
(IPv6)
|
||||
--p2p-bind-port arg (=18080, 28080 if 'testnet', 38080 if 'stagenet')
|
||||
Port for p2p network protocol (IPv4)
|
||||
--p2p-bind-port-ipv6 arg (=18080, 28080 if 'testnet', 38080 if 'stagenet')
|
||||
Port for p2p network protocol (IPv6)
|
||||
--p2p-use-ipv6 Enable IPv6 for p2p
|
||||
--p2p-ignore-ipv4 Ignore unsuccessful IPv4 bind for p2p
|
||||
--p2p-external-port arg (=0) External port for p2p network protocol
|
||||
(if port forwarding used with NAT)
|
||||
--allow-local-ip Allow local ip add to peer list, mostly
|
||||
in debug purposes
|
||||
--add-peer arg Manually add peer to local peerlist
|
||||
--add-priority-node arg Specify list of peers to connect to and
|
||||
attempt to keep the connection open
|
||||
--add-exclusive-node arg Specify list of peers to connect to
|
||||
only. If this option is given the
|
||||
options add-priority-node and seed-node
|
||||
are ignored
|
||||
--seed-node arg Connect to a node to retrieve peer
|
||||
addresses, and disconnect
|
||||
--tx-proxy arg Send local txes through proxy:
|
||||
<network-type>,<socks-ip:port>[,max_con
|
||||
nections][,disable_noise] i.e.
|
||||
"tor,127.0.0.1:9050,100,disable_noise"
|
||||
--anonymous-inbound arg <hidden-service-address>,<[bind-ip:]por
|
||||
t>[,max_connections] i.e.
|
||||
"x.onion,127.0.0.1:18083,100"
|
||||
--ban-list arg Specify ban list file, one IP address
|
||||
per line
|
||||
--hide-my-port Do not announce yourself as peerlist
|
||||
candidate
|
||||
--no-sync Don't synchronize the blockchain with
|
||||
other peers
|
||||
--enable-dns-blocklist Apply realtime blocklist from DNS
|
||||
--no-igd Disable UPnP port mapping
|
||||
--igd arg (=delayed) UPnP port mapping (disabled, enabled,
|
||||
delayed)
|
||||
--out-peers arg (=-1) set max number of out peers
|
||||
--in-peers arg (=-1) set max number of in peers
|
||||
--tos-flag arg (=-1) set TOS flag
|
||||
--limit-rate-up arg (=2048) set limit-rate-up [kB/s]
|
||||
--limit-rate-down arg (=8192) set limit-rate-down [kB/s]
|
||||
--limit-rate arg (=-1) set limit-rate [kB/s]
|
||||
--pad-transactions Pad relayed transactions to help defend
|
||||
against traffic volume analysis
|
||||
--max-connections-per-ip arg (=1) Maximum number of connections allowed
|
||||
from the same IP address
|
||||
--rpc-bind-port arg (=18081, 28081 if 'testnet', 38081 if 'stagenet')
|
||||
Port for RPC server
|
||||
--rpc-restricted-bind-port arg Port for restricted RPC server
|
||||
--restricted-rpc Restrict RPC to view only commands and
|
||||
do not return privacy sensitive data in
|
||||
RPC calls
|
||||
--bootstrap-daemon-address arg URL of a 'bootstrap' remote daemon that
|
||||
the connected wallets can use while
|
||||
this daemon is still not fully synced.
|
||||
Use 'auto' to enable automatic public
|
||||
nodes discovering and bootstrap daemon
|
||||
switching
|
||||
--bootstrap-daemon-login arg Specify username:password for the
|
||||
bootstrap daemon login
|
||||
--bootstrap-daemon-proxy arg <ip>:<port> socks proxy to use for
|
||||
bootstrap daemon connections
|
||||
--rpc-bind-ip arg (=127.0.0.1) Specify IP to bind RPC server
|
||||
--rpc-bind-ipv6-address arg (=::1) Specify IPv6 address to bind RPC server
|
||||
--rpc-restricted-bind-ip arg (=127.0.0.1)
|
||||
Specify IP to bind restricted RPC
|
||||
server
|
||||
--rpc-restricted-bind-ipv6-address arg (=::1)
|
||||
Specify IPv6 address to bind restricted
|
||||
RPC server
|
||||
--rpc-use-ipv6 Allow IPv6 for RPC
|
||||
--rpc-ignore-ipv4 Ignore unsuccessful IPv4 bind for RPC
|
||||
--rpc-login arg Specify username[:password] required
|
||||
for RPC server
|
||||
--confirm-external-bind Confirm rpc-bind-ip value is NOT a
|
||||
loopback (local) IP
|
||||
--rpc-access-control-origins arg Specify a comma separated list of
|
||||
origins to allow cross origin resource
|
||||
sharing
|
||||
--rpc-ssl arg (=autodetect) Enable SSL on RPC connections:
|
||||
enabled|disabled|autodetect
|
||||
--rpc-ssl-private-key arg Path to a PEM format private key
|
||||
--rpc-ssl-certificate arg Path to a PEM format certificate
|
||||
--rpc-ssl-ca-certificates arg Path to file containing concatenated
|
||||
PEM format certificate(s) to replace
|
||||
system CA(s).
|
||||
--rpc-ssl-allowed-fingerprints arg List of certificate fingerprints to
|
||||
allow
|
||||
--rpc-ssl-allow-chained Allow user (via --rpc-ssl-certificates)
|
||||
chain certificates
|
||||
--disable-rpc-ban Do not ban hosts on RPC errors
|
||||
--rpc-ssl-allow-any-cert Allow any peer certificate
|
||||
--rpc-payment-address arg Restrict RPC to clients sending
|
||||
micropayment to this address
|
||||
--rpc-payment-difficulty arg (=1000) Restrict RPC to clients sending
|
||||
micropayment at this difficulty
|
||||
--rpc-payment-credits arg (=100) Restrict RPC to clients sending
|
||||
micropayment, yields that many credits
|
||||
per payment
|
||||
--rpc-payment-allow-free-loopback Allow free access from the loopback
|
||||
address (ie, the local host)
|
||||
|
||||
*/
|
14
src/app/settings/settings.module.ts
Normal file
14
src/app/settings/settings.module.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { SettingsRoutingModule } from './settings-routing.module';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
CommonModule,
|
||||
SettingsRoutingModule
|
||||
]
|
||||
})
|
||||
export class SettingsModule { }
|
|
@ -20,6 +20,7 @@ export class SidebarComponent {
|
|||
new NavLink('Mining', '/mining', 'bi bi-minecart-loaded'),
|
||||
new NavLink('Hard Fork Info', '/hardforkinfo', 'bi bi-signpost-split'),
|
||||
new NavLink('Bans', '/bans', 'bi bi-ban'),
|
||||
new NavLink('Settings', '/settings', 'bi bi-gear')
|
||||
];
|
||||
this.isLoading = false;
|
||||
this.errorMessage = '';
|
||||
|
|
136
src/common/DaemonSettings.ts
Normal file
136
src/common/DaemonSettings.ts
Normal file
|
@ -0,0 +1,136 @@
|
|||
export class DaemonSettings {
|
||||
public logFile: string = '';
|
||||
public logLevel: number = 0;
|
||||
public maxLogFileSize: number = 104850000;
|
||||
public maxLogFiles: number = 50;
|
||||
|
||||
public maxConcurrency: number = 0;
|
||||
public proxy: string = '';
|
||||
public proxyAllowDnsLeaks: boolean = false;
|
||||
public publicNode: boolean = false;
|
||||
|
||||
public zmqRpcBindIp: string = '';
|
||||
public zmqRpcBindPort: number = 0;
|
||||
public zmqPub: string = '';
|
||||
public noZmq: boolean = false;
|
||||
|
||||
public testDropDownload: boolean = false;
|
||||
public testDropDownloadHeight: number = 0;
|
||||
|
||||
public testDbgLockSleep: number = 0;
|
||||
|
||||
public testnet: boolean = false;
|
||||
public mainnet: boolean = false;
|
||||
public stagenet: boolean = false;
|
||||
|
||||
public regtest: boolean = false;
|
||||
|
||||
public keepFakeChain: boolean = false;
|
||||
public fixedDifficulty: number = 0;
|
||||
public enforceDnsCheckpoint: boolean = false;
|
||||
public prepBlocksThreads: number = 0;
|
||||
public fastBlockSync: boolean = false;
|
||||
public showTimeStats: boolean = false;
|
||||
public blockSyncSize: number = 0;
|
||||
public checkUpdates: 'disabled' | 'notify' | 'download' | 'update' = 'notify';
|
||||
public fluffyBlocks: boolean = true;
|
||||
public noFluffyBlocks: boolean = false;
|
||||
|
||||
public offline: boolean = false;
|
||||
public disableDnsCheckpoints: boolean = false;
|
||||
|
||||
public blockDownloadMaxSize: number = 0;
|
||||
public syncPrunedBlocks: boolean = false;
|
||||
public maxTxPoolWeight: number = 648000000;
|
||||
public blockNotify: string = '';
|
||||
public pruneBlockchain: boolean = false;
|
||||
|
||||
public reorgNotify: string = '';
|
||||
public blockRateNotify: string = '';
|
||||
|
||||
public keepAltBlocks: boolean = false;
|
||||
public extraMessagesFile: string = '';
|
||||
|
||||
public startMining: string = '';
|
||||
public miningThreds: number = 0;
|
||||
|
||||
public bgMiningEnable: boolean = false;
|
||||
public bgMiningIgnoreBattery: boolean = false;
|
||||
public bgMiningMinIdleInterval: number = 0;
|
||||
public bgMiningIdleThreshold: number = 0;
|
||||
public bgMiningMinerTarget: number = 0;
|
||||
|
||||
public dbSyncMode: string = 'fast:async:250000000bytes';
|
||||
public dbSalvage: boolean = false;
|
||||
|
||||
public p2pBindIp: string = '0.0.0.0';
|
||||
public p2pBindIpv6Address: string = "::";
|
||||
public p2pBindPort: number = 0;
|
||||
public p2pBindPortIpv6: number = 0;
|
||||
public p2pUseIpv6: boolean = false;
|
||||
public p2pIgnoreIpv4: boolean = false;
|
||||
public p2pExternalPort: number = 0;
|
||||
public allowLocalIp: boolean = false;
|
||||
public addPeer: string = '';
|
||||
public addPriorityNode: string = '';
|
||||
public addExclusiveNode: string = '';
|
||||
|
||||
public seedNode: string = '';
|
||||
public txProxy: string = '';
|
||||
public anonymousInbound: string = '';
|
||||
|
||||
public banList: string = '';
|
||||
public hideMyPort: boolean = false;
|
||||
|
||||
public noSync: boolean = false;
|
||||
|
||||
public enableDnsBlocklist: boolean = false;
|
||||
public noIgd: boolean = false;
|
||||
public igd: 'disable' | 'enabled' | 'delayed' = 'delayed';
|
||||
public outPeers: number = -1;
|
||||
public inPeers: number = -1;
|
||||
public tosFlag: number = -1;
|
||||
|
||||
public limitRateUp: number = 2048;
|
||||
public limitRateDown: number = 8192;
|
||||
public limitRate: number = -1;
|
||||
|
||||
public padTransactions: boolean = false;
|
||||
public maxConnectionsPerIp: number = 1;
|
||||
|
||||
public rpcBindPort: number = 0;
|
||||
public restrictedBindPort: number = 0;
|
||||
public restrictedRpc: boolean = false;
|
||||
|
||||
public bootstrapDaemonAddress: string = '';
|
||||
public bootstrapDaemonLogin: string = '';
|
||||
public bootstrapDaemonProxy: string = '';
|
||||
|
||||
public confirmExternalBind: boolean = false;
|
||||
|
||||
public rpcBindIp: string = '127.0.0.1';
|
||||
public rpcBindIpv6Address: string = '::1';
|
||||
public rpcRestrictedBindIp: string = '';
|
||||
public rpcUseIpv6: boolean = false;
|
||||
public rpcIgnoreIpv4: boolean = false;
|
||||
public rpcLogin: string = '';
|
||||
public rpcAccessControlOrigins: string = '';
|
||||
public rpcSsl: 'autodetect' | 'enabled' | 'disabled' = 'autodetect';
|
||||
public rpcSslPrivateKey: string = '';
|
||||
public rpcSslCertificate: string = '';
|
||||
public rpcSslCACertificates: string = '';
|
||||
public rpcAllowedFingerprints: string = '';
|
||||
public rpcSslAllowChained: boolean = false;
|
||||
public rpcSslAllowAnyCert: boolean = false;
|
||||
public rpcPaymentAddress: string = '';
|
||||
public rpcPaymentDifficuly: number = 1000;
|
||||
public rpcPaymentCredits: number = 100;
|
||||
public rpcPaymentAllowFreeLoopback: boolean = false;
|
||||
public disableRpcBan: boolean = false;
|
||||
|
||||
public toCommandOptions(): string {
|
||||
let options: string = '';
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ export class SyncInfo {
|
|||
const rawPeers: any[] = syncInfo.peers;
|
||||
const rawSpans: any[] | undefined = syncInfo.rawSpans;
|
||||
|
||||
rawPeers.forEach((peer: any) => peers.push(Peer.parse(peer)));
|
||||
if (rawPeers) rawPeers.forEach((peer: any) => peers.push(Peer.parse(peer)));
|
||||
if (rawSpans) rawSpans.forEach((span: any) => spans.push(Span.parse(span)));
|
||||
|
||||
return new SyncInfo(height, targetHeight, nextNeededPruningSeed, overview, peers, spans);
|
||||
|
|
2
src/common/error.ts
Normal file
2
src/common/error.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { RpcError } from "./error/RpcError";
|
||||
export { CoreIsBusyError } from "./error/CoreIsBusyError";
|
8
src/common/error/CoreIsBusyError.ts
Normal file
8
src/common/error/CoreIsBusyError.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { RpcError } from "./RpcError";
|
||||
|
||||
export class CoreIsBusyError extends RpcError {
|
||||
|
||||
constructor() {
|
||||
super(-9, "Core is busy");
|
||||
}
|
||||
}
|
9
src/common/error/RpcError.ts
Normal file
9
src/common/error/RpcError.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
export abstract class RpcError extends Error {
|
||||
public readonly code: number;
|
||||
|
||||
constructor(code: number, message: string) {
|
||||
super(message);
|
||||
|
||||
this.code = code;
|
||||
}
|
||||
}
|
|
@ -25,4 +25,36 @@ export { GetTxPoolBacklogRequest } from "./request/GetTxPoolBacklogRequest";
|
|||
export { PruneBlockchainRequest } from "./request/PruneBlockchainRequest";
|
||||
export { CalculatePoWHashRequest } from "./request/CalculatePoWHashRequest";
|
||||
export { FlushCacheRequest } from "./request/FlushCacheRequest";
|
||||
export { GetMinerDataRequest } from "./request/GetMinerDataRequest";
|
||||
export { GetMinerDataRequest } from "./request/GetMinerDataRequest";
|
||||
export { GetCoinbaseTxSumRequest } from "./request/GetCoinbaseTxSumRequest";
|
||||
export { EmptyRpcRequest } from "./request/EmptyRpcRequest";
|
||||
|
||||
/**
|
||||
* Restricted requests
|
||||
* flush_txpool
|
||||
generateblocks
|
||||
get_alternate_chains
|
||||
get_bans
|
||||
get_coinbase_tx_sum
|
||||
get_peer_list
|
||||
in_peers
|
||||
mining_status
|
||||
on_get_connections
|
||||
on_set_bans
|
||||
out_peers
|
||||
relay_tx
|
||||
save_bc
|
||||
set_bans
|
||||
set_limit
|
||||
set_log_categories
|
||||
set_log_hash_rate
|
||||
set_log_level
|
||||
start_mining
|
||||
start_save_graph
|
||||
stop_daemon
|
||||
stop_mining
|
||||
stop_save_graph
|
||||
sync_info
|
||||
update
|
||||
|
||||
*/
|
|
@ -2,6 +2,8 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class BannedRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'banned';
|
||||
public override readonly restricted: boolean = false;
|
||||
|
||||
public readonly address: string;
|
||||
|
||||
constructor(address: string) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class CalculatePoWHashRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'calc_pow';
|
||||
public override readonly restricted: boolean = false;
|
||||
public readonly majorVersion: number;
|
||||
public readonly height: number;
|
||||
public readonly blockBlob: string;
|
||||
|
|
6
src/common/request/EmptyRpcRequest.ts
Normal file
6
src/common/request/EmptyRpcRequest.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { JsonRPCRequest } from "./JsonRPCRequest";
|
||||
|
||||
export class EmptyRpcRequest extends JsonRPCRequest {
|
||||
public override readonly restricted: boolean = false;
|
||||
public override readonly method: string = "";
|
||||
}
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class FlushCacheRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'flush_cache';
|
||||
public override readonly restricted: boolean = false;
|
||||
public readonly badTxs: boolean;
|
||||
public readonly badBlocks: boolean;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class FlushTxPoolRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'flush_txpool';
|
||||
public override readonly restricted: boolean = true;
|
||||
public txIds: string[];
|
||||
|
||||
constructor(txIds: string[]) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GenerateBlocksRequest extends JsonRPCRequest {
|
||||
public override method: string = "generateblocks";
|
||||
public override readonly restricted: boolean = true;
|
||||
public readonly amountOfBlocks: number;
|
||||
public readonly walletAddress: string;
|
||||
public readonly prevBlock: string;
|
||||
|
|
|
@ -2,5 +2,5 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetAlternateChainsRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_alternate_chains';
|
||||
|
||||
public override readonly restricted: boolean = true;
|
||||
}
|
|
@ -2,4 +2,5 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetBansRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_bans';
|
||||
public override readonly restricted: boolean = true;
|
||||
}
|
|
@ -2,4 +2,5 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetBlockCountRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = "get_block_count";
|
||||
public override readonly restricted: boolean = false;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetBlockHashRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = "on_get_block_hash";
|
||||
public override readonly restricted: boolean = false;
|
||||
public readonly blockHeight: number;
|
||||
|
||||
constructor(blockHeight: number) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetBlockHeaderByHashRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_block_header_by_hash';
|
||||
public override readonly restricted: boolean = false;
|
||||
public readonly hash: string;
|
||||
public readonly fillPowHash: boolean;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetBlockHeaderByHeightRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_block_header_by_height';
|
||||
public override readonly restricted: boolean = false;
|
||||
public readonly height: number;
|
||||
public readonly fillPowHash: boolean;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetBlockHeadersRangeRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_block_headers_range';
|
||||
public override readonly restricted: boolean = false;
|
||||
public readonly startHeight: number;
|
||||
public readonly endHeight: number;
|
||||
public readonly fillPowHash: boolean;
|
||||
|
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetBlockTemplateRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = "get_block_template";
|
||||
public override readonly restricted: boolean = false;
|
||||
public readonly walletAddress: string;
|
||||
public readonly reserveSize: number;
|
||||
|
||||
|
|
26
src/common/request/GetCoinbaseTxSumRequest.ts
Normal file
26
src/common/request/GetCoinbaseTxSumRequest.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { JsonRPCRequest } from "./JsonRPCRequest";
|
||||
|
||||
|
||||
export class GetCoinbaseTxSumRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = "get_coinbase_tx_sum";
|
||||
public override readonly restricted: boolean = true;
|
||||
public readonly height: number;
|
||||
public readonly count: number;
|
||||
|
||||
constructor(height: number, count: number) {
|
||||
super();
|
||||
this.height = height;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public override toDictionary(): { [key: string]: any; } {
|
||||
const dict = super.toDictionary();
|
||||
|
||||
dict['params'] = {
|
||||
'height': this.height,
|
||||
'count': this.count
|
||||
};
|
||||
|
||||
return dict;
|
||||
}
|
||||
}
|
|
@ -2,4 +2,5 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetConnectionsRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_connections';
|
||||
public override readonly restricted: boolean = false;
|
||||
}
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetFeeEstimateRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_fee_estimate';
|
||||
public override readonly restricted: boolean = false;
|
||||
public readonly graceBlocks: number;
|
||||
|
||||
constructor(graceBlocks: number = 0) {
|
||||
|
|
|
@ -2,4 +2,5 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetInfoRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_info';
|
||||
public override readonly restricted: boolean = false;
|
||||
}
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetLastBlockHeaderRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_last_block_header';
|
||||
public override readonly restricted: boolean = false;
|
||||
public readonly fillPowHash: boolean;
|
||||
|
||||
constructor(fillPowHash: boolean = false) {
|
||||
|
|
|
@ -2,6 +2,6 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetMinerDataRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_miner_data';
|
||||
public override readonly restricted: boolean = false;
|
||||
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetOutputHistogramRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_output_histogram';
|
||||
public override readonly restricted: boolean = false;
|
||||
public readonly amounts: number[];
|
||||
public readonly minCount: number;
|
||||
public readonly maxCount: number;
|
||||
|
|
|
@ -2,4 +2,5 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class GetTxPoolBacklogRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_txpool_backlog';
|
||||
public override readonly restricted: boolean = false;
|
||||
}
|
||||
|
|
|
@ -2,4 +2,5 @@ import { JsonRPCRequest } from "./JsonRPCRequest"
|
|||
|
||||
export class GetVersionRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'get_version';
|
||||
public override readonly restricted: boolean = false;
|
||||
}
|
|
@ -2,4 +2,5 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class HardForkInfoRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'hard_fork_info';
|
||||
public override readonly restricted: boolean = false;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ export abstract class JsonRPCRequest {
|
|||
public readonly version: string = "2.0";
|
||||
public readonly id: string = "0";
|
||||
public abstract readonly method: string;
|
||||
public abstract readonly restricted: boolean;
|
||||
|
||||
public toDictionary(): { [key: string]: any } {
|
||||
return {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class PruneBlockchainRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'prune_blockchain';
|
||||
public override readonly restricted: boolean = true;
|
||||
public readonly check: boolean;
|
||||
|
||||
constructor(check: boolean = false) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class RelayTxRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'relay_tx';
|
||||
public override readonly restricted: boolean = true;
|
||||
public readonly txIds: string[];
|
||||
|
||||
constructor(txIds: string[]) {
|
||||
|
|
|
@ -3,6 +3,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class SetBansRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'set_bans';
|
||||
public override readonly restricted: boolean = true;
|
||||
public bans: Ban[];
|
||||
|
||||
constructor(bans: Ban[]) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class SubmitBlockRequest extends JsonRPCRequest {
|
||||
public override method: string = "submit_block";
|
||||
public override readonly restricted: boolean = false;
|
||||
public readonly blockBlobData: string[];
|
||||
|
||||
constructor(blockBlobData: string[]) {
|
||||
|
|
|
@ -2,4 +2,5 @@ import { JsonRPCRequest } from "./JsonRPCRequest";
|
|||
|
||||
export class SyncInfoRequest extends JsonRPCRequest {
|
||||
public override readonly method: string = 'sync_info';
|
||||
public override readonly restricted: boolean = true;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<html data-bs-theme="dark">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Angular Electron</title>
|
||||
|
|
|
@ -51,3 +51,7 @@ import 'zone.js'; // Included with Angular CLI.
|
|||
/***************************************************************************************************
|
||||
* APPLICATION IMPORTS
|
||||
*/
|
||||
|
||||
import 'jquery';
|
||||
import * as $ from 'jquery';
|
||||
import 'bootstrap-table';
|
||||
|
|
Loading…
Reference in a new issue