- docs/lite-wallet-implementation-plan-v2-2026-06-04.md: vertical-slice plan that supersedes the v1 plan (now banner-marked); carries over the inherited artifact/ signing/phase-2 design docs for reference. - scripts/check-source-hygiene.sh: pre-commit/CI guard rejecting >80-char filenames and chained churn-token names, to stop the deleted "_plan"/"_batch" scaffolding from regrowing. - CLAUDE.md: repository guidance for future sessions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
80 lines
6.9 KiB
Markdown
80 lines
6.9 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## What this is
|
|
|
|
ObsidianDragon is a portable, full-node GUI wallet for DragonX (DRGX), written in C++17 using SDL3 + Dear ImGui (immediate-mode). It drives a `dragonxd` full node over JSON-RPC and can embed/extract the daemon itself. A separate **Lite** variant (`ObsidianDragonLite`) drops the full node and instead talks to an external lite-wallet backend library.
|
|
|
|
## Build & run
|
|
|
|
`build.sh` is the single entry point for all builds. `setup.sh` (repo root) installs/validates dependencies.
|
|
|
|
```bash
|
|
./build.sh # Dev build (native, no packaging) -> build/linux/bin/ObsidianDragon
|
|
./build.sh --lite # Dev build of the Lite variant -> build/linux/bin/ObsidianDragonLite
|
|
./build.sh --clean # Wipe the build dir first
|
|
./build.sh --linux-release # Release zip + AppImage -> release/linux/
|
|
./build.sh --win-release # Windows cross-compile (mingw-w64) -> release/windows/
|
|
./build.sh --mac-release # macOS .app bundle + DMG
|
|
./setup.sh --check # Report missing build deps without installing
|
|
```
|
|
|
|
Dev builds use `build/linux/` (or `build/mac/`). To re-build incrementally without re-running CMake config: `cmake --build build/linux -j$(nproc)`.
|
|
|
|
The wallet connects to the daemon using credentials in `~/.hush/DRAGONX/DRAGONX.conf` (`rpcuser`/`rpcpassword`/`rpcport`). It searches for `dragonxd`/`dragonx-cli` binaries in the **executable's own directory first**, so dropping custom node builds next to the wallet binary overrides the bundled ones.
|
|
|
|
## Tests
|
|
|
|
Tests live in `tests/test_phase4.cpp` — a single large translation unit using a custom assertion harness (`EXPECT_TRUE`/`EXPECT_EQ`/`EXPECT_NEAR` macros, one `main()`, exit code = failure count). `include(CTest)` enables `BUILD_TESTING=ON` by default, so the `ObsidianDragonTests` executable is built alongside the app.
|
|
|
|
```bash
|
|
cd build/linux && ctest --output-on-failure # run the suite
|
|
./build/linux/bin/ObsidianDragonTests # run the binary directly (same thing)
|
|
```
|
|
|
|
There is no per-test filtering — it is one binary that runs every assertion. The suite exercises the services layer, lite-wallet bridge, and pure helpers (parsers, formatters, model classes) without launching the GUI. Fixtures are under `tests/fixtures/` (path injected as `DRAGONX_TEST_FIXTURE_DIR`).
|
|
|
|
## Architecture
|
|
|
|
**Entry & main loop.** `src/main.cpp` owns SDL3 window creation, ImGui/OpenGL(or DX11 on Windows) setup, and the frame loop. The `App` class is the central controller; because it is large it is split across four files that all implement the same class:
|
|
- `src/app.cpp` — core lifecycle, the per-frame `render()`, tab dispatch
|
|
- `src/app_network.cpp` — RPC orchestration, sync, peers, daemon lifecycle
|
|
- `src/app_security.cpp` — encryption, PIN/lock screen, key import/export, backup
|
|
- `src/app_wizard.cpp` — first-run wizard
|
|
|
|
**RPC.** All daemon calls go through `src/rpc/` (`rpc_client`, `connection`, `rpc_worker`). **Never block the main/UI thread with synchronous network I/O — dispatch through `RPCWorker`** (async). `rpc/types.h` holds the shared DTOs.
|
|
|
|
**Services** (`src/services/`) hold the non-UI state machines that the `App` owns: `NetworkRefreshService` + `RefreshScheduler` (polling/refresh of balance, peers, txs on intervals) and the `WalletSecurity*` controller/workflow stack (encryption & unlock flows).
|
|
|
|
**Data model** (`src/data/`): `WalletState`, `address_book`, `transaction_history_cache`, `exchange_info`. UI reads from these.
|
|
|
|
**UI** (`src/ui/`): `windows/` are the tabs and dialogs (one pair per screen, e.g. `send_tab`, `mining_tab`, `console_tab`), `pages/` are multi-section screens (Settings), `screens/` are layout headers, `material/` is the design-system layer, `schema/` loads the TOML UI schema/skins, `effects/` is GL post-processing (blur/acrylic).
|
|
|
|
**Lite wallet** (`src/wallet/`): the bridge to an external `litelib_*` C-ABI backend (`lite_client_bridge`, `lite_bridge_runtime`, `lite_connection_service`, `lite_sync_service`, result parsers, and the artifact-contract/resolver that validates a prebuilt backend library). The real frontend entry points are `lite_wallet_lifecycle_ui_adapter` and `lite_wallet_server_selection_adapter` (used by `src/ui/pages/settings_page.cpp`); everything else is reachable through them.
|
|
|
|
> ⚠️ **Do not regrow the `_plan`/`_batch` churn.** This directory previously held ~160 dead `lite_wallet_*_plan` / `*_batch*_receipt_custody_acceptance_confirmation_archive_handoff_*` files (filenames up to 250 chars) — auto-generated scaffolding that never reached the shipping binary. They were deleted. When extending lite-wallet behavior, **edit the named service/bridge/runtime files in place**; never add another "promotion/receipt/custody/handoff/stewardship" wrapper layer. `scripts/check-source-hygiene.sh` (wired as a `.git/hooks/pre-commit` hook) blocks >80-char filenames and chained churn-token names — run it in CI too.
|
|
|
|
**Chat** (`src/chat/chat_protocol.cpp`): experimental HushChat protocol, compiled in only when `DRAGONX_ENABLE_CHAT=ON`.
|
|
|
|
## Build variants & feature gating
|
|
|
|
Variants are selected with CMake options (set by `build.sh` flags), surfaced to C++ as compile definitions:
|
|
- `DRAGONX_BUILD_LITE` (`--lite`) → `DRAGONX_LITE_BUILD` define; renames the app to `ObsidianDragonLite` and excludes embedded-daemon / full-node assets (Sapling params, asmap, dragonxd).
|
|
- `DRAGONX_ENABLE_LITE_BACKEND` → links a real external lite backend. Requires `--lite`, link mode `imported`, ABI `sdxl-c-v1`, and a symbols inventory file (built by `scripts/build-lite-backend-artifact.sh`); CMake hard-fails if any required `litelib_*` symbol is missing.
|
|
- `DRAGONX_ENABLE_CHAT` → `DRAGONX_ENABLE_CHAT` define gating the chat module.
|
|
|
|
Guard full-node-only code paths with `#if DRAGONX_LITE_BUILD` / chat code with `DRAGONX_ENABLE_CHAT`.
|
|
|
|
## Versioning
|
|
|
|
The version has a **single source of truth**: `project(... VERSION 1.2.0 ...)` plus `DRAGONX_VERSION_SUFFIX` in `CMakeLists.txt`. CMake generates `build/.../generated/dragonx_generated_version.h` from `src/config/version.h.in`. Do not hand-edit generated version output or hardcode version strings — bump the `project()` version in `CMakeLists.txt`.
|
|
|
|
## Conventions
|
|
|
|
- **C++17.** Match the surrounding code's style per file.
|
|
- **Icons:** use the Material Design icon font defines (`ICON_MD_*`); never raw Unicode glyphs.
|
|
- **UI layout values** belong in `res/themes/ui.toml`, read via `schema::UI()` — do not hardcode pixel sizes/offsets in code.
|
|
- **i18n:** user-facing strings are translated via `src/util/i18n`; translation JSON lives in `res/lang/` (`de`, `es`, `fr`, `ja`, `ko`, `pt`, `ru`, `zh`, English fallback in code). Translation/font helper scripts are in `scripts/` (`gen_*.py`, CJK subset tooling).
|
|
- **Commits:** the history uses Conventional Commits (`feat(scope): …`, `fix(scope): …`). PRs target `master`.
|