diff --git a/package-lock.json b/package-lock.json
index 4453296..518aaef 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,8 @@
"@angular/platform-browser-dynamic": "15.1.5",
"@angular/router": "15.1.5",
"chart.js": "^4.3.0",
+ "chartjs-adapter-moment": "^1.0.1",
+ "moment": "^2.29.4",
"primeflex": "^3.3.0",
"primeng": "15.2.0",
"rxjs": "~7.8.0",
@@ -4797,6 +4799,15 @@
"pnpm": ">=7"
}
},
+ "node_modules/chartjs-adapter-moment": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.1.tgz",
+ "integrity": "sha512-Uz+nTX/GxocuqXpGylxK19YG4R3OSVf8326D+HwSTsNw1LgzyIGRo+Qujwro1wy6X+soNSnfj5t2vZ+r6EaDmA==",
+ "peerDependencies": {
+ "chart.js": ">=3.0.0",
+ "moment": "^2.10.2"
+ }
+ },
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@@ -8573,6 +8584,14 @@
"mkdirp": "bin/cmd.js"
}
},
+ "node_modules/moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -15527,6 +15546,12 @@
"@kurkle/color": "^0.3.0"
}
},
+ "chartjs-adapter-moment": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.1.tgz",
+ "integrity": "sha512-Uz+nTX/GxocuqXpGylxK19YG4R3OSVf8326D+HwSTsNw1LgzyIGRo+Qujwro1wy6X+soNSnfj5t2vZ+r6EaDmA==",
+ "requires": {}
+ },
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@@ -18417,6 +18442,11 @@
"minimist": "^1.2.6"
}
},
+ "moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
+ },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
diff --git a/package.json b/package.json
index 7edb83d..3def581 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,8 @@
"@angular/platform-browser-dynamic": "15.1.5",
"@angular/router": "15.1.5",
"chart.js": "^4.3.0",
+ "chartjs-adapter-moment": "^1.0.1",
+ "moment": "^2.29.4",
"primeflex": "^3.3.0",
"primeng": "15.2.0",
"rxjs": "~7.8.0",
@@ -38,4 +40,4 @@
"karma-jasmine-html-reporter": "~2.0.0",
"typescript": "~4.8.2"
}
-}
\ No newline at end of file
+}
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 008360c..a65cca3 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -3,6 +3,7 @@ import { RouterModule, Routes } from '@angular/router';
import { DashboardComponent } from './components/dashboard/dashboard.component';
import { SplashComponent } from './components/splash/splash.component';
+import { WorkerComponent } from './components/worker/worker.component';
import { AppLayoutComponent } from './layout/app.layout.component';
const routes: Routes = [
@@ -16,7 +17,16 @@ const routes: Routes = [
children: [
{
path: ':address',
- component: DashboardComponent
+ children: [
+ {
+ path: '',
+ component: DashboardComponent,
+ },
+ {
+ path: ':workerId',
+ component: WorkerComponent
+ }
+ ]
}
]
}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index ee2a7b7..91d1b8d 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,3 +1,5 @@
+import 'chartjs-adapter-moment';
+
import { CommonModule, HashLocationStrategy, LocationStrategy } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
@@ -8,13 +10,19 @@ import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { DashboardComponent } from './components/dashboard/dashboard.component';
import { SplashComponent } from './components/splash/splash.component';
+import { WorkerComponent } from './components/worker/worker.component';
import { AppLayoutModule } from './layout/app.layout.module';
+import { NumberSuffixPipe } from './pipes/number-suffix.pipe';
+
+
@NgModule({
declarations: [
AppComponent,
SplashComponent,
- DashboardComponent
+ DashboardComponent,
+ WorkerComponent,
+ NumberSuffixPipe
],
imports: [
CommonModule,
diff --git a/src/app/components/dashboard/dashboard.component.html b/src/app/components/dashboard/dashboard.component.html
index 64d1f38..f56b5e6 100644
--- a/src/app/components/dashboard/dashboard.component.html
+++ b/src/app/components/dashboard/dashboard.component.html
@@ -1,5 +1,32 @@
-
-
- {{clientInfo$ | async | json}}
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+ | Name |
+ ID |
+ Hash Rate |
+ Best Luck |
+
+
+
+
+ | {{worker.name}} |
+ {{worker.id}} |
+ {{worker.hashRate}} |
+ {{worker.bestDifficulty}} |
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/components/dashboard/dashboard.component.ts b/src/app/components/dashboard/dashboard.component.ts
index d8cad54..69a1216 100644
--- a/src/app/components/dashboard/dashboard.component.ts
+++ b/src/app/components/dashboard/dashboard.component.ts
@@ -11,9 +11,13 @@ import { ClientService } from '../../services/client.service';
})
export class DashboardComponent {
+
public clientInfo$: Observable;
constructor(private clientService: ClientService, private route: ActivatedRoute) {
this.clientInfo$ = this.clientService.getClientInfo(this.route.snapshot.params['address']);
+
+
+
}
}
diff --git a/src/app/components/worker/worker.component.html b/src/app/components/worker/worker.component.html
new file mode 100644
index 0000000..e8fc9fa
--- /dev/null
+++ b/src/app/components/worker/worker.component.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
ID
+
{{workerInfo.name}}
+
+
+
+
+
+
+
{{workerInfo.id}}
+
+
+
+
+
+
+
Best Luck
+
{{workerInfo.bestDifficulty | numberSuffix}}
+
+
+
+
+
+
+
{{workerInfo.bestDifficulty | number}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/components/worker/worker.component.scss b/src/app/components/worker/worker.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/components/worker/worker.component.spec.ts b/src/app/components/worker/worker.component.spec.ts
new file mode 100644
index 0000000..28e4b46
--- /dev/null
+++ b/src/app/components/worker/worker.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { WorkerComponent } from './worker.component';
+
+describe('WorkerComponent', () => {
+ let component: WorkerComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ WorkerComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(WorkerComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/worker/worker.component.ts b/src/app/components/worker/worker.component.ts
new file mode 100644
index 0000000..3e2a3ce
--- /dev/null
+++ b/src/app/components/worker/worker.component.ts
@@ -0,0 +1,121 @@
+import { Component } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { map, Observable, shareReplay } from 'rxjs';
+
+import { WorkerService } from '../../services/worker.service';
+
+@Component({
+ selector: 'app-worker',
+ templateUrl: './worker.component.html',
+ styleUrls: ['./worker.component.scss']
+})
+export class WorkerComponent {
+
+ public workerInfo$: Observable;
+
+ public chartData$: Observable;
+
+ public chartOptions: any;
+
+ constructor(private workerService: WorkerService, private route: ActivatedRoute) {
+ const documentStyle = getComputedStyle(document.documentElement);
+ const textColor = documentStyle.getPropertyValue('--text-color');
+ const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary');
+ const surfaceBorder = documentStyle.getPropertyValue('--surface-border');
+
+ this.workerInfo$ = this.workerService.getWorkerInfo(this.route.snapshot.params['address'], this.route.snapshot.params['workerId']).pipe(
+ shareReplay({ bufferSize: 1, refCount: true })
+ )
+
+ this.chartData$ = this.workerInfo$.pipe(
+ map((workerInfo: any) => {
+
+ const GROUP_SIZE = 20;
+ const slice = workerInfo.hashData.length % GROUP_SIZE == 0 ? workerInfo.hashData : workerInfo.hashData.slice(0, workerInfo.hashData.length - workerInfo.hashData.length % GROUP_SIZE)
+ const reducedData = ((slice as any[])
+ .reduce((pre, cur, idx, arr) => {
+ if (idx % GROUP_SIZE != 0) {
+ pre[pre.length - 1].difficulty += cur.difficulty;
+ } else {
+ pre.push(cur);
+ }
+ return pre;
+ }, []) as any[]);
+
+ const labels = reducedData.reduce((pre, cur, idx, arr) => {
+ if (idx == 0) {
+ return pre;
+ }
+ pre.push(new Date(cur.time));
+ return pre;
+ }, []);
+
+ const data = reducedData
+ .reduce((pre, cur, idx, arr) => {
+ if (idx == 0) {
+ return pre;
+ }
+ //hashrate = (nonce_difficulty * 2^32) / time_to_find
+ pre.push((cur.difficulty * 4294967296 / (new Date(cur.time).getTime() - new Date(arr[idx - 1].time).getTime())) / 1000000);
+ return pre;
+
+ }, []);
+ return {
+ labels,
+ datasets: [
+ {
+ label: workerInfo.name,
+ data,
+ fill: false,
+ backgroundColor: documentStyle.getPropertyValue('--bluegray-700'),
+ borderColor: documentStyle.getPropertyValue('--bluegray-700'),
+ tension: .4
+ }
+ ]
+ }
+ })
+ );
+
+
+
+ this.chartOptions = {
+ plugins: {
+ legend: {
+ labels: {
+ color: textColor
+ }
+ }
+ },
+ scales: {
+ x: {
+ type: 'time',
+ time: {
+ unit: 'minute', // Set the unit to 'minute'
+ stepSize: 10, // Set the desired interval between labels in minutes
+
+ },
+ ticks: {
+ color: textColorSecondary
+ },
+ grid: {
+ color: surfaceBorder,
+ drawBorder: false
+ }
+ },
+ y: {
+ ticks: {
+ color: textColorSecondary,
+ callback: (value: number) => value + 'GH/s',
+ },
+ grid: {
+ color: surfaceBorder,
+ drawBorder: false
+ }
+ }
+ }
+ };
+ }
+
+
+
+}
diff --git a/src/app/layout/app.menu.component.html b/src/app/layout/app.menu.component.html
index 2171c9f..f8684e0 100644
--- a/src/app/layout/app.menu.component.html
+++ b/src/app/layout/app.menu.component.html
@@ -1,5 +1,5 @@