From 774e9be207c694c85bc67cdf8d9564e72713fe85 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 4 Apr 2026 08:33:14 +0100 Subject: [PATCH] feat: /status page with live system health checks Shows blockchain daemon, wallet, gateways, name registry, and consensus status with green/amber indicators. Chain stats, hardfork status, and gateway details. Footer link added. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Lethean/Controllers/HomeController.php | 74 ++++++++++++++++ app/Website/Lethean/Routes/web.php | 1 + app/Website/Lethean/Views/layout.blade.php | 1 + app/Website/Lethean/Views/status.blade.php | 88 +++++++++++++++++++ 4 files changed, 164 insertions(+) create mode 100644 app/Website/Lethean/Views/status.blade.php diff --git a/app/Website/Lethean/Controllers/HomeController.php b/app/Website/Lethean/Controllers/HomeController.php index 4620d3a..008f85f 100644 --- a/app/Website/Lethean/Controllers/HomeController.php +++ b/app/Website/Lethean/Controllers/HomeController.php @@ -5,7 +5,9 @@ declare(strict_types=1); namespace Website\Lethean\Controllers; use Illuminate\Routing\Controller; +use Illuminate\Support\Facades\Cache; use Mod\Chain\Services\DaemonRpc; +use Mod\Chain\Services\WalletRpc; use Mod\Gateway\Services\GatewayRegistry; /** @@ -18,6 +20,7 @@ class HomeController extends Controller public function __construct( private readonly DaemonRpc $rpc, private readonly GatewayRegistry $registry, + private readonly WalletRpc $wallet, ) {} public function index(): \Illuminate\View\View @@ -153,6 +156,77 @@ class HomeController extends Controller return view('lethean::services-seo', ['nodes' => array_values($nodes)]); } + public function status(): \Illuminate\View\View + { + $chainInfo = $this->rpc->getInfo(); + $walletInfo = $this->wallet->getBalance(); + $liveGateways = $this->registry->liveGateways(); + $claims = Cache::get('name_claims', []); + $pendingClaims = count(array_filter($claims, fn ($c) => $c['status'] === 'pending')); + + $checks = [ + 'chain' => [ + 'label' => 'Blockchain Daemon', + 'ok' => ! isset($chainInfo['_offline']), + 'stale' => isset($chainInfo['_stale']), + 'detail' => isset($chainInfo['_offline']) + ? 'Unreachable' + : 'Height ' . number_format($chainInfo['height'] ?? 0) . ' — ' . ($chainInfo['status'] ?? 'unknown'), + ], + 'wallet' => [ + 'label' => 'Registry Wallet', + 'ok' => ! isset($walletInfo['error']), + 'detail' => isset($walletInfo['error']) + ? 'Unreachable' + : 'Connected', + ], + 'gateways' => [ + 'label' => 'Paired Gateways', + 'ok' => true, + 'detail' => count($liveGateways) . ' live', + ], + 'names' => [ + 'label' => 'Name Registry', + 'ok' => ! isset($chainInfo['_offline']), + 'detail' => ($chainInfo['alias_count'] ?? 0) . ' registered, ' . $pendingClaims . ' claims pending', + ], + 'consensus' => [ + 'label' => 'Consensus', + 'ok' => ! isset($chainInfo['_offline']), + 'detail' => isset($chainInfo['_offline']) + ? 'Unknown' + : (($chainInfo['pos_allowed'] ?? false) ? 'PoW + PoS (hybrid)' : 'PoW only'), + ], + ]; + + $allOk = ! in_array(false, array_column($checks, 'ok')); + + return view('lethean::status', [ + 'checks' => $checks, + 'allOk' => $allOk, + 'info' => $chainInfo, + 'liveGateways' => $liveGateways, + 'uptime' => $this->uptimeString(), + ]); + } + + private function uptimeString(): string + { + $started = Cache::get('app.started_at'); + if (! $started) { + Cache::put('app.started_at', now()->toIso8601String(), 86400 * 365); + return 'Just started'; + } + + $diff = now()->diff(\Carbon\Carbon::parse($started)); + $parts = []; + if ($diff->d > 0) $parts[] = $diff->d . 'd'; + if ($diff->h > 0) $parts[] = $diff->h . 'h'; + $parts[] = $diff->i . 'm'; + + return implode(' ', $parts); + } + public function services(): \Illuminate\View\View { $result = $this->rpc->getAllAliases(); diff --git a/app/Website/Lethean/Routes/web.php b/app/Website/Lethean/Routes/web.php index 6b7909b..75a1f22 100644 --- a/app/Website/Lethean/Routes/web.php +++ b/app/Website/Lethean/Routes/web.php @@ -11,6 +11,7 @@ Route::get('/network', [HomeController::class, 'network'])->name('network'); Route::get('/sunrise', [HomeController::class, 'sunrise'])->name('sunrise'); Route::get('/pricing', [HomeController::class, 'pricing'])->name('pricing'); Route::get('/docs', [HomeController::class, 'apiDocs'])->name('api'); +Route::get('/status', [HomeController::class, 'status'])->name('status'); Route::get('/services', [HomeController::class, 'servicesLanding'])->name('services'); Route::get('/services/ssl', [HomeController::class, 'sslCertificates'])->name('services.ssl'); Route::get('/services/dns-hosting', [HomeController::class, 'dnsHosting'])->name('services.dns'); diff --git a/app/Website/Lethean/Views/layout.blade.php b/app/Website/Lethean/Views/layout.blade.php index b5eee37..8ada084 100644 --- a/app/Website/Lethean/Views/layout.blade.php +++ b/app/Website/Lethean/Views/layout.blade.php @@ -127,6 +127,7 @@ API Sunrise Order + Status Source Contact diff --git a/app/Website/Lethean/Views/status.blade.php b/app/Website/Lethean/Views/status.blade.php new file mode 100644 index 0000000..2e4c92c --- /dev/null +++ b/app/Website/Lethean/Views/status.blade.php @@ -0,0 +1,88 @@ +@extends('lethean::layout') + +@section('title', 'System Status') +@section('meta_description', 'Live system status for the Lethean .lthn TLD registrar — blockchain, wallet, gateways, DNS.') + +@section('content') +
+
+

System Status

+
+ @if($allOk) + All Systems Operational + @else + Degraded Performance + @endif +
+

Uptime: {{ $uptime }} · Last checked: now

+
+ +
+ @foreach($checks as $key => $check) +
+
+ + {{ $check['label'] }} +
+
+ @if(isset($check['stale']) && $check['stale']) + stale + @endif + {{ $check['detail'] }} +
+
+ @endforeach +
+ +
+
+

Chain

+
+
Block Height{{ number_format($info['height'] ?? 0) }}
+
PoW Difficulty{{ number_format($info['pow_difficulty'] ?? 0) }}
+
PoS{{ ($info['pos_allowed'] ?? false) ? 'Active' : 'Inactive' }}
+
TX Pool{{ $info['tx_pool_size'] ?? 0 }} pending
+
Total TXs{{ number_format($info['tx_count'] ?? 0) }}
+
+
+
+

Gateways

+
+
Paired{{ count($liveGateways) }}
+ @foreach($liveGateways as $gw) +
+ {{ $gw['name'] }} + {{ $gw['region'] ?? 'unknown' }} · {{ $gw['current_load'] ?? 0 }}% load +
+ @endforeach + @if(empty($liveGateways)) +
No gateways currently paired
+ @endif +
+
+
+ +
+

Hardforks

+
+ @foreach(($info['is_hardfok_active'] ?? []) as $i => $active) + HF{{ $i + 1 }}: {{ $active ? 'Active' : 'Pending' }} + @endforeach +
+
+ +
+

+ API health: /v1/names/health + · Chain data: /v1/chain/info +

+
+
+ + +@endsection