feat(lite): lite wallet foundation (inherited working-tree state)

Preserve the previously-uncommitted lite wallet implementation and related dev WIP
under version control:
- src/wallet/ lite services: client bridge, bridge runtime, connection, lifecycle,
  sync, gateway, result parsers, state mapper, artifact contract/resolver, refresh
  services, UI adapters, wallet_backend/capabilities. (Includes two small M1 fixes:
  lifecycle walletReady now parses the response; default chain name -> "main".)
- src/chat/ chat protocol; tests/fixtures/ (lite + hushchat); tools/hushchat_fixture_check.cpp;
  scripts/build-lite-backend-artifact.sh.
- Pre-existing modified app_network/security/wizard, network_refresh_service, sidebar,
  mining_tab, bootstrap dialog, and version headers captured as-is.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 21:15:28 -05:00
parent a78a13edf3
commit 863d015628
69 changed files with 39458 additions and 85 deletions

View File

@@ -151,13 +151,11 @@ static void RenderMiningTabContent(App* app)
strncpy(s_pool_worker, app->settings()->getPoolWorker().c_str(), sizeof(s_pool_worker) - 1);
s_pool_state_loaded = true;
}
#if DRAGONX_LITE_BUILD
if (!s_pool_mode) {
if (!app->supportsSoloMining() && !s_pool_mode) {
s_pool_mode = true;
app->settings()->setPoolMode(true);
app->settings()->save();
}
#endif
// Default pool worker to user's first shielded (z) address once available.
// For new wallets without a z-address, leave the field blank so the user
@@ -242,11 +240,11 @@ static void RenderMiningTabContent(App* app)
// MODE TOGGLE — SOLO | POOL segmented control
// ================================================================
{
const bool liteBuild = app->isLiteBuild();
const bool soloMiningAvailable = app->supportsSoloMining();
float toggleW = schema::UI().drawElement("tabs.mining", "mode-toggle-width").size * hs;
float toggleH = schema::UI().drawElement("tabs.mining", "mode-toggle-height").size;
float toggleRnd = schema::UI().drawElement("tabs.mining", "mode-toggle-rounding").size;
float totalW = liteBuild ? toggleW : (toggleW * 2);
float totalW = soloMiningAvailable ? (toggleW * 2) : toggleW;
ImVec2 tMin = ImGui::GetCursorScreenPos();
ImVec2 tMax(tMin.x + totalW, tMin.y + toggleH);
@@ -258,7 +256,7 @@ static void RenderMiningTabContent(App* app)
ImVec2 soloMin = tMin;
ImVec2 soloMax(tMin.x + toggleW, tMax.y);
bool soloHov = material::IsRectHovered(soloMin, soloMax);
if (!liteBuild) {
if (soloMiningAvailable) {
// SOLO button (left half)
if (!s_pool_mode) {
dl->AddRectFilled(soloMin, soloMax, WithAlpha(Primary(), 180), toggleRnd);
@@ -275,7 +273,7 @@ static void RenderMiningTabContent(App* app)
// POOL button (right half) — disabled when solo mining is active
bool soloMiningActive = mining.generate;
ImVec2 poolMin(tMin.x + (liteBuild ? 0.0f : toggleW), tMin.y);
ImVec2 poolMin(tMin.x + (soloMiningAvailable ? toggleW : 0.0f), tMin.y);
ImVec2 poolMax = tMax;
bool poolHov = material::IsRectHovered(poolMin, poolMax);
if (s_pool_mode) {
@@ -296,7 +294,7 @@ static void RenderMiningTabContent(App* app)
}
// Invisible buttons for click targets
if (!liteBuild) {
if (soloMiningAvailable) {
ImGui::SetCursorScreenPos(soloMin);
ImGui::InvisibleButton("##SoloMode", ImVec2(toggleW, toggleH));
if (ImGui::IsItemClicked() && s_pool_mode) {
@@ -310,7 +308,7 @@ static void RenderMiningTabContent(App* app)
ImGui::SetCursorScreenPos(poolMin);
ImGui::InvisibleButton("##PoolMode", ImVec2(toggleW, toggleH));
if (!liteBuild && ImGui::IsItemClicked() && !s_pool_mode && !soloMiningActive) {
if (soloMiningAvailable && ImGui::IsItemClicked() && !s_pool_mode && !soloMiningActive) {
s_pool_mode = true;
app->settings()->setPoolMode(true);
app->settings()->save();
@@ -318,7 +316,7 @@ static void RenderMiningTabContent(App* app)
// so no need to call stopMining() — it would just set the
// toggle-in-progress flag and make the button show "STARTING".
}
if (!liteBuild && poolHov && !soloMiningActive) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
if (soloMiningAvailable && poolHov && !soloMiningActive) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
if (poolHov && soloMiningActive && !s_pool_mode) {
ImGui::SetTooltip("%s", TR("mining_stop_solo_for_pool"));
}
@@ -1935,7 +1933,7 @@ static void RenderMiningTabContent(App* app)
&& tx.memo.find("Mining Pool payout") != std::string::npos);
if (isSoloMined || isPoolPayout) {
// Apply earnings filter
if (app->isLiteBuild()) {
if (!app->supportsSoloMining()) {
if (s_earnings_filter == 1 && !isPoolPayout) continue;
} else {
if (s_earnings_filter == 1 && !isSoloMined) continue;
@@ -1984,10 +1982,10 @@ static void RenderMiningTabContent(App* app)
// === Earnings filter toggle button (top-right of card) ===
{
const bool liteBuild = app->isLiteBuild();
const char* filterLabels[] = { TR("mining_filter_all"), liteBuild ? TR("mining_pool") : TR("mining_solo"), TR("mining_pool") };
const char* filterIcons[] = { ICON_MD_FUNCTIONS, liteBuild ? ICON_MD_CLOUD : ICON_MD_MEMORY, ICON_MD_CLOUD };
const int filterCount = liteBuild ? 2 : 3;
const bool soloMiningAvailable = app->supportsSoloMining();
const char* filterLabels[] = { TR("mining_filter_all"), soloMiningAvailable ? TR("mining_solo") : TR("mining_pool"), TR("mining_pool") };
const char* filterIcons[] = { ICON_MD_FUNCTIONS, soloMiningAvailable ? ICON_MD_MEMORY : ICON_MD_CLOUD, ICON_MD_CLOUD };
const int filterCount = soloMiningAvailable ? 3 : 2;
const char* curIcon = filterIcons[s_earnings_filter];
const char* curLabel = filterLabels[s_earnings_filter];
@@ -2033,7 +2031,7 @@ static void RenderMiningTabContent(App* app)
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
const char* tips[] = {
TR("mining_filter_tip_all"),
liteBuild ? TR("mining_filter_tip_pool") : TR("mining_filter_tip_solo"),
soloMiningAvailable ? TR("mining_filter_tip_solo") : TR("mining_filter_tip_pool"),
TR("mining_filter_tip_pool")
};
ImGui::SetTooltip("%s", tips[s_earnings_filter]);