# 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`.
