From 5ebccceffca24925cb2e7d14e530202faf25ba99 Mon Sep 17 00:00:00 2001 From: DanS Date: Sat, 4 Apr 2026 11:29:12 -0500 Subject: [PATCH] refactor: move AI/agent files into ObsidianDragon-agent/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - copilot-instructions.md → ObsidianDragon-agent/copilot-instructions.md - ARCHITECTURE.md → ObsidianDragon-agent/ARCHITECTURE.md - Symlinks at original locations preserve Copilot auto-discovery --- .github/copilot-instructions.md | 176 +------------------ ObsidianDragon-agent/ARCHITECTURE.md | 154 ++++++++++++++++ ObsidianDragon-agent/copilot-instructions.md | 175 ++++++++++++++++++ docs/ARCHITECTURE.md | 155 +--------------- 4 files changed, 331 insertions(+), 329 deletions(-) mode change 100644 => 120000 .github/copilot-instructions.md create mode 100644 ObsidianDragon-agent/ARCHITECTURE.md create mode 100644 ObsidianDragon-agent/copilot-instructions.md mode change 100644 => 120000 docs/ARCHITECTURE.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index f2e0e82..0000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,175 +0,0 @@ -# ObsidianDragon — Coding Standards & Architecture - -## Project Identity - -ObsidianDragon is a native C++17 desktop wallet for the DragonX (DRGX) cryptocurrency. -It uses ImGui (immediate-mode GUI) with SDL3, ships an embedded full-node daemon (`dragonxd`), -and includes an integrated CPU miner (`xmrig-hac`). Licensed GPLv3. - -Platforms: Linux (x86_64), Windows (x86_64, cross-compiled via MinGW), macOS (universal arm64+x86_64). - -## Code Style - -### Naming -- **Classes/structs/enums:** `CamelCase` — `RPCClient`, `WalletState`, `NavPage` -- **Member variables:** `snake_case_` with trailing underscore — `rpc_`, `connection_status_`, `fast_worker_` -- **Functions/methods:** `camelCase` — `tryConnect()`, `isConnected()`, `drainResults()` -- **Constants:** `UPPER_SNAKE` for macros, `camelCase` for const vars — `REFRESH_INTERVAL`, `DEFAULT_FEE` -- **Enum values:** `CamelCase` — `NavPage::Overview`, `State::Running` -- **Type aliases:** `using MainCb = std::function;` - -### Formatting -- 4-space indentation, no tabs -- Opening brace on same line: `void foo() {` -- `#pragma once` (not include guards) -- Include order: self header, standard library, third-party, project headers - -### Memory & Ownership -- `std::unique_ptr` for ownership — never raw `new`/`delete` -- Raw pointers for non-owning references (e.g., function parameters) -- RAII for all resource management (threads, handles, mutexes) - -### Documentation -- `///` Doxygen comments on public APIs in headers -- Implementation files: explain *why*, not *what* -- Use `DEBUG_LOGF()` for debug logging, not `printf`/`std::cout` - -## Threading Model - -**Main thread** — ImGui render loop (`App::update()`), all UI code, `drainResults()` callbacks. -Never block this thread with network I/O or disk I/O. - -**`worker_`** (RPCWorker) — General-purpose background thread for batched RPC polling. -Executes the `refreshData()` cycle every 5 seconds. - -**`fast_worker_`** (RPCWorker) — Fast-lane background thread for latency-sensitive operations: -console commands, mining hashrate polls. Avoids head-of-line blocking behind main refresh batch. - -**Monitor threads** — `EmbeddedDaemon` and `XmrigManager` each spawn a monitor thread -to read stdout/stderr pipes from their child processes. - -### Work Submission Pattern -```cpp -// Post work to background thread; return a callback for the main thread -worker_->post([this]() -> rpc::RPCWorker::MainCb { - json result = rpc_->call("getinfo"); // Runs on worker thread (blocking OK) - return [this, result]() { - state_.connected = true; // Runs on main thread via drainResults() - }; -}); -``` -`drainResults()` is called each frame in `App::update()` to execute completed callbacks. - -## RPC Architecture - -**Dual-client design:** -- `rpc_` + `worker_` — main polling (balance, transactions, sync status) -- `fast_rpc_` + `fast_worker_` — console commands, mining stats - -Both are `RPCClient` instances wrapping libcurl for JSON-RPC over HTTPS. - -**Callback types:** -```cpp -using Callback = std::function; -using ErrorCallback = std::function; -``` - -**Error flow:** RPC errors throw `std::runtime_error` → caught in `doRPC()` → invokes -`ErrorCallback` → surfaces via `Notifications::instance().error(msg)`. - -**Connection state:** `state_.connected` (app-level, set in `onConnected()`) vs -`rpc_->isConnected()` (per-client, set after successful `getinfo()`). These can differ — -always check the right one for the context. - -## Connection Lifecycle - -``` -[Disconnected] → tryConnect() every 5s - → auto-detect DRAGONX.conf (host, port, rpcuser, rpcpassword) - → if no config: start embedded daemon → retry - → post async rpc_->connect() to worker_ - → success: onConnected() → state_.connected = true - → auth 401: try .cookie auth → retry - → failure: onDisconnected(reason) → may restart daemon -``` - -## UI Patterns - -### Page Routing -`NavPage` enum in `src/ui/sidebar.h` defines all pages. `App::update()` dispatches -via switch on `current_page_` to render functions like `RenderBalanceTab(this)` or -`console_tab_.render(...)`. - -### Dialogs -Modal dialogs use `show_*` boolean flags (e.g., `show_import_key_`, `show_backup_`). -Set the flag to `true` to open; the dialog renders in `App::update()` and clears -the flag when dismissed. - -### Notifications -```cpp -Notifications::instance().success("Transaction sent"); -Notifications::instance().error("Insufficient funds"); -``` -Toast-style popups in the bottom-right corner. - -### Lock Screen & Loading Overlay -- Lock screen gates all interaction when `state_.isLocked()` -- Loading overlay shown while daemon isn't ready, gates all tabs except Peers, Console, Settings - -## Platform Abstractions - -Detection: `#ifdef _WIN32` / `#elif __APPLE__` / `#elif __linux__` - -Platform-specific files live in `src/platform/` (Windows only: DX11 context, backdrop effects). -Shared platform utilities in `src/util/platform.h` — `openUrl()`, `getHomeDir()`, `getDragonXDataDir()`. - -Rendering backends: -- Windows: DirectX 11 (`imgui_impl_dx11`) -- macOS/Linux: OpenGL 3 (`imgui_impl_opengl3`) + GLAD loader - -## Build System - -CMake 3.20+, C++17. Single `CMakeLists.txt` at root. - -**FetchContent dependencies:** SDL3, nlohmann/json v3.11.3, toml++ v3.4.0, libcurl (Windows only) -**Bundled libraries:** ImGui, GLAD, miniz, libsodium (pre-built per platform), qrcode - -**macOS:** Universal binary (arm64+x86_64), deployment target 11.0 (Big Sur+). -Set `CMAKE_OSX_DEPLOYMENT_TARGET` and `CMAKE_OSX_ARCHITECTURES` before `project()`. - -**Build commands:** -```bash -./build.sh # Dev build -./build.sh --mac-release # macOS universal .app + DMG -./build.sh --linux-release # Linux AppImage + zip -./build.sh --win-release # Windows cross-compile -``` - -## Theme System - -UI layout values are defined in `res/themes/ui.toml` and accessed via `schema::UI()` — -**never hardcode pixel sizes in C++ code**. - -Skins are self-contained TOML files in `res/themes/` defining color palettes. -`scripts/expand_themes.py` merges layout sections from `ui.toml` into each skin at build time. - -Colors support CSS-style variables: `--primary`, `--surface`, `--on-surface-medium`, resolved -by `ColorVarResolver` at runtime. - -## Internationalization - -All user-visible strings use `TR("key")` macro → `dragonx::util::tr()` → lookup in -`I18n` singleton. Never hardcode English strings in UI code. - -Language files: `res/lang/{locale}.json` (runtime) with embedded fallback compiled into binary. -Supported: en, es, zh, ru, de, fr, pt, ja, ko. - -## Key Rules - -1. **Never block the main thread** — all network/disk I/O goes through `worker_->post()` -2. **Never hardcode pixel sizes** — use `ui.toml` schema values via `schema::UI()` -3. **Always use `TR()` for strings** — no hardcoded English in UI rendering code -4. **Use `ICON_MD_*` for icons** — Material Design icon font, never raw Unicode -5. **Use `std::unique_ptr`** — no raw `new`/`delete` in application code -6. **Check the right connection state** — `state_.connected` for app-level, `rpc_->isConnected()` for per-client -7. **Test all three platforms** — build must pass Linux; cross-compile test if touching platform code diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 120000 index 0000000..e881900 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1 @@ +../ObsidianDragon-agent/copilot-instructions.md \ No newline at end of file diff --git a/ObsidianDragon-agent/ARCHITECTURE.md b/ObsidianDragon-agent/ARCHITECTURE.md new file mode 100644 index 0000000..b6a9d78 --- /dev/null +++ b/ObsidianDragon-agent/ARCHITECTURE.md @@ -0,0 +1,154 @@ +# ObsidianDragon — Architecture Guide + +A native C++17 desktop wallet for DragonX (DRGX), built with ImGui + SDL3. + +## Directory Layout + +``` +src/ +├── main.cpp Entry point, SDL3/backend init, render loop +├── app.h / app.cpp App class: init, shutdown, frame dispatch +├── app_network.cpp RPC connection, data refresh, mining ops +├── app_security.cpp Encryption, lock screen, PIN management +├── app_wizard.cpp First-run setup wizard +├── config/ +│ └── settings.h/.cpp JSON settings persistence (~/.config/ObsidianDragon/) +├── daemon/ +│ ├── embedded_daemon.h/.cpp dragonxd process lifecycle +│ └── xmrig_manager.h/.cpp xmrig-hac pool mining management +├── rpc/ +│ ├── rpc_client.h/.cpp JSON-RPC over HTTPS (libcurl) +│ ├── rpc_worker.h/.cpp Background work queue + main-thread drain +│ ├── connection.h/.cpp DRAGONX.conf auto-detection +│ └── types.h Transaction, address data types +├── ui/ +│ ├── sidebar.h NavPage enum, sidebar rendering +│ ├── notifications.h/.cpp Toast notification system +│ ├── schema/ +│ │ ├── ui_schema.h/.cpp UISchema singleton (TOML → typed lookups) +│ │ ├── skin_manager.h/.cpp Skin enumeration, switching, import +│ │ └── color_var_resolver.h/.cpp CSS-style color resolution +│ └── windows/ Per-tab render functions (console, settings, etc.) +├── util/ +│ ├── i18n.h/.cpp Internationalization (TR() macro, I18n singleton) +│ ├── platform.h/.cpp Cross-platform utilities (paths, URLs) +│ └── logger.h DEBUG_LOGF / VERBOSE_LOGF macros +├── platform/ Windows-specific (DX11 context, backdrop effects) +├── embedded/ Build-generated headers (embedded resources) +└── resources/ Runtime resource loading (fonts, images) +``` + +## Threading Model + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Main Thread (UI) │ +│ • ImGui render loop (App::update()) │ +│ • drainResults() each frame → executes completed callbacks │ +│ • NEVER does blocking I/O │ +└────────────┬────────────────────────┬───────────────────────┘ + │ post() │ post() + ▼ ▼ +┌────────────────────┐ ┌────────────────────────────────┐ +│ worker_ (RPCWorker)│ │ fast_worker_ (RPCWorker) │ +│ General RPC polling│ │ Console commands, hashrate │ +│ refreshData() 5s │ │ Avoids head-of-line blocking │ +└────────────────────┘ └────────────────────────────────┘ + +┌────────────────────────────────────────────┐ +│ Monitor Threads (per child process) │ +│ • EmbeddedDaemon: reads dragonxd stdout │ +│ • XmrigManager: reads xmrig-hac stdout │ +└────────────────────────────────────────────┘ +``` + +### Work Submission Pattern + +```cpp +worker_->post([this]() -> rpc::RPCWorker::MainCb { + json result = rpc_->call("getinfo"); // Runs on worker thread + return [this, result]() { + state_.connected = true; // Runs on main thread + }; +}); +``` + +## RPC Architecture + +**Dual-client design** avoids head-of-line blocking: + +| Client | Worker | Purpose | +|--------|--------|---------| +| `rpc_` | `worker_` | Main polling: balance, transactions, sync status | +| `fast_rpc_` | `fast_worker_` | Console commands, mining stats | + +Both are `RPCClient` instances wrapping libcurl for JSON-RPC over HTTPS to `dragonxd`. + +**Error flow:** `RPCClient::call()` throws `std::runtime_error` → +caught in worker lambda → error string captured → `MainCb` calls +`Notifications::instance().error(msg)` on main thread. + +## Connection Lifecycle + +``` +[Disconnected] → tryConnect() every 5s + → auto-detect DRAGONX.conf (host, port, rpcuser, rpcpassword) + → if no config: start embedded daemon → retry + → post async rpc_->connect() to worker_ + → success: onConnected() → state_.connected = true + → auth 401: try .cookie auth → retry + → failure: onDisconnected(reason) → may restart daemon +``` + +## UI System + +### Page Routing +`NavPage` enum defines all pages. `App::update()` dispatches via switch on +`current_page_` to render functions (e.g., `RenderBalanceTab(this)`). + +### Theme System +- Layout defined in `res/themes/ui.toml`, accessed via `schema::UI()` +- Skins are TOML files in `res/themes/` defining color palettes +- `scripts/expand_themes.py` merges layout into skins at build time +- Colors support CSS-style variables resolved by `ColorVarResolver` +- Hot-reload: `UISchema::pollForChanges()` watches file mtime + +### Internationalization +- All UI strings use `TR("key")` macro → `I18n` singleton lookup +- Language files: `res/lang/{locale}.json` with compiled-in fallbacks +- Supported: en, es, zh, ru, de, fr, pt, ja, ko + +### Notifications +```cpp +Notifications::instance().success("Transaction sent"); +Notifications::instance().error("Insufficient funds"); +``` +Toast-style popups, bottom-right corner, 5-second default duration. + +## Build System + +CMake 3.20+, C++17. FetchContent for SDL3, nlohmann/json, toml++. +Bundled: ImGui, GLAD, miniz, libsodium, qrcode. + +```bash +./build.sh # Dev build +./build.sh --mac-release # macOS universal .app + DMG +./build.sh --linux-release # Linux AppImage + zip +./build.sh --win-release # Windows cross-compile (MinGW) +``` + +### Platform Backends +| Platform | Renderer | Notes | +|----------|----------|-------| +| Windows | DirectX 11 | `imgui_impl_dx11`, backdrop effects | +| macOS | OpenGL 3 | Universal binary (arm64+x86_64), target 11.0+ | +| Linux | OpenGL 3 | GLAD loader | + +## Key Conventions + +1. **Never block the main thread** — all I/O goes through `worker_->post()` +2. **Never hardcode pixel sizes** — use `schema::UI()` lookups from `ui.toml` +3. **Always use `TR()` for strings** — no hardcoded English in UI code +4. **Use `ICON_MD_*` for icons** — Material Design icon font +5. **`std::unique_ptr` for ownership** — no raw `new`/`delete` +6. **Check the right connection state** — `state_.connected` vs `rpc_->isConnected()` diff --git a/ObsidianDragon-agent/copilot-instructions.md b/ObsidianDragon-agent/copilot-instructions.md new file mode 100644 index 0000000..f2e0e82 --- /dev/null +++ b/ObsidianDragon-agent/copilot-instructions.md @@ -0,0 +1,175 @@ +# ObsidianDragon — Coding Standards & Architecture + +## Project Identity + +ObsidianDragon is a native C++17 desktop wallet for the DragonX (DRGX) cryptocurrency. +It uses ImGui (immediate-mode GUI) with SDL3, ships an embedded full-node daemon (`dragonxd`), +and includes an integrated CPU miner (`xmrig-hac`). Licensed GPLv3. + +Platforms: Linux (x86_64), Windows (x86_64, cross-compiled via MinGW), macOS (universal arm64+x86_64). + +## Code Style + +### Naming +- **Classes/structs/enums:** `CamelCase` — `RPCClient`, `WalletState`, `NavPage` +- **Member variables:** `snake_case_` with trailing underscore — `rpc_`, `connection_status_`, `fast_worker_` +- **Functions/methods:** `camelCase` — `tryConnect()`, `isConnected()`, `drainResults()` +- **Constants:** `UPPER_SNAKE` for macros, `camelCase` for const vars — `REFRESH_INTERVAL`, `DEFAULT_FEE` +- **Enum values:** `CamelCase` — `NavPage::Overview`, `State::Running` +- **Type aliases:** `using MainCb = std::function;` + +### Formatting +- 4-space indentation, no tabs +- Opening brace on same line: `void foo() {` +- `#pragma once` (not include guards) +- Include order: self header, standard library, third-party, project headers + +### Memory & Ownership +- `std::unique_ptr` for ownership — never raw `new`/`delete` +- Raw pointers for non-owning references (e.g., function parameters) +- RAII for all resource management (threads, handles, mutexes) + +### Documentation +- `///` Doxygen comments on public APIs in headers +- Implementation files: explain *why*, not *what* +- Use `DEBUG_LOGF()` for debug logging, not `printf`/`std::cout` + +## Threading Model + +**Main thread** — ImGui render loop (`App::update()`), all UI code, `drainResults()` callbacks. +Never block this thread with network I/O or disk I/O. + +**`worker_`** (RPCWorker) — General-purpose background thread for batched RPC polling. +Executes the `refreshData()` cycle every 5 seconds. + +**`fast_worker_`** (RPCWorker) — Fast-lane background thread for latency-sensitive operations: +console commands, mining hashrate polls. Avoids head-of-line blocking behind main refresh batch. + +**Monitor threads** — `EmbeddedDaemon` and `XmrigManager` each spawn a monitor thread +to read stdout/stderr pipes from their child processes. + +### Work Submission Pattern +```cpp +// Post work to background thread; return a callback for the main thread +worker_->post([this]() -> rpc::RPCWorker::MainCb { + json result = rpc_->call("getinfo"); // Runs on worker thread (blocking OK) + return [this, result]() { + state_.connected = true; // Runs on main thread via drainResults() + }; +}); +``` +`drainResults()` is called each frame in `App::update()` to execute completed callbacks. + +## RPC Architecture + +**Dual-client design:** +- `rpc_` + `worker_` — main polling (balance, transactions, sync status) +- `fast_rpc_` + `fast_worker_` — console commands, mining stats + +Both are `RPCClient` instances wrapping libcurl for JSON-RPC over HTTPS. + +**Callback types:** +```cpp +using Callback = std::function; +using ErrorCallback = std::function; +``` + +**Error flow:** RPC errors throw `std::runtime_error` → caught in `doRPC()` → invokes +`ErrorCallback` → surfaces via `Notifications::instance().error(msg)`. + +**Connection state:** `state_.connected` (app-level, set in `onConnected()`) vs +`rpc_->isConnected()` (per-client, set after successful `getinfo()`). These can differ — +always check the right one for the context. + +## Connection Lifecycle + +``` +[Disconnected] → tryConnect() every 5s + → auto-detect DRAGONX.conf (host, port, rpcuser, rpcpassword) + → if no config: start embedded daemon → retry + → post async rpc_->connect() to worker_ + → success: onConnected() → state_.connected = true + → auth 401: try .cookie auth → retry + → failure: onDisconnected(reason) → may restart daemon +``` + +## UI Patterns + +### Page Routing +`NavPage` enum in `src/ui/sidebar.h` defines all pages. `App::update()` dispatches +via switch on `current_page_` to render functions like `RenderBalanceTab(this)` or +`console_tab_.render(...)`. + +### Dialogs +Modal dialogs use `show_*` boolean flags (e.g., `show_import_key_`, `show_backup_`). +Set the flag to `true` to open; the dialog renders in `App::update()` and clears +the flag when dismissed. + +### Notifications +```cpp +Notifications::instance().success("Transaction sent"); +Notifications::instance().error("Insufficient funds"); +``` +Toast-style popups in the bottom-right corner. + +### Lock Screen & Loading Overlay +- Lock screen gates all interaction when `state_.isLocked()` +- Loading overlay shown while daemon isn't ready, gates all tabs except Peers, Console, Settings + +## Platform Abstractions + +Detection: `#ifdef _WIN32` / `#elif __APPLE__` / `#elif __linux__` + +Platform-specific files live in `src/platform/` (Windows only: DX11 context, backdrop effects). +Shared platform utilities in `src/util/platform.h` — `openUrl()`, `getHomeDir()`, `getDragonXDataDir()`. + +Rendering backends: +- Windows: DirectX 11 (`imgui_impl_dx11`) +- macOS/Linux: OpenGL 3 (`imgui_impl_opengl3`) + GLAD loader + +## Build System + +CMake 3.20+, C++17. Single `CMakeLists.txt` at root. + +**FetchContent dependencies:** SDL3, nlohmann/json v3.11.3, toml++ v3.4.0, libcurl (Windows only) +**Bundled libraries:** ImGui, GLAD, miniz, libsodium (pre-built per platform), qrcode + +**macOS:** Universal binary (arm64+x86_64), deployment target 11.0 (Big Sur+). +Set `CMAKE_OSX_DEPLOYMENT_TARGET` and `CMAKE_OSX_ARCHITECTURES` before `project()`. + +**Build commands:** +```bash +./build.sh # Dev build +./build.sh --mac-release # macOS universal .app + DMG +./build.sh --linux-release # Linux AppImage + zip +./build.sh --win-release # Windows cross-compile +``` + +## Theme System + +UI layout values are defined in `res/themes/ui.toml` and accessed via `schema::UI()` — +**never hardcode pixel sizes in C++ code**. + +Skins are self-contained TOML files in `res/themes/` defining color palettes. +`scripts/expand_themes.py` merges layout sections from `ui.toml` into each skin at build time. + +Colors support CSS-style variables: `--primary`, `--surface`, `--on-surface-medium`, resolved +by `ColorVarResolver` at runtime. + +## Internationalization + +All user-visible strings use `TR("key")` macro → `dragonx::util::tr()` → lookup in +`I18n` singleton. Never hardcode English strings in UI code. + +Language files: `res/lang/{locale}.json` (runtime) with embedded fallback compiled into binary. +Supported: en, es, zh, ru, de, fr, pt, ja, ko. + +## Key Rules + +1. **Never block the main thread** — all network/disk I/O goes through `worker_->post()` +2. **Never hardcode pixel sizes** — use `ui.toml` schema values via `schema::UI()` +3. **Always use `TR()` for strings** — no hardcoded English in UI rendering code +4. **Use `ICON_MD_*` for icons** — Material Design icon font, never raw Unicode +5. **Use `std::unique_ptr`** — no raw `new`/`delete` in application code +6. **Check the right connection state** — `state_.connected` for app-level, `rpc_->isConnected()` for per-client +7. **Test all three platforms** — build must pass Linux; cross-compile test if touching platform code diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md deleted file mode 100644 index b6a9d78..0000000 --- a/docs/ARCHITECTURE.md +++ /dev/null @@ -1,154 +0,0 @@ -# ObsidianDragon — Architecture Guide - -A native C++17 desktop wallet for DragonX (DRGX), built with ImGui + SDL3. - -## Directory Layout - -``` -src/ -├── main.cpp Entry point, SDL3/backend init, render loop -├── app.h / app.cpp App class: init, shutdown, frame dispatch -├── app_network.cpp RPC connection, data refresh, mining ops -├── app_security.cpp Encryption, lock screen, PIN management -├── app_wizard.cpp First-run setup wizard -├── config/ -│ └── settings.h/.cpp JSON settings persistence (~/.config/ObsidianDragon/) -├── daemon/ -│ ├── embedded_daemon.h/.cpp dragonxd process lifecycle -│ └── xmrig_manager.h/.cpp xmrig-hac pool mining management -├── rpc/ -│ ├── rpc_client.h/.cpp JSON-RPC over HTTPS (libcurl) -│ ├── rpc_worker.h/.cpp Background work queue + main-thread drain -│ ├── connection.h/.cpp DRAGONX.conf auto-detection -│ └── types.h Transaction, address data types -├── ui/ -│ ├── sidebar.h NavPage enum, sidebar rendering -│ ├── notifications.h/.cpp Toast notification system -│ ├── schema/ -│ │ ├── ui_schema.h/.cpp UISchema singleton (TOML → typed lookups) -│ │ ├── skin_manager.h/.cpp Skin enumeration, switching, import -│ │ └── color_var_resolver.h/.cpp CSS-style color resolution -│ └── windows/ Per-tab render functions (console, settings, etc.) -├── util/ -│ ├── i18n.h/.cpp Internationalization (TR() macro, I18n singleton) -│ ├── platform.h/.cpp Cross-platform utilities (paths, URLs) -│ └── logger.h DEBUG_LOGF / VERBOSE_LOGF macros -├── platform/ Windows-specific (DX11 context, backdrop effects) -├── embedded/ Build-generated headers (embedded resources) -└── resources/ Runtime resource loading (fonts, images) -``` - -## Threading Model - -``` -┌─────────────────────────────────────────────────────────────┐ -│ Main Thread (UI) │ -│ • ImGui render loop (App::update()) │ -│ • drainResults() each frame → executes completed callbacks │ -│ • NEVER does blocking I/O │ -└────────────┬────────────────────────┬───────────────────────┘ - │ post() │ post() - ▼ ▼ -┌────────────────────┐ ┌────────────────────────────────┐ -│ worker_ (RPCWorker)│ │ fast_worker_ (RPCWorker) │ -│ General RPC polling│ │ Console commands, hashrate │ -│ refreshData() 5s │ │ Avoids head-of-line blocking │ -└────────────────────┘ └────────────────────────────────┘ - -┌────────────────────────────────────────────┐ -│ Monitor Threads (per child process) │ -│ • EmbeddedDaemon: reads dragonxd stdout │ -│ • XmrigManager: reads xmrig-hac stdout │ -└────────────────────────────────────────────┘ -``` - -### Work Submission Pattern - -```cpp -worker_->post([this]() -> rpc::RPCWorker::MainCb { - json result = rpc_->call("getinfo"); // Runs on worker thread - return [this, result]() { - state_.connected = true; // Runs on main thread - }; -}); -``` - -## RPC Architecture - -**Dual-client design** avoids head-of-line blocking: - -| Client | Worker | Purpose | -|--------|--------|---------| -| `rpc_` | `worker_` | Main polling: balance, transactions, sync status | -| `fast_rpc_` | `fast_worker_` | Console commands, mining stats | - -Both are `RPCClient` instances wrapping libcurl for JSON-RPC over HTTPS to `dragonxd`. - -**Error flow:** `RPCClient::call()` throws `std::runtime_error` → -caught in worker lambda → error string captured → `MainCb` calls -`Notifications::instance().error(msg)` on main thread. - -## Connection Lifecycle - -``` -[Disconnected] → tryConnect() every 5s - → auto-detect DRAGONX.conf (host, port, rpcuser, rpcpassword) - → if no config: start embedded daemon → retry - → post async rpc_->connect() to worker_ - → success: onConnected() → state_.connected = true - → auth 401: try .cookie auth → retry - → failure: onDisconnected(reason) → may restart daemon -``` - -## UI System - -### Page Routing -`NavPage` enum defines all pages. `App::update()` dispatches via switch on -`current_page_` to render functions (e.g., `RenderBalanceTab(this)`). - -### Theme System -- Layout defined in `res/themes/ui.toml`, accessed via `schema::UI()` -- Skins are TOML files in `res/themes/` defining color palettes -- `scripts/expand_themes.py` merges layout into skins at build time -- Colors support CSS-style variables resolved by `ColorVarResolver` -- Hot-reload: `UISchema::pollForChanges()` watches file mtime - -### Internationalization -- All UI strings use `TR("key")` macro → `I18n` singleton lookup -- Language files: `res/lang/{locale}.json` with compiled-in fallbacks -- Supported: en, es, zh, ru, de, fr, pt, ja, ko - -### Notifications -```cpp -Notifications::instance().success("Transaction sent"); -Notifications::instance().error("Insufficient funds"); -``` -Toast-style popups, bottom-right corner, 5-second default duration. - -## Build System - -CMake 3.20+, C++17. FetchContent for SDL3, nlohmann/json, toml++. -Bundled: ImGui, GLAD, miniz, libsodium, qrcode. - -```bash -./build.sh # Dev build -./build.sh --mac-release # macOS universal .app + DMG -./build.sh --linux-release # Linux AppImage + zip -./build.sh --win-release # Windows cross-compile (MinGW) -``` - -### Platform Backends -| Platform | Renderer | Notes | -|----------|----------|-------| -| Windows | DirectX 11 | `imgui_impl_dx11`, backdrop effects | -| macOS | OpenGL 3 | Universal binary (arm64+x86_64), target 11.0+ | -| Linux | OpenGL 3 | GLAD loader | - -## Key Conventions - -1. **Never block the main thread** — all I/O goes through `worker_->post()` -2. **Never hardcode pixel sizes** — use `schema::UI()` lookups from `ui.toml` -3. **Always use `TR()` for strings** — no hardcoded English in UI code -4. **Use `ICON_MD_*` for icons** — Material Design icon font -5. **`std::unique_ptr` for ownership** — no raw `new`/`delete` -6. **Check the right connection state** — `state_.connected` vs `rpc_->isConnected()` diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 120000 index 0000000..9fae175 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1 @@ +../ObsidianDragon-agent/ARCHITECTURE.md \ No newline at end of file