ovtools 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +121 -2
  3. package/assets/common/bond-inspect.sh +368 -0
  4. package/assets/common/config.sh +263 -0
  5. package/assets/common/extract-data.sh +197 -0
  6. package/assets/common/harden-host.sh +37 -0
  7. package/assets/common/install-deps.sh +93 -0
  8. package/assets/common/node-enroll.sh +65 -0
  9. package/assets/common/node-setup.sh +150 -0
  10. package/assets/common/node-start.sh +90 -0
  11. package/assets/common/node-stop.sh +18 -0
  12. package/assets/common/node-upgrade.sh +45 -0
  13. package/assets/common/pre-run.sh +497 -0
  14. package/assets/common/promote-validator.sh +104 -0
  15. package/assets/deploy/10-prepare-host.sh +98 -0
  16. package/assets/deploy/20-install-toolchain.sh +93 -0
  17. package/assets/deploy/30-setup-node.sh +82 -0
  18. package/assets/deploy/40-start-node.sh +75 -0
  19. package/assets/deploy/50-verify.sh +259 -0
  20. package/assets/deploy/60-enroll.sh +304 -0
  21. package/assets/deploy/70-promote.sh +152 -0
  22. package/assets/deploy/lib.sh +398 -0
  23. package/assets/manage/10-bond-increase.sh +149 -0
  24. package/assets/manage/10-diagnose-node.sh +169 -0
  25. package/assets/manage/20-exit-validator.sh +259 -0
  26. package/assets/manage/25-recover-node.sh +291 -0
  27. package/assets/manage/30-status.sh +64 -0
  28. package/assets/manage/40-exit-withdraw.sh +133 -0
  29. package/assets/manage/bond_inc.sh +318 -0
  30. package/assets/manage/dashboard_monitor/app.js +1544 -0
  31. package/assets/manage/dashboard_monitor/assets/v2.2/css/base.css +113 -0
  32. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/content.css +133 -0
  33. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/controls.css +229 -0
  34. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/data.css +374 -0
  35. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/icons.css +35 -0
  36. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/motion.css +57 -0
  37. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/shell.css +51 -0
  38. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/sidebar.css +242 -0
  39. package/assets/manage/dashboard_monitor/assets/v2.2/css/components/topbar.css +138 -0
  40. package/assets/manage/dashboard_monitor/assets/v2.2/css/fonts.css +30 -0
  41. package/assets/manage/dashboard_monitor/assets/v2.2/css/synteq-ui-v2.css +25 -0
  42. package/assets/manage/dashboard_monitor/assets/v2.2/css/theme-dark.css +38 -0
  43. package/assets/manage/dashboard_monitor/assets/v2.2/css/theme-light.css +36 -0
  44. package/assets/manage/dashboard_monitor/assets/v2.2/css/tokens.css +61 -0
  45. package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-Medium.ttf +0 -0
  46. package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-Regular.ttf +0 -0
  47. package/assets/manage/dashboard_monitor/assets/v2.2/fonts/GoogleSansCode-SemiBold.ttf +0 -0
  48. package/assets/manage/dashboard_monitor/assets/v2.2/js/synteq-ui-v2.js +869 -0
  49. package/assets/manage/dashboard_monitor/deploy-dashboard.sh +230 -0
  50. package/assets/manage/dashboard_monitor/favicon.svg +13 -0
  51. package/assets/manage/dashboard_monitor/index.html +1197 -0
  52. package/assets/manage/dashboard_monitor/nginx-octra.conf +76 -0
  53. package/assets/manage/dashboard_monitor/octra-dashboard.service +29 -0
  54. package/assets/manage/dashboard_monitor/octra-node-prune.cron +12 -0
  55. package/assets/manage/dashboard_monitor/octra-node-prune.service +16 -0
  56. package/assets/manage/dashboard_monitor/octra-node-prune.timer +12 -0
  57. package/assets/manage/dashboard_monitor/prune-node-junk.sh +329 -0
  58. package/assets/manage/dashboard_monitor/server.py +1887 -0
  59. package/assets/manage/dashboard_monitor/ssl-certbot.sh +90 -0
  60. package/assets/manage/dashboard_monitor/styles.css +327 -0
  61. package/assets/manage/lib.sh +347 -0
  62. package/assets/manifest.json +143 -0
  63. package/assets/migrate/00-backup-identity.sh +67 -0
  64. package/assets/migrate/01-prepare-target.sh +145 -0
  65. package/assets/migrate/02-authorize-pull.sh +43 -0
  66. package/assets/migrate/03-pull-state.sh +102 -0
  67. package/assets/migrate/04-stop-source.sh +85 -0
  68. package/assets/migrate/05-finalize-target.sh +140 -0
  69. package/assets/migrate/06-start-target.sh +57 -0
  70. package/assets/migrate/07-verify.sh +237 -0
  71. package/assets/migrate/08-rollback.sh +54 -0
  72. package/assets/migrate/lib.sh +149 -0
  73. package/assets/upgrade/10-preflight.sh +120 -0
  74. package/assets/upgrade/20-upgrade.sh +142 -0
  75. package/assets/upgrade/30-manual-upgrade.sh +129 -0
  76. package/assets/upgrade/40-storage-prune.sh +65 -0
  77. package/assets/upgrade/50-status.sh +58 -0
  78. package/assets/upgrade/lib.sh +232 -0
  79. package/bin/ovtools.js +32 -0
  80. package/dist/api/checks.d.ts +6 -0
  81. package/dist/api/checks.d.ts.map +1 -0
  82. package/dist/api/checks.js +173 -0
  83. package/dist/api/checks.js.map +1 -0
  84. package/dist/api/hostkeys.d.ts +10 -0
  85. package/dist/api/hostkeys.d.ts.map +1 -0
  86. package/dist/api/hostkeys.js +58 -0
  87. package/dist/api/hostkeys.js.map +1 -0
  88. package/dist/api/jobs.d.ts +33 -0
  89. package/dist/api/jobs.d.ts.map +1 -0
  90. package/dist/api/jobs.js +483 -0
  91. package/dist/api/jobs.js.map +1 -0
  92. package/dist/api/nodes.d.ts +16 -0
  93. package/dist/api/nodes.d.ts.map +1 -0
  94. package/dist/api/nodes.js +126 -0
  95. package/dist/api/nodes.js.map +1 -0
  96. package/dist/api/server.d.ts +3 -0
  97. package/dist/api/server.d.ts.map +1 -0
  98. package/dist/api/server.js +443 -0
  99. package/dist/api/server.js.map +1 -0
  100. package/dist/cli.d.ts +3 -0
  101. package/dist/cli.d.ts.map +1 -0
  102. package/dist/cli.js +301 -0
  103. package/dist/cli.js.map +1 -0
  104. package/dist/constants.d.ts +76 -0
  105. package/dist/constants.d.ts.map +1 -0
  106. package/dist/constants.js +150 -0
  107. package/dist/constants.js.map +1 -0
  108. package/dist/index.d.ts +18 -0
  109. package/dist/index.d.ts.map +1 -0
  110. package/dist/index.js +60 -0
  111. package/dist/index.js.map +1 -0
  112. package/dist/orchestrator/base.d.ts +52 -0
  113. package/dist/orchestrator/base.d.ts.map +1 -0
  114. package/dist/orchestrator/base.js +219 -0
  115. package/dist/orchestrator/base.js.map +1 -0
  116. package/dist/orchestrator/deploy.d.ts +33 -0
  117. package/dist/orchestrator/deploy.d.ts.map +1 -0
  118. package/dist/orchestrator/deploy.js +313 -0
  119. package/dist/orchestrator/deploy.js.map +1 -0
  120. package/dist/orchestrator/manage.d.ts +28 -0
  121. package/dist/orchestrator/manage.d.ts.map +1 -0
  122. package/dist/orchestrator/manage.js +267 -0
  123. package/dist/orchestrator/manage.js.map +1 -0
  124. package/dist/orchestrator/migrate.d.ts +31 -0
  125. package/dist/orchestrator/migrate.d.ts.map +1 -0
  126. package/dist/orchestrator/migrate.js +442 -0
  127. package/dist/orchestrator/migrate.js.map +1 -0
  128. package/dist/ssh/client.d.ts +39 -0
  129. package/dist/ssh/client.d.ts.map +1 -0
  130. package/dist/ssh/client.js +418 -0
  131. package/dist/ssh/client.js.map +1 -0
  132. package/dist/test/core.test.d.ts +2 -0
  133. package/dist/test/core.test.d.ts.map +1 -0
  134. package/dist/test/core.test.js +188 -0
  135. package/dist/test/core.test.js.map +1 -0
  136. package/dist/types.d.ts +267 -0
  137. package/dist/types.d.ts.map +1 -0
  138. package/dist/types.js +3 -0
  139. package/dist/types.js.map +1 -0
  140. package/dist/utils/assets.d.ts +28 -0
  141. package/dist/utils/assets.d.ts.map +1 -0
  142. package/dist/utils/assets.js +583 -0
  143. package/dist/utils/assets.js.map +1 -0
  144. package/dist/utils/browser.d.ts +2 -0
  145. package/dist/utils/browser.d.ts.map +1 -0
  146. package/dist/utils/browser.js +23 -0
  147. package/dist/utils/browser.js.map +1 -0
  148. package/dist/utils/dashboard.d.ts +16 -0
  149. package/dist/utils/dashboard.d.ts.map +1 -0
  150. package/dist/utils/dashboard.js +177 -0
  151. package/dist/utils/dashboard.js.map +1 -0
  152. package/dist/utils/helpers.d.ts +29 -0
  153. package/dist/utils/helpers.d.ts.map +1 -0
  154. package/dist/utils/helpers.js +204 -0
  155. package/dist/utils/helpers.js.map +1 -0
  156. package/dist/utils/scripts.d.ts +60 -0
  157. package/dist/utils/scripts.d.ts.map +1 -0
  158. package/dist/utils/scripts.js +174 -0
  159. package/dist/utils/scripts.js.map +1 -0
  160. package/dist/utils/state.d.ts +12 -0
  161. package/dist/utils/state.d.ts.map +1 -0
  162. package/dist/utils/state.js +44 -0
  163. package/dist/utils/state.js.map +1 -0
  164. package/dist/utils/tar.d.ts +11 -0
  165. package/dist/utils/tar.d.ts.map +1 -0
  166. package/dist/utils/tar.js +93 -0
  167. package/dist/utils/tar.js.map +1 -0
  168. package/dist/utils/update.d.ts +9 -0
  169. package/dist/utils/update.d.ts.map +1 -0
  170. package/dist/utils/update.js +134 -0
  171. package/dist/utils/update.js.map +1 -0
  172. package/dist/utils/websocket.d.ts +10 -0
  173. package/dist/utils/websocket.d.ts.map +1 -0
  174. package/dist/utils/websocket.js +203 -0
  175. package/dist/utils/websocket.js.map +1 -0
  176. package/package.json +55 -4
  177. package/public/app.js +2712 -0
  178. package/public/assets/v2.2/css/base.css +113 -0
  179. package/public/assets/v2.2/css/components/content.css +133 -0
  180. package/public/assets/v2.2/css/components/controls.css +229 -0
  181. package/public/assets/v2.2/css/components/data.css +373 -0
  182. package/public/assets/v2.2/css/components/icons.css +35 -0
  183. package/public/assets/v2.2/css/components/motion.css +57 -0
  184. package/public/assets/v2.2/css/components/shell.css +51 -0
  185. package/public/assets/v2.2/css/components/sidebar.css +242 -0
  186. package/public/assets/v2.2/css/components/topbar.css +138 -0
  187. package/public/assets/v2.2/css/fonts.css +30 -0
  188. package/public/assets/v2.2/css/synteq-ui-v2.css +25 -0
  189. package/public/assets/v2.2/css/theme-dark.css +38 -0
  190. package/public/assets/v2.2/css/theme-light.css +36 -0
  191. package/public/assets/v2.2/css/tokens.css +61 -0
  192. package/public/assets/v2.2/fonts/GoogleSansCode-Medium.ttf +0 -0
  193. package/public/assets/v2.2/fonts/GoogleSansCode-Regular.ttf +0 -0
  194. package/public/assets/v2.2/fonts/GoogleSansCode-SemiBold.ttf +0 -0
  195. package/public/assets/v2.2/js/synteq-ui-v2.js +869 -0
  196. package/public/favicon.svg +7 -0
  197. package/public/index.html +1080 -0
  198. package/public/styles.css +552 -0
@@ -0,0 +1,1197 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" data-theme="dark" class="theme-dark">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
6
+ <meta name="color-scheme" content="dark light" />
7
+ <meta name="description" content="Validator Monitoring System - live node monitoring" />
8
+ <title>Validator Monitoring System</title>
9
+ <link rel="icon" type="image/svg+xml" href="favicon.svg?v=2.1.3" />
10
+ <!-- Asset URLs carry a version: nginx/Cloudflare cache css+js for a day, so a
11
+ deploy must change these query strings (or the folder path) to bust it. -->
12
+ <link rel="stylesheet" href="assets/v2.2/css/synteq-ui-v2.css" />
13
+ <link rel="stylesheet" href="styles.css?v=2.2.1" />
14
+ </head>
15
+ <body>
16
+
17
+ <div class="v2-app" id="app">
18
+
19
+ <!-- --------------- NAVIGATION DOCK --------------- -->
20
+ <aside class="v2-aside" aria-label="Primary navigation" id="sidebar">
21
+ <a href="#overview" class="v2-aside__brand" id="aside-brand"
22
+ aria-label="Validator Monitoring System" title="Validator Monitoring System">
23
+ <span class="v2-aside__brand-mark" aria-hidden="true">
24
+ <svg width="14" height="14" viewBox="0 0 50 50" fill="none" aria-hidden="true">
25
+ <circle cx="25" cy="25" r="21" stroke="currentColor" stroke-width="8" />
26
+ </svg>
27
+ </span>
28
+ </a>
29
+
30
+ <nav class="v2-nav" aria-label="Monitoring sections">
31
+ <a href="#overview" class="v2-nav__item v2-nav__item--active" aria-current="page">
32
+ <svg class="v2-icon v2-icon--16" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/></svg>
33
+ Overview
34
+ </a>
35
+ <a href="#consensus" class="v2-nav__item">
36
+ <svg class="v2-icon v2-icon--16" viewBox="0 0 24 24" aria-hidden="true"><rect x="9" y="2" width="6" height="4" rx="1"/><rect x="2" y="16" width="6" height="4" rx="1"/><rect x="16" y="16" width="6" height="4" rx="1"/><line x1="12" y1="6" x2="12" y2="11"/><line x1="5" y1="16" x2="10" y2="12"/><line x1="19" y1="16" x2="14" y2="12"/></svg>
37
+ Consensus
38
+ </a>
39
+ <a href="#resources" class="v2-nav__item">
40
+ <svg class="v2-icon v2-icon--16" viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/><line x1="9" y1="2" x2="9" y2="4"/><line x1="15" y1="2" x2="15" y2="4"/><line x1="9" y1="20" x2="9" y2="22"/><line x1="15" y1="20" x2="15" y2="22"/><line x1="20" y1="9" x2="22" y2="9"/><line x1="20" y1="14" x2="22" y2="14"/><line x1="2" y1="9" x2="4" y2="9"/><line x1="2" y1="14" x2="4" y2="14"/></svg>
41
+ Resources
42
+ </a>
43
+ <a href="#peers" class="v2-nav__item">
44
+ <svg class="v2-icon v2-icon--16" viewBox="0 0 24 24" aria-hidden="true"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>
45
+ Peers
46
+ </a>
47
+ <a href="#process" class="v2-nav__item">
48
+ <svg class="v2-icon v2-icon--16" viewBox="0 0 24 24" aria-hidden="true"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>
49
+ Process
50
+ </a>
51
+ <a href="#logs" class="v2-nav__item">
52
+ <svg class="v2-icon v2-icon--16" viewBox="0 0 24 24" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="8" y1="13" x2="16" y2="13"/><line x1="8" y1="17" x2="14" y2="17"/></svg>
53
+ Logs
54
+ <span class="v2-nav__badge" id="nav-log-badge" hidden>0</span>
55
+ </a>
56
+ <a href="#system" class="v2-nav__item">
57
+ <svg class="v2-icon v2-icon--16" viewBox="0 0 24 24" aria-hidden="true"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg>
58
+ System
59
+ </a>
60
+ <a href="#wallets" class="v2-nav__item">
61
+ <svg class="v2-icon v2-icon--16" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 12V7H5a2 2 0 0 1 0-4h14v4"/><path d="M3 5v14a2 2 0 0 0 2 2h16v-5"/><path d="M18 12a2 2 0 0 0 0 4h4v-4z"/></svg>
62
+ Wallets
63
+ </a>
64
+ </nav>
65
+
66
+ <div class="v2-aside__footer">
67
+ <!-- Bottom-right of the navigation: the validator status itself, not the
68
+ chain id (the chain is in Overview). -->
69
+ <span class="v2-badge dash-status" id="dock-status" title="Validator status">
70
+ <span class="v2-dot" id="dock-dot" aria-hidden="true"></span>
71
+ <span id="dock-status-text">-</span>
72
+ </span>
73
+ </div>
74
+ </aside>
75
+
76
+ <!-- --------------- TOPBAR --------------- -->
77
+ <header class="v2-topbar" role="banner">
78
+ <button class="v2-sidebar-toggle" data-v2-sidebar-toggle aria-label="Toggle navigation" aria-expanded="true" aria-controls="sidebar">
79
+ <svg class="v2-icon v2-icon--18 icon-menu" viewBox="0 0 24 24" aria-hidden="true"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
80
+ <svg class="v2-icon v2-icon--18 icon-close" viewBox="0 0 24 24" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
81
+ </button>
82
+
83
+ <div class="v2-topbar__left">
84
+ <span class="v2-topbar__crumb v2-mono">octra</span>
85
+ <span class="v2-topbar__sep" aria-hidden="true">/</span>
86
+ <span class="v2-topbar__title" id="topbar-title">Dashboard Monitoring</span>
87
+ <span class="v2-badge" id="topbar-status" title="Node status">
88
+ <span class="v2-dot" id="topbar-dot" aria-hidden="true"></span>
89
+ <span id="topbar-status-text">connecting</span>
90
+ </span>
91
+ </div>
92
+
93
+ <div class="v2-topbar__right">
94
+ <span class="live-age v2-t-xs v2-mono" id="live-age" title="Time since the last successful poll">-</span>
95
+ <button class="v2-iconbtn" id="btn-refresh" aria-label="Refresh now" title="Refresh now">
96
+ <svg class="v2-icon v2-icon--16" viewBox="0 0 24 24" aria-hidden="true"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>
97
+ </button>
98
+ <button class="v2-iconbtn" id="btn-pause" aria-label="Pause auto-refresh" aria-pressed="false" title="Pause auto-refresh">
99
+ <svg class="v2-icon v2-icon--16 icon-pause" viewBox="0 0 24 24" aria-hidden="true"><rect x="6" y="4" width="4" height="16" rx="1"/><rect x="14" y="4" width="4" height="16" rx="1"/></svg>
100
+ <svg class="v2-icon v2-icon--16 icon-play" viewBox="0 0 24 24" aria-hidden="true" style="display:none;"><polygon points="6 3 20 12 6 21 6 3"/></svg>
101
+ </button>
102
+ <button class="v2-iconbtn v2-theme-toggle" data-v2-toggle-theme aria-label="Toggle theme">
103
+ <svg class="v2-icon v2-icon--16 v2-icon--moon" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
104
+ <svg class="v2-icon v2-icon--16 v2-icon--sun" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>
105
+ </button>
106
+ </div>
107
+ </header>
108
+
109
+ <main class="v2-main" aria-label="Node live monitoring">
110
+ <div class="v2-content v2-scroll" id="main-content">
111
+
112
+ <!-- ---------- 1. OVERVIEW ---------- -->
113
+ <section class="v2-section v2-section--compact" id="overview" aria-label="Overview">
114
+
115
+ <div class="dash-hero">
116
+ <div class="dash-hero__main">
117
+ <div class="dash-hero__title-row">
118
+ <h1 class="dash-hero__hostname" id="hero-hostname">-</h1>
119
+ <span class="v2-badge dash-status" id="hero-status">
120
+ <span class="v2-dot" id="hero-status-dot" aria-hidden="true"></span>
121
+ <span id="hero-status-text">connecting</span>
122
+ </span>
123
+ </div>
124
+ <div class="dash-hero__meta">
125
+ <button class="addr-chip" id="hero-address-btn" title="Copy validator address" data-v2-copy="" data-v2-copy-label="Address copied" aria-label="Copy validator address">
126
+ <span class="addr-chip__label">
127
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><rect x="2" y="5" width="20" height="14" rx="2"/><path d="M2 10h20"/></svg>
128
+ Validator
129
+ </span>
130
+ <span class="addr-chip__value v2-mono" id="hero-address">-</span>
131
+ <svg class="v2-icon v2-icon--14 addr-chip__copy" viewBox="0 0 24 24" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
132
+ </button>
133
+ <span class="dash-hero__sep v2-mute" aria-hidden="true">|</span>
134
+ <span class="v2-t-xs v2-mute">Node up <span class="v2-mono" id="hero-node-uptime">-</span></span>
135
+ <span class="dash-hero__sep v2-mute" aria-hidden="true">|</span>
136
+ <span class="v2-t-xs v2-mute">Updated <span class="v2-mono" id="hero-updated">-</span></span>
137
+ </div>
138
+ </div>
139
+ </div>
140
+
141
+ <!-- Actionable alerts: only rendered when something needs attention -->
142
+ <div class="alerts" id="alerts" hidden></div>
143
+
144
+ <!-- Vital signs -->
145
+ <div class="v2-stat-strip" data-v2-stagger>
146
+ <div class="v2-stat">
147
+ <span class="v2-stat__label">
148
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2v20"/><path d="m17 5-5-3-5 3"/><path d="m17 19-5 3-5-3"/></svg>
149
+ Head epoch
150
+ </span>
151
+ <div class="v2-stat__value" id="kpi-head">-</div>
152
+ <span class="v2-t-xs v2-mute" id="kpi-head-sub">current -</span>
153
+ </div>
154
+ <div class="v2-stat">
155
+ <span class="v2-stat__label">
156
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg>
157
+ Sync lag
158
+ </span>
159
+ <div class="v2-stat__value" id="kpi-lag">-</div>
160
+ <span class="v2-t-xs v2-mute" id="kpi-lag-sub">network head -</span>
161
+ </div>
162
+ <div class="v2-stat">
163
+ <span class="v2-stat__label">
164
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg>
165
+ Quorum
166
+ </span>
167
+ <div class="v2-stat__value" id="kpi-quorum">-</div>
168
+ <span class="v2-t-xs v2-mute" id="kpi-quorum-sub">prevotes -</span>
169
+ </div>
170
+ <div class="v2-stat">
171
+ <span class="v2-stat__label">
172
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>
173
+ Consensus peers
174
+ </span>
175
+ <div class="v2-stat__value" id="kpi-peers">-</div>
176
+ <span class="v2-t-xs v2-mute" id="kpi-peers-sub">- connected</span>
177
+ </div>
178
+ <div class="v2-stat">
179
+ <span class="v2-stat__label">
180
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 15 14"/></svg>
181
+ Epoch rate
182
+ </span>
183
+ <div class="v2-stat__value" id="kpi-rate">-</div>
184
+ <span class="v2-t-xs v2-mute" id="kpi-rate-sub">- s / epoch</span>
185
+ </div>
186
+ <div class="v2-stat">
187
+ <span class="v2-stat__label">
188
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><path d="M22 12h-4l-3 9L9 3l-3 9H2"/></svg>
189
+ Availability
190
+ </span>
191
+ <div class="v2-stat__value" id="kpi-avail">-</div>
192
+ <span class="v2-t-xs v2-mute" id="kpi-avail-sub">since service start</span>
193
+ </div>
194
+ </div>
195
+
196
+ <div class="v2-grid v2-grid--auto">
197
+
198
+ <!-- Live consensus round -->
199
+ <div class="panel">
200
+ <div class="v2-section__head">
201
+ <span class="v2-section__title">
202
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="3"/><circle cx="12" cy="12" r="9"/></svg>
203
+ Consensus round
204
+ </span>
205
+ <span class="v2-section__meta"><span class="v2-badge" id="con-step-badge">-</span></span>
206
+ </div>
207
+
208
+ <div class="v2-kv">
209
+ <div class="v2-kv__row">
210
+ <span class="v2-kv__label">Round epoch</span>
211
+ <span class="v2-kv__value v2-mono" id="con-epoch">-</span>
212
+ </div>
213
+ <div class="v2-kv__row">
214
+ <span class="v2-kv__label">Round / step</span>
215
+ <span class="v2-kv__value"><span class="v2-mono" id="con-round">-</span> | <span id="con-step">-</span></span>
216
+ </div>
217
+ <div class="v2-kv__row">
218
+ <span class="v2-kv__label">Agreed</span>
219
+ <span class="v2-kv__value" id="con-agreed">-</span>
220
+ </div>
221
+ <div class="v2-kv__row">
222
+ <span class="v2-kv__label">Participants</span>
223
+ <span class="v2-kv__value v2-mono" id="con-participants">-</span>
224
+ </div>
225
+ <div class="v2-kv__row">
226
+ <span class="v2-kv__label">Voting</span>
227
+ <span class="v2-kv__value" id="con-voting">-</span>
228
+ </div>
229
+ </div>
230
+
231
+ <div class="gauge-stack">
232
+ <div class="v2-gauge" role="progressbar" aria-label="Prevote quorum" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" id="gauge-prevote">
233
+ <div class="v2-gauge__head">
234
+ <span class="v2-gauge__label">Prevotes</span>
235
+ <span class="v2-gauge__value"><span id="prevote-count">-</span> <span class="v2-gauge__max" id="prevote-quorum">/ -</span></span>
236
+ </div>
237
+ <div class="v2-gauge__track"><div class="v2-gauge__fill" id="prevote-fill"></div></div>
238
+ <span class="v2-t-xs v2-mute" id="prevote-sub">-</span>
239
+ </div>
240
+
241
+ <div class="v2-gauge" role="progressbar" aria-label="Precommit quorum" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" id="gauge-precommit">
242
+ <div class="v2-gauge__head">
243
+ <span class="v2-gauge__label">Precommits</span>
244
+ <span class="v2-gauge__value"><span id="precommit-count">-</span> <span class="v2-gauge__max" id="precommit-quorum">/ -</span></span>
245
+ </div>
246
+ <div class="v2-gauge__track"><div class="v2-gauge__fill" id="precommit-fill"></div></div>
247
+ <span class="v2-t-xs v2-mute" id="precommit-sub">-</span>
248
+ </div>
249
+ </div>
250
+ </div>
251
+
252
+ <!-- Health checks -->
253
+ <div class="panel">
254
+ <div class="v2-section__head">
255
+ <span class="v2-section__title">
256
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
257
+ Health checks
258
+ </span>
259
+ <span class="v2-section__meta" id="health-meta">-</span>
260
+ </div>
261
+ <div class="health" id="health-list" role="list">
262
+ <div class="health__row" role="listitem"><span class="v2-badge">...</span><span class="health__label">Waiting for telemetry</span></div>
263
+ </div>
264
+ </div>
265
+
266
+ </div>
267
+ </section>
268
+
269
+ <!-- ---------- 2. CONSENSUS ---------- -->
270
+ <section class="v2-section v2-section--compact" id="consensus" aria-label="Consensus">
271
+ <div class="v2-section__head">
272
+ <span class="v2-section__title">
273
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><rect x="9" y="2" width="6" height="4" rx="1"/><rect x="2" y="16" width="6" height="4" rx="1"/><rect x="16" y="16" width="6" height="4" rx="1"/><line x1="12" y1="6" x2="12" y2="11"/><line x1="5" y1="16" x2="10" y2="12"/><line x1="19" y1="16" x2="14" y2="12"/></svg>
274
+ Consensus &amp; epoch
275
+ </span>
276
+ <span class="v2-section__meta">live | 5 s</span>
277
+ </div>
278
+
279
+ <div class="v2-stat-strip">
280
+ <div class="v2-stat">
281
+ <span class="v2-stat__label">Step</span>
282
+ <div class="v2-stat__value v2-t-xl" id="c-step">-</div>
283
+ </div>
284
+ <div class="v2-stat">
285
+ <span class="v2-stat__label">Round</span>
286
+ <div class="v2-stat__value v2-t-xl v2-mono" id="c-round">-</div>
287
+ </div>
288
+ <div class="v2-stat">
289
+ <span class="v2-stat__label">Round participants</span>
290
+ <div class="v2-stat__value v2-t-xl v2-mono" id="c-participants">-</div>
291
+ <span class="v2-t-xs v2-mute" id="c-participants-sub">- / - / -</span>
292
+ </div>
293
+ <div class="v2-stat">
294
+ <span class="v2-stat__label">Newest vote</span>
295
+ <div class="v2-stat__value v2-t-xl v2-mono" id="c-vote-age">-</div>
296
+ <span class="v2-t-xs v2-mute">age of the freshest round vote</span>
297
+ </div>
298
+ <div class="v2-stat">
299
+ <span class="v2-stat__label">Epoch interval</span>
300
+ <div class="v2-stat__value v2-t-xl v2-mono" id="c-interval">-</div>
301
+ <span class="v2-t-xs v2-mute">avg, 5 min window</span>
302
+ </div>
303
+ <div class="v2-stat">
304
+ <span class="v2-stat__label">Last advance</span>
305
+ <div class="v2-stat__value v2-t-xl v2-mono" id="c-last-advance">-</div>
306
+ <span class="v2-t-xs v2-mute" id="c-last-advance-sub">-</span>
307
+ </div>
308
+ </div>
309
+
310
+ <div class="v2-grid v2-grid--2">
311
+
312
+ <div class="panel">
313
+ <div class="v2-section__head">
314
+ <span class="v2-section__title">Vote weight vs quorum</span>
315
+ <span class="v2-section__meta v2-mono" id="c-quorum-weight">-</span>
316
+ </div>
317
+ <div class="gauge-stack">
318
+ <div class="v2-gauge" role="progressbar" aria-label="Prevote weight" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" id="gauge-prevote-w">
319
+ <div class="v2-gauge__head">
320
+ <span class="v2-gauge__label">Prevote weight</span>
321
+ <span class="v2-gauge__value" id="prevote-w-pct">-</span>
322
+ </div>
323
+ <div class="v2-gauge__track"><div class="v2-gauge__fill" id="prevote-w-fill"></div></div>
324
+ <span class="v2-t-xs v2-mute" id="prevote-w-raw">-</span>
325
+ </div>
326
+ <div class="v2-gauge" role="progressbar" aria-label="Precommit weight" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" id="gauge-precommit-w">
327
+ <div class="v2-gauge__head">
328
+ <span class="v2-gauge__label">Precommit weight</span>
329
+ <span class="v2-gauge__value" id="precommit-w-pct">-</span>
330
+ </div>
331
+ <div class="v2-gauge__track"><div class="v2-gauge__fill" id="precommit-w-fill"></div></div>
332
+ <span class="v2-t-xs v2-mute" id="precommit-w-raw">-</span>
333
+ </div>
334
+ </div>
335
+ <div class="v2-kv">
336
+ <div class="v2-kv__row">
337
+ <span class="v2-kv__label">Quorum weight</span>
338
+ <span class="v2-kv__value v2-mono" id="c-quorum-weight-kv">-</span>
339
+ </div>
340
+ <div class="v2-kv__row">
341
+ <span class="v2-kv__label">Proposals in round</span>
342
+ <span class="v2-kv__value v2-mono" id="c-proposals">-</span>
343
+ </div>
344
+ <div class="v2-kv__row">
345
+ <span class="v2-kv__label">Round agreed</span>
346
+ <span class="v2-kv__value" id="c-agreed">-</span>
347
+ </div>
348
+ </div>
349
+ </div>
350
+
351
+ <div class="panel">
352
+ <div class="v2-section__head">
353
+ <span class="v2-section__title">Epoch progression</span>
354
+ <span class="v2-section__meta v2-mono" id="epoch-spark-meta">-</span>
355
+ </div>
356
+ <svg class="v2-spark" id="epoch-spark" viewBox="0 0 400 56" preserveAspectRatio="none" role="img" aria-label="Head epoch progression"></svg>
357
+ <div class="v2-kv">
358
+ <div class="v2-kv__row">
359
+ <span class="v2-kv__label">Head epoch</span>
360
+ <span class="v2-kv__value v2-mono" id="c-head">-</span>
361
+ </div>
362
+ <div class="v2-kv__row">
363
+ <span class="v2-kv__label">Current epoch</span>
364
+ <span class="v2-kv__value v2-mono" id="c-current">-</span>
365
+ </div>
366
+ <div class="v2-kv__row">
367
+ <span class="v2-kv__label">Pending epochs</span>
368
+ <span class="v2-kv__value v2-mono" id="c-pending">-</span>
369
+ </div>
370
+ <div class="v2-kv__row">
371
+ <span class="v2-kv__label">Rate</span>
372
+ <span class="v2-kv__value v2-mono" id="c-rate">-</span>
373
+ </div>
374
+ </div>
375
+ </div>
376
+
377
+ </div>
378
+
379
+ <div class="panel">
380
+ <div class="v2-section__head">
381
+ <span class="v2-section__title">Prevote proposals</span>
382
+ <span class="v2-section__meta v2-mono" id="votes-meta">-</span>
383
+ </div>
384
+ <div class="v2-table-wrap">
385
+ <table class="v2-table">
386
+ <thead>
387
+ <tr><th scope="col">Proposal</th><th scope="col" class="v2-table__num">Voters</th><th scope="col" class="v2-table__num">Weight</th></tr>
388
+ </thead>
389
+ <tbody id="votes-body">
390
+ <tr><td colspan="3" class="v2-mute">Waiting for round data...</td></tr>
391
+ </tbody>
392
+ </table>
393
+ </div>
394
+ </div>
395
+ </section>
396
+
397
+ <!-- ---------- 3. RESOURCES ---------- -->
398
+ <section class="v2-section v2-section--compact" id="resources" aria-label="Resources">
399
+ <div class="v2-section__head">
400
+ <span class="v2-section__title">
401
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/><line x1="9" y1="2" x2="9" y2="4"/><line x1="15" y1="2" x2="15" y2="4"/><line x1="9" y1="20" x2="9" y2="22"/><line x1="15" y1="20" x2="15" y2="22"/><line x1="20" y1="9" x2="22" y2="9"/><line x1="20" y1="14" x2="22" y2="14"/><line x1="2" y1="9" x2="4" y2="9"/><line x1="2" y1="14" x2="4" y2="14"/></svg>
402
+ Resource usage
403
+ </span>
404
+ <span class="v2-section__meta" id="res-meta">-</span>
405
+ </div>
406
+
407
+ <div class="v2-grid v2-grid--2">
408
+
409
+ <div class="panel">
410
+ <div class="v2-section__head">
411
+ <span class="v2-section__title">Compute</span>
412
+ <span class="v2-section__meta v2-mono" id="res-cores-meta">-</span>
413
+ </div>
414
+ <div class="gauge-stack">
415
+ <div class="v2-gauge" role="progressbar" aria-label="CPU usage" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" id="gauge-cpu">
416
+ <div class="v2-gauge__head">
417
+ <span class="v2-gauge__label">
418
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><rect x="4" y="4" width="16" height="16" rx="2"/><rect x="9" y="9" width="6" height="6"/></svg>
419
+ CPU
420
+ </span>
421
+ <span class="v2-gauge__value" id="res-cpu-pct">-</span>
422
+ </div>
423
+ <div class="v2-gauge__track"><div class="v2-gauge__fill" id="res-cpu-fill"></div></div>
424
+ <span class="v2-t-xs v2-mute" id="res-cpu-sub">-</span>
425
+ </div>
426
+
427
+ <div class="v2-gauge" role="progressbar" aria-label="Memory usage" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" id="gauge-mem">
428
+ <div class="v2-gauge__head">
429
+ <span class="v2-gauge__label">
430
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z"/><line x1="8" y1="12" x2="8.01" y2="12"/><line x1="12" y1="12" x2="12.01" y2="12"/><line x1="16" y1="12" x2="16.01" y2="12"/></svg>
431
+ Memory
432
+ </span>
433
+ <span class="v2-gauge__value" id="res-mem-pct">-</span>
434
+ </div>
435
+ <div class="v2-gauge__track"><div class="v2-gauge__fill" id="res-mem-fill"></div></div>
436
+ <span class="v2-t-xs v2-mute" id="res-mem-sub">-</span>
437
+ </div>
438
+
439
+ <div class="v2-gauge" role="progressbar" aria-label="Swap usage" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" id="gauge-swap">
440
+ <div class="v2-gauge__head">
441
+ <span class="v2-gauge__label">
442
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/></svg>
443
+ Swap
444
+ </span>
445
+ <span class="v2-gauge__value" id="res-swap-pct">-</span>
446
+ </div>
447
+ <div class="v2-gauge__track"><div class="v2-gauge__fill" id="res-swap-fill"></div></div>
448
+ <span class="v2-t-xs v2-mute" id="res-swap-sub">-</span>
449
+ </div>
450
+ </div>
451
+
452
+ <div class="v2-kv">
453
+ <div class="v2-kv__row">
454
+ <span class="v2-kv__label">Load average (1 / 5 / 15 m)</span>
455
+ <span class="v2-kv__value v2-mono" id="res-load">-</span>
456
+ </div>
457
+ <div class="v2-kv__row">
458
+ <span class="v2-kv__label">Load per core</span>
459
+ <span class="v2-kv__value v2-mono" id="res-load-pct">-</span>
460
+ </div>
461
+ <div class="v2-kv__row">
462
+ <span class="v2-kv__label">System uptime</span>
463
+ <span class="v2-kv__value v2-mono" id="res-uptime">-</span>
464
+ </div>
465
+ </div>
466
+ </div>
467
+
468
+ <div class="panel">
469
+ <div class="v2-section__head">
470
+ <span class="v2-section__title">Storage</span>
471
+ <span class="v2-section__meta v2-mono" id="res-storage-meta">-</span>
472
+ </div>
473
+ <div class="gauge-stack">
474
+ <div class="v2-gauge" role="progressbar" aria-label="Data volume usage" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" id="gauge-disk">
475
+ <div class="v2-gauge__head">
476
+ <span class="v2-gauge__label">
477
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M3 5v4c0 1.66 4.03 3 9 3s9-1.34 9-3V5"/><path d="M3 9v4c0 1.66 4.03 3 9 3s9-1.34 9-3V9"/></svg>
478
+ Data volume
479
+ </span>
480
+ <span class="v2-gauge__value" id="res-disk-pct">-</span>
481
+ </div>
482
+ <div class="v2-gauge__track"><div class="v2-gauge__fill" id="res-disk-fill"></div></div>
483
+ <span class="v2-t-xs v2-mute" id="res-disk-sub">-</span>
484
+ </div>
485
+
486
+ <div class="v2-gauge" role="progressbar" aria-label="Root filesystem usage" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" id="gauge-root">
487
+ <div class="v2-gauge__head">
488
+ <span class="v2-gauge__label">
489
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
490
+ Root filesystem
491
+ </span>
492
+ <span class="v2-gauge__value" id="res-root-pct">-</span>
493
+ </div>
494
+ <div class="v2-gauge__track"><div class="v2-gauge__fill" id="res-root-fill"></div></div>
495
+ <span class="v2-t-xs v2-mute" id="res-root-sub">-</span>
496
+ </div>
497
+ </div>
498
+
499
+ <div class="v2-kv">
500
+ <div class="v2-kv__row">
501
+ <span class="v2-kv__label">Disk read</span>
502
+ <span class="v2-kv__value v2-mono" id="res-disk-read">-</span>
503
+ </div>
504
+ <div class="v2-kv__row">
505
+ <span class="v2-kv__label">Disk write</span>
506
+ <span class="v2-kv__value v2-mono" id="res-disk-write">-</span>
507
+ </div>
508
+ <div class="v2-kv__row">
509
+ <span class="v2-kv__label">Data dir</span>
510
+ <span class="v2-kv__value v2-mono truncate" id="res-data-dir">-</span>
511
+ </div>
512
+ </div>
513
+ </div>
514
+
515
+ </div>
516
+
517
+ <div class="panel">
518
+ <div class="v2-section__head">
519
+ <span class="v2-section__title">CPU - last 5 minutes</span>
520
+ <span class="v2-section__meta v2-mono" id="cpu-spark-meta">-</span>
521
+ </div>
522
+ <svg class="v2-spark v2-spark--tall" id="cpu-spark" viewBox="0 0 400 56" preserveAspectRatio="none" role="img" aria-label="CPU utilisation trend"></svg>
523
+ </div>
524
+ </section>
525
+
526
+ <!-- ---------- 4. PEERS ---------- -->
527
+ <section class="v2-section v2-section--compact" id="peers" aria-label="Peers">
528
+ <div class="v2-section__head">
529
+ <span class="v2-section__title">
530
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>
531
+ Peer mesh
532
+ </span>
533
+ <span class="v2-section__meta" id="peers-meta">-</span>
534
+ </div>
535
+
536
+ <div class="v2-stat-strip">
537
+ <div class="v2-stat">
538
+ <span class="v2-stat__label">Connected</span>
539
+ <div class="v2-stat__value" id="p-connected">-</div>
540
+ <span class="v2-t-xs v2-mute" id="p-known-sub">of - known</span>
541
+ </div>
542
+ <div class="v2-stat">
543
+ <span class="v2-stat__label">Consensus peers</span>
544
+ <div class="v2-stat__value" id="p-consensus">-</div>
545
+ <span class="v2-t-xs v2-mute">peer state records</span>
546
+ </div>
547
+ <div class="v2-stat">
548
+ <span class="v2-stat__label">Network lag</span>
549
+ <div class="v2-stat__value" id="p-lag-max">-</div>
550
+ <span class="v2-t-xs v2-mute">epochs vs network head</span>
551
+ </div>
552
+ <div class="v2-stat">
553
+ <span class="v2-stat__label">Median drift</span>
554
+ <div class="v2-stat__value" id="p-drift-median">-</div>
555
+ <span class="v2-t-xs v2-mute" id="p-lag-median-sub">beyond record age, &lt; 2 min</span>
556
+ </div>
557
+ <div class="v2-stat">
558
+ <span class="v2-stat__label">Behind</span>
559
+ <div class="v2-stat__value" id="p-behind">-</div>
560
+ <span class="v2-t-xs v2-mute">recent records &gt; 3 epochs</span>
561
+ </div>
562
+ <div class="v2-stat">
563
+ <span class="v2-stat__label">Stale records</span>
564
+ <div class="v2-stat__value" id="p-stale">-</div>
565
+ <span class="v2-t-xs v2-mute">no update &gt; 10 min</span>
566
+ </div>
567
+ </div>
568
+
569
+ <div class="v2-grid v2-grid--2">
570
+
571
+ <div class="panel">
572
+ <div class="v2-section__head">
573
+ <span class="v2-section__title">Peer scoring</span>
574
+ <span class="v2-section__meta">p2p guard</span>
575
+ </div>
576
+ <div class="v2-kv">
577
+ <div class="v2-kv__row">
578
+ <span class="v2-kv__label">Synced peers</span>
579
+ <span class="v2-kv__value v2-mono" id="p-synced">-</span>
580
+ </div>
581
+ <div class="v2-kv__row">
582
+ <span class="v2-kv__label">Max drift</span>
583
+ <span class="v2-kv__value v2-mono" id="p-drift-max">-</span>
584
+ </div>
585
+ <div class="v2-kv__row">
586
+ <span class="v2-kv__label">Peers ahead of us</span>
587
+ <span class="v2-kv__value v2-mono" id="p-ahead">-</span>
588
+ </div>
589
+ <div class="v2-kv__row">
590
+ <span class="v2-kv__label">Banned peers</span>
591
+ <span class="v2-kv__value" id="p-banned">-</span>
592
+ </div>
593
+ <div class="v2-kv__row">
594
+ <span class="v2-kv__label">Paused peers</span>
595
+ <span class="v2-kv__value" id="p-paused">-</span>
596
+ </div>
597
+ <div class="v2-kv__row">
598
+ <span class="v2-kv__label">Public discovery sources</span>
599
+ <span class="v2-kv__value v2-mono" id="p-sources">-</span>
600
+ </div>
601
+ </div>
602
+ </div>
603
+
604
+ <div class="panel">
605
+ <div class="v2-section__head">
606
+ <span class="v2-section__title">Network I/O</span>
607
+ <span class="v2-section__meta">
608
+ <span class="v2-legend">
609
+ <span class="v2-legend__item"><span class="v2-legend__sw v2-legend__sw--in"></span>In</span>
610
+ <span class="v2-legend__item"><span class="v2-legend__sw v2-legend__sw--out"></span>Out</span>
611
+ </span>
612
+ </span>
613
+ </div>
614
+ <div class="v2-kv">
615
+ <div class="v2-kv__row">
616
+ <span class="v2-kv__label">Inbound</span>
617
+ <span class="v2-kv__value v2-mono" id="net-in">-</span>
618
+ </div>
619
+ <div class="v2-kv__row">
620
+ <span class="v2-kv__label">Outbound</span>
621
+ <span class="v2-kv__value v2-mono" id="net-out">-</span>
622
+ </div>
623
+ </div>
624
+ <div class="v2-bars" id="net-bars" role="img" aria-label="Network throughput history"></div>
625
+ <span class="v2-t-xs v2-mute" id="net-bars-meta">-</span>
626
+ </div>
627
+
628
+ </div>
629
+
630
+ <div class="panel">
631
+ <div class="v2-section__head">
632
+ <span class="v2-section__title">Peer lag - worst first</span>
633
+ <span class="v2-section__meta v2-mono" id="peers-table-meta">-</span>
634
+ </div>
635
+ <div class="v2-table-wrap">
636
+ <table class="v2-table">
637
+ <thead>
638
+ <tr>
639
+ <th scope="col">Peer</th>
640
+ <th scope="col" class="v2-table__num">Head epoch</th>
641
+ <th scope="col" class="v2-table__num">Lag</th>
642
+ <th scope="col" class="v2-table__num">Drift</th>
643
+ <th scope="col" class="v2-table__num">Age</th>
644
+ <th scope="col">Source</th>
645
+ </tr>
646
+ </thead>
647
+ <tbody id="peers-body">
648
+ <tr><td colspan="6" class="v2-mute">Waiting for peer telemetry...</td></tr>
649
+ </tbody>
650
+ </table>
651
+ </div>
652
+ </div>
653
+ </section>
654
+
655
+ <!-- ---------- 5. PROCESS ---------- -->
656
+ <section class="v2-section v2-section--compact" id="process" aria-label="Process">
657
+ <div class="v2-section__head">
658
+ <span class="v2-section__title">
659
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/></svg>
660
+ Node process
661
+ </span>
662
+ <span class="v2-section__meta" id="pr-meta">-</span>
663
+ </div>
664
+
665
+ <div class="v2-stat-strip">
666
+ <div class="v2-stat">
667
+ <span class="v2-stat__label">Status</span>
668
+ <div class="v2-stat__value v2-t-xl" id="pr-status">-</div>
669
+ <span class="v2-t-xs v2-mute" id="pr-name-sub">-</span>
670
+ </div>
671
+ <div class="v2-stat">
672
+ <span class="v2-stat__label">PID</span>
673
+ <div class="v2-stat__value v2-t-xl v2-mono" id="pr-pid">-</div>
674
+ </div>
675
+ <div class="v2-stat">
676
+ <span class="v2-stat__label">Uptime</span>
677
+ <div class="v2-stat__value v2-t-xl v2-mono" id="pr-uptime">-</div>
678
+ </div>
679
+ <div class="v2-stat">
680
+ <span class="v2-stat__label">Restarts</span>
681
+ <div class="v2-stat__value v2-t-xl v2-mono" id="pr-restarts">-</div>
682
+ <span class="v2-t-xs v2-mute">since pm2 start</span>
683
+ </div>
684
+ <div class="v2-stat">
685
+ <span class="v2-stat__label">Process CPU</span>
686
+ <div class="v2-stat__value v2-t-xl v2-mono" id="pr-cpu">-</div>
687
+ <span class="v2-t-xs v2-mute">1 core = 100%</span>
688
+ </div>
689
+ <div class="v2-stat">
690
+ <span class="v2-stat__label">Resident memory</span>
691
+ <div class="v2-stat__value v2-t-xl v2-mono" id="pr-mem">-</div>
692
+ </div>
693
+ </div>
694
+
695
+ <div class="v2-grid v2-grid--2">
696
+
697
+ <div class="panel">
698
+ <div class="v2-section__head">
699
+ <span class="v2-section__title">Runtime</span>
700
+ <span class="v2-section__meta v2-mono" id="pr-runtime-meta">-</span>
701
+ </div>
702
+ <div class="v2-kv">
703
+ <div class="v2-kv__row">
704
+ <span class="v2-kv__label">Process name</span>
705
+ <span class="v2-kv__value v2-mono truncate" id="pr-name">-</span>
706
+ </div>
707
+ <div class="v2-kv__row">
708
+ <span class="v2-kv__label">Exec mode</span>
709
+ <span class="v2-kv__value v2-mono" id="pr-exec">-</span>
710
+ </div>
711
+ <div class="v2-kv__row">
712
+ <span class="v2-kv__label">Instances</span>
713
+ <span class="v2-kv__value v2-mono" id="pr-instances">-</span>
714
+ </div>
715
+ <div class="v2-kv__row">
716
+ <span class="v2-kv__label">Source commit</span>
717
+ <span class="v2-kv__value v2-mono" id="pr-commit">-</span>
718
+ </div>
719
+ <div class="v2-kv__row">
720
+ <span class="v2-kv__label">RPC endpoint</span>
721
+ <span class="v2-kv__value v2-mono" id="pr-rpc">-</span>
722
+ </div>
723
+ </div>
724
+ </div>
725
+
726
+ <div class="panel">
727
+ <div class="v2-section__head">
728
+ <span class="v2-section__title">Log signal - last 120 lines</span>
729
+ <span class="v2-section__meta v2-mono" id="pr-log-meta">-</span>
730
+ </div>
731
+ <div class="v2-kv">
732
+ <div class="v2-kv__row">
733
+ <span class="v2-kv__label">Warnings</span>
734
+ <span class="v2-kv__value" id="pr-warn">-</span>
735
+ </div>
736
+ <div class="v2-kv__row">
737
+ <span class="v2-kv__label">Errors</span>
738
+ <span class="v2-kv__value" id="pr-error">-</span>
739
+ </div>
740
+ <div class="v2-kv__row">
741
+ <span class="v2-kv__label">Last warning</span>
742
+ <span class="v2-kv__value v2-mono truncate" id="pr-last-warn">-</span>
743
+ </div>
744
+ <div class="v2-kv__row">
745
+ <span class="v2-kv__label">Last error</span>
746
+ <span class="v2-kv__value v2-mono truncate" id="pr-last-error">-</span>
747
+ </div>
748
+ </div>
749
+ </div>
750
+
751
+ </div>
752
+ </section>
753
+
754
+
755
+ <!-- ---------- 6. LOGS ---------- -->
756
+ <section class="v2-section v2-section--compact" id="logs" aria-label="Logs">
757
+ <div class="v2-section__head">
758
+ <span class="v2-section__title">
759
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="8" y1="13" x2="16" y2="13"/><line x1="8" y1="17" x2="14" y2="17"/></svg>
760
+ Live logs
761
+ </span>
762
+ <span class="v2-section__meta" id="log-section-meta">-</span>
763
+ </div>
764
+
765
+ <div class="log-toolbar">
766
+ <div class="v2-seg" role="group" aria-label="Log level filter" id="log-filter">
767
+ <button type="button" class="v2-seg__btn v2-seg__btn--active" data-log-level="all">All</button>
768
+ <button type="button" class="v2-seg__btn" data-log-level="warn">Warn</button>
769
+ <button type="button" class="v2-seg__btn" data-log-level="error">Errors</button>
770
+ </div>
771
+ <input class="v2-input log-search" id="log-search" type="search" placeholder="Filter component, event or text..." aria-label="Filter logs" autocomplete="off" />
772
+ <button type="button" class="v2-btn v2-btn--ghost" id="log-pause" aria-pressed="false">
773
+ <svg class="v2-icon v2-icon--14 icon-pause" viewBox="0 0 24 24" aria-hidden="true"><rect x="6" y="4" width="4" height="16" rx="1"/><rect x="14" y="4" width="4" height="16" rx="1"/></svg>
774
+ <svg class="v2-icon v2-icon--14 icon-play" viewBox="0 0 24 24" aria-hidden="true" style="display:none;"><polygon points="6 3 20 12 6 21 6 3"/></svg>
775
+ <span id="log-pause-text">Pause</span>
776
+ </button>
777
+ <span class="v2-t-xs v2-mute log-meta" id="log-meta">-</span>
778
+ </div>
779
+
780
+ <div class="v2-log v2-log--scroll v2-log--bordered" id="log-body" role="log" aria-label="Node log tail">
781
+ <div class="v2-log__empty">Waiting for log stream...</div>
782
+ </div>
783
+ </section>
784
+
785
+
786
+ <!-- ---------- 7. SYSTEM ---------- -->
787
+ <section class="v2-section v2-section--compact" id="system" aria-label="System and identity">
788
+ <div class="v2-section__head">
789
+ <span class="v2-section__title">
790
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg>
791
+ System &amp; identity
792
+ </span>
793
+ <span class="v2-section__meta" id="sys-meta">-</span>
794
+ </div>
795
+
796
+ <div class="v2-grid v2-grid--2">
797
+
798
+ <div class="panel">
799
+ <div class="v2-section__head"><span class="v2-section__title">Node</span></div>
800
+ <div class="v2-kv">
801
+ <div class="v2-kv__row">
802
+ <span class="v2-kv__label">Chain</span>
803
+ <span class="v2-kv__value v2-mono truncate" id="sys-chain">-</span>
804
+ </div>
805
+ <div class="v2-kv__row">
806
+ <span class="v2-kv__label">Role</span>
807
+ <span class="v2-kv__value" id="sys-role">-</span>
808
+ </div>
809
+ <div class="v2-kv__row">
810
+ <span class="v2-kv__label">API port</span>
811
+ <span class="v2-kv__value v2-mono" id="sys-api">-</span>
812
+ </div>
813
+ <div class="v2-kv__row">
814
+ <span class="v2-kv__label">Network version</span>
815
+ <span class="v2-kv__value v2-mono" id="sys-network-version">-</span>
816
+ </div>
817
+ <div class="v2-kv__row">
818
+ <span class="v2-kv__label">Storage backend</span>
819
+ <span class="v2-kv__value v2-mono" id="sys-storage">-</span>
820
+ </div>
821
+ <div class="v2-kv__row">
822
+ <span class="v2-kv__label">Data directory</span>
823
+ <span class="v2-kv__value v2-mono truncate" id="sys-data-dir">-</span>
824
+ </div>
825
+ </div>
826
+ </div>
827
+
828
+ <div class="panel">
829
+ <div class="v2-section__head"><span class="v2-section__title">Host</span></div>
830
+ <div class="v2-kv">
831
+ <div class="v2-kv__row">
832
+ <span class="v2-kv__label">Hostname</span>
833
+ <span class="v2-kv__value v2-mono" id="sys-hostname">-</span>
834
+ </div>
835
+ <div class="v2-kv__row">
836
+ <span class="v2-kv__label">Operating system</span>
837
+ <span class="v2-kv__value truncate" id="sys-os">-</span>
838
+ </div>
839
+ <div class="v2-kv__row">
840
+ <span class="v2-kv__label">Kernel</span>
841
+ <span class="v2-kv__value v2-mono truncate" id="sys-kernel">-</span>
842
+ </div>
843
+ <div class="v2-kv__row">
844
+ <span class="v2-kv__label">Architecture</span>
845
+ <span class="v2-kv__value v2-mono" id="sys-arch">-</span>
846
+ </div>
847
+ <div class="v2-kv__row">
848
+ <span class="v2-kv__label">CPU cores</span>
849
+ <span class="v2-kv__value v2-mono" id="sys-cores">-</span>
850
+ </div>
851
+ <div class="v2-kv__row">
852
+ <span class="v2-kv__label">System uptime</span>
853
+ <span class="v2-kv__value v2-mono" id="sys-uptime">-</span>
854
+ </div>
855
+ </div>
856
+ </div>
857
+
858
+ </div>
859
+
860
+
861
+ <div class="v2-grid v2-grid--2">
862
+
863
+ <div class="panel">
864
+ <div class="v2-section__head"><span class="v2-section__title">Ledger</span></div>
865
+ <div class="v2-kv">
866
+ <div class="v2-kv__row">
867
+ <span class="v2-kv__label">Accounts</span>
868
+ <span class="v2-kv__value v2-mono" id="sys-accounts">-</span>
869
+ </div>
870
+ <div class="v2-kv__row">
871
+ <span class="v2-kv__label">Active accounts</span>
872
+ <span class="v2-kv__value v2-mono" id="sys-active-accounts">-</span>
873
+ </div>
874
+ <div class="v2-kv__row">
875
+ <span class="v2-kv__label">Total supply</span>
876
+ <span class="v2-kv__value v2-mono" id="sys-supply">-</span>
877
+ </div>
878
+ <div class="v2-kv__row">
879
+ <span class="v2-kv__label">Circulating supply</span>
880
+ <span class="v2-kv__value v2-mono" id="sys-circulating">-</span>
881
+ </div>
882
+ <div class="v2-kv__row">
883
+ <span class="v2-kv__label">Encrypted supply</span>
884
+ <span class="v2-kv__value v2-mono" id="sys-encrypted">-</span>
885
+ </div>
886
+ <div class="v2-kv__row">
887
+ <span class="v2-kv__label">Txid high-water mark</span>
888
+ <span class="v2-kv__value v2-mono" id="sys-txid">-</span>
889
+ </div>
890
+ </div>
891
+ </div>
892
+
893
+ <div class="panel">
894
+ <div class="v2-section__head"><span class="v2-section__title">Commitments</span></div>
895
+ <div class="v2-kv">
896
+ <div class="v2-kv__row">
897
+ <span class="v2-kv__label">State root</span>
898
+ <span class="v2-kv__value hash-cell">
899
+ <span class="v2-mono truncate" id="sys-state-root">-</span>
900
+ <button type="button" class="v2-btn v2-btn--icon copy-btn" id="copy-state-root" aria-label="Copy state root" data-v2-copy="" data-v2-copy-label="State root copied">
901
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
902
+ </button>
903
+ </span>
904
+ </div>
905
+ <div class="v2-kv__row">
906
+ <span class="v2-kv__label">Irmin commit</span>
907
+ <span class="v2-kv__value hash-cell">
908
+ <span class="v2-mono truncate" id="sys-irmin">-</span>
909
+ <button type="button" class="v2-btn v2-btn--icon copy-btn" id="copy-irmin" aria-label="Copy irmin commit" data-v2-copy="" data-v2-copy-label="Irmin commit copied">
910
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
911
+ </button>
912
+ </span>
913
+ </div>
914
+ <div class="v2-kv__row">
915
+ <span class="v2-kv__label">Source commit</span>
916
+ <span class="v2-kv__value v2-mono" id="sys-commit">-</span>
917
+ </div>
918
+ <div class="v2-kv__row">
919
+ <span class="v2-kv__label">Backend service</span>
920
+ <span class="v2-kv__value v2-mono" id="sys-backend">-</span>
921
+ </div>
922
+ <div class="v2-kv__row">
923
+ <span class="v2-kv__label">Backend availability</span>
924
+ <span class="v2-kv__value v2-mono" id="sys-backend-avail">-</span>
925
+ </div>
926
+ </div>
927
+ </div>
928
+
929
+ </div>
930
+
931
+ <p class="v2-t-xs v2-mute sys-foot" id="sys-foot">Octra live monitor - read-only telemetry from the node RPC, /proc and pm2.</p>
932
+ </section>
933
+
934
+ <!-- ---------- 8. WALLETS ---------- -->
935
+ <section class="v2-section v2-section--compact" id="wallets" aria-label="Wallet and rewards">
936
+ <div class="v2-section__head">
937
+ <span class="v2-section__title">
938
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 12V7H5a2 2 0 0 1 0-4h14v4"/><path d="M3 5v14a2 2 0 0 0 2 2h16v-5"/><path d="M18 12a2 2 0 0 0 0 4h4v-4z"/></svg>
939
+ Wallet &amp; rewards
940
+ </span>
941
+ <span class="v2-section__meta" id="wal-meta">-</span>
942
+ </div>
943
+
944
+ <div class="v2-stat-strip">
945
+ <div class="v2-stat">
946
+ <span class="v2-stat__label">
947
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 12V7H5a2 2 0 0 1 0-4h14v4"/><path d="M3 5v14a2 2 0 0 0 2 2h16v-5"/><path d="M18 12a2 2 0 0 0 0 4h4v-4z"/></svg>
948
+ Balance
949
+ </span>
950
+ <div class="v2-stat__value" id="wal-balance">-</div>
951
+ <span class="v2-t-xs v2-mute" id="wal-balance-sub">raw -</span>
952
+ </div>
953
+ <div class="v2-stat">
954
+ <span class="v2-stat__label">
955
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="11" width="18" height="10" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
956
+ Bonded
957
+ </span>
958
+ <div class="v2-stat__value" id="wal-bond">-</div>
959
+ <span class="v2-t-xs v2-mute" id="wal-bond-sub">-</span>
960
+ </div>
961
+ <div class="v2-stat">
962
+ <span class="v2-stat__label">
963
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><path d="M4 4h16v4H4z"/><path d="M4 12h16"/><path d="M4 20h10"/></svg>
964
+ Nonce / tx count
965
+ </span>
966
+ <div class="v2-stat__value v2-mono" id="wal-nonce">-</div>
967
+ <span class="v2-t-xs v2-mute" id="wal-nonce-sub">-</span>
968
+ </div>
969
+ <div class="v2-stat">
970
+ <span class="v2-stat__label">
971
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2 3 7l9 5 9-5z"/><path d="m3 12 9 5 9-5"/><path d="m3 17 9 5 9-5"/></svg>
972
+ Proposer count
973
+ </span>
974
+ <div class="v2-stat__value v2-mono" id="wal-proposals">-</div>
975
+ <span class="v2-t-xs v2-mute" id="wal-proposals-sub">-</span>
976
+ </div>
977
+ <div class="v2-stat">
978
+ <span class="v2-stat__label">
979
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2v20"/><path d="M17 6H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
980
+ Total reward
981
+ </span>
982
+ <div class="v2-stat__value" id="wal-reward">-</div>
983
+ <span class="v2-t-xs v2-mute" id="wal-reward-sub">-</span>
984
+ <span class="v2-t-xs v2-mute" id="wal-reward-tag">-</span>
985
+ </div>
986
+ <div class="v2-stat">
987
+ <span class="v2-stat__label">
988
+ <svg class="v2-icon v2-icon--14 v2-icon--mute" viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><polyline points="12 7 12 12 15 14"/></svg>
989
+ Est. reward / day
990
+ </span>
991
+ <div class="v2-stat__value" id="wal-reward-rate">-</div>
992
+ <span class="v2-t-xs v2-mute" id="wal-reward-rate-sub">-</span>
993
+ </div>
994
+ </div>
995
+
996
+ <div class="v2-grid v2-grid--2">
997
+
998
+ <div class="panel">
999
+ <div class="v2-section__head">
1000
+ <span class="v2-section__title">Account</span>
1001
+ <span class="v2-section__meta"><span class="v2-badge" id="wal-state">-</span></span>
1002
+ </div>
1003
+ <div class="v2-kv">
1004
+ <div class="v2-kv__row">
1005
+ <span class="v2-kv__label">Address</span>
1006
+ <span class="v2-kv__value hash-cell">
1007
+ <span class="v2-mono truncate" id="wal-address">-</span>
1008
+ <button type="button" class="v2-btn v2-btn--icon copy-btn" id="wal-copy-address" aria-label="Copy wallet address" data-v2-copy="" data-v2-copy-label="Address copied">
1009
+ <svg class="v2-icon v2-icon--14" viewBox="0 0 24 24" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
1010
+ </button>
1011
+ </span>
1012
+ </div>
1013
+ <div class="v2-kv__row">
1014
+ <span class="v2-kv__label">Balance raw</span>
1015
+ <span class="v2-kv__value v2-mono" id="wal-balance-raw">-</span>
1016
+ </div>
1017
+ <div class="v2-kv__row">
1018
+ <span class="v2-kv__label">Balance + bond</span>
1019
+ <span class="v2-kv__value v2-mono" id="wal-holdings">-</span>
1020
+ </div>
1021
+ <div class="v2-kv__row">
1022
+ <span class="v2-kv__label">Pending nonce</span>
1023
+ <span class="v2-kv__value v2-mono" id="wal-pending">-</span>
1024
+ </div>
1025
+ <div class="v2-kv__row">
1026
+ <span class="v2-kv__label">Transactions</span>
1027
+ <span class="v2-kv__value v2-mono" id="wal-tx-count">-</span>
1028
+ </div>
1029
+ <div class="v2-kv__row">
1030
+ <span class="v2-kv__label">Public key</span>
1031
+ <span class="v2-kv__value" id="wal-pubkey">-</span>
1032
+ </div>
1033
+ <div class="v2-kv__row">
1034
+ <span class="v2-kv__label">Encrypted balance</span>
1035
+ <span class="v2-kv__value" id="wal-encrypted">-</span>
1036
+ </div>
1037
+ </div>
1038
+ </div>
1039
+
1040
+ <div class="panel">
1041
+ <div class="v2-section__head">
1042
+ <span class="v2-section__title">Stake &amp; duty</span>
1043
+ <span class="v2-section__meta v2-mono" id="wal-duty">-</span>
1044
+ </div>
1045
+ <div class="v2-kv">
1046
+ <div class="v2-kv__row">
1047
+ <span class="v2-kv__label">Bond raw</span>
1048
+ <span class="v2-kv__value v2-mono" id="wal-bond-raw">-</span>
1049
+ </div>
1050
+ <div class="v2-kv__row">
1051
+ <span class="v2-kv__label">Bonded epoch</span>
1052
+ <span class="v2-kv__value v2-mono" id="wal-bonded-epoch">-</span>
1053
+ </div>
1054
+ <div class="v2-kv__row">
1055
+ <span class="v2-kv__label">Ready epoch</span>
1056
+ <span class="v2-kv__value v2-mono" id="wal-ready-epoch">-</span>
1057
+ </div>
1058
+ <div class="v2-kv__row">
1059
+ <span class="v2-kv__label">Epochs in set</span>
1060
+ <span class="v2-kv__value v2-mono" id="wal-epochs-in-set">-</span>
1061
+ </div>
1062
+ <div class="v2-kv__row">
1063
+ <span class="v2-kv__label">Membership</span>
1064
+ <span class="v2-kv__value" id="wal-membership">-</span>
1065
+ </div>
1066
+ <div class="v2-kv__row">
1067
+ <span class="v2-kv__label">Activate / next set</span>
1068
+ <span class="v2-kv__value v2-mono" id="wal-next-set">-</span>
1069
+ </div>
1070
+ <div class="v2-kv__row">
1071
+ <span class="v2-kv__label">Exit epoch</span>
1072
+ <span class="v2-kv__value v2-mono" id="wal-exit">-</span>
1073
+ </div>
1074
+ </div>
1075
+ </div>
1076
+
1077
+ </div>
1078
+
1079
+ <div class="v2-grid v2-grid--2">
1080
+
1081
+ <div class="panel">
1082
+ <div class="v2-section__head">
1083
+ <span class="v2-section__title">Reward attribution</span>
1084
+ <span class="v2-section__meta v2-mono" id="wal-reward-meta">-</span>
1085
+ </div>
1086
+ <div class="v2-kv">
1087
+ <div class="v2-kv__row">
1088
+ <span class="v2-kv__label">As proposer</span>
1089
+ <span class="v2-kv__value v2-mono" id="wal-reward-proposer">-</span>
1090
+ </div>
1091
+ <div class="v2-kv__row">
1092
+ <span class="v2-kv__label">As validator</span>
1093
+ <span class="v2-kv__value v2-mono" id="wal-reward-validator">-</span>
1094
+ </div>
1095
+ <div class="v2-kv__row">
1096
+ <span class="v2-kv__label">Average / epoch</span>
1097
+ <span class="v2-kv__value v2-mono" id="wal-avg">-</span>
1098
+ </div>
1099
+ <div class="v2-kv__row">
1100
+ <span class="v2-kv__label">Proposer share</span>
1101
+ <span class="v2-kv__value v2-mono" id="wal-share">-</span>
1102
+ </div>
1103
+ <div class="v2-kv__row">
1104
+ <span class="v2-kv__label">Last reward</span>
1105
+ <span class="v2-kv__value v2-mono" id="wal-last-reward">-</span>
1106
+ </div>
1107
+ <div class="v2-kv__row">
1108
+ <span class="v2-kv__label">Last reward role</span>
1109
+ <span class="v2-kv__value" id="wal-last-role">-</span>
1110
+ </div>
1111
+ </div>
1112
+ </div>
1113
+
1114
+ <div class="panel">
1115
+ <div class="v2-section__head">
1116
+ <span class="v2-section__title">Baseline &amp; log index</span>
1117
+ <span class="v2-section__meta v2-mono" id="wal-baseline-age">-</span>
1118
+ </div>
1119
+ <div class="v2-kv">
1120
+ <div class="v2-kv__row">
1121
+ <span class="v2-kv__label">Baseline balance</span>
1122
+ <span class="v2-kv__value v2-mono" id="wal-baseline">-</span>
1123
+ </div>
1124
+ <div class="v2-kv__row">
1125
+ <span class="v2-kv__label">Baseline epoch</span>
1126
+ <span class="v2-kv__value v2-mono" id="wal-baseline-epoch">-</span>
1127
+ </div>
1128
+ <div class="v2-kv__row">
1129
+ <span class="v2-kv__label">Balance delta since baseline</span>
1130
+ <span class="v2-kv__value v2-mono" id="wal-delta">-</span>
1131
+ </div>
1132
+ <div class="v2-kv__row">
1133
+ <span class="v2-kv__label">Indexed log</span>
1134
+ <span class="v2-kv__value v2-mono" id="wal-index">-</span>
1135
+ </div>
1136
+ <div class="v2-kv__row">
1137
+ <span class="v2-kv__label">Reward epoch window</span>
1138
+ <span class="v2-kv__value v2-mono" id="wal-epoch-span">-</span>
1139
+ </div>
1140
+ <div class="v2-kv__row">
1141
+ <span class="v2-kv__label">Tracking since</span>
1142
+ <span class="v2-kv__value v2-mono" id="wal-since">-</span>
1143
+ </div>
1144
+ <div class="v2-kv__row">
1145
+ <span class="v2-kv__label">Log path</span>
1146
+ <span class="v2-kv__value v2-mono truncate" id="wal-log">-</span>
1147
+ </div>
1148
+ <div class="v2-kv__row">
1149
+ <span class="v2-kv__label">Rewards in the log (gross fold)</span>
1150
+ <span class="v2-kv__value v2-mono" id="wal-log-total">-</span>
1151
+ </div>
1152
+ <div class="v2-kv__row">
1153
+ <span class="v2-kv__label">Observed share of that fold</span>
1154
+ <span class="v2-kv__value v2-mono" id="wal-log-ratio">-</span>
1155
+ </div>
1156
+ </div>
1157
+ </div>
1158
+
1159
+ </div>
1160
+
1161
+ <div class="panel">
1162
+ <div class="v2-section__head">
1163
+ <span class="v2-section__title">Epoch rewards - newest first</span>
1164
+ <span class="v2-section__meta v2-mono" id="wal-rewards-meta">-</span>
1165
+ </div>
1166
+ <div class="v2-table-wrap">
1167
+ <table class="v2-table">
1168
+ <thead>
1169
+ <tr>
1170
+ <th scope="col" class="v2-table__num">Epoch</th>
1171
+ <th scope="col">Role</th>
1172
+ <th scope="col" class="v2-table__num">Reward</th>
1173
+ <th scope="col" class="v2-table__num">Finalized</th>
1174
+ </tr>
1175
+ </thead>
1176
+ <tbody id="wal-rewards-body">
1177
+ <tr><td colspan="4" class="v2-mute">Waiting for wallet telemetry...</td></tr>
1178
+ </tbody>
1179
+ </table>
1180
+ </div>
1181
+ </div>
1182
+
1183
+ <p class="v2-t-xs v2-mute sys-foot" id="wal-foot">-</p>
1184
+
1185
+ </section>
1186
+
1187
+ <div class="content-pad" aria-hidden="true"></div>
1188
+ </div><!-- /.v2-content -->
1189
+ </main>
1190
+
1191
+ </div><!-- /.v2-app -->
1192
+
1193
+ <script src="assets/v2.2/js/synteq-ui-v2.js"></script>
1194
+ <script src="app.js?v=2.7.0"></script>
1195
+ </body>
1196
+ </html>
1197
+