From f428292ea483ddf291993fd4cde577a7310da1cf Mon Sep 17 00:00:00 2001 From: DanS Date: Mon, 13 Jul 2026 13:53:35 -0500 Subject: [PATCH] feat(settings): split import into separate key + viewing-key buttons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backup & Data now has two distinct import actions instead of one auto-detecting dialog: - "Import Key" imports a spending key (transparent WIF or shielded z-spending key) with the strong "grants access to funds" warning. - "Import Viewing Key" imports a watch-only shielded viewing key (zxviews…) with a milder eye/watch-only note and an optional "scan from block height" field — z_importviewingkey accepts a start height, so watching a recent address needn't rescan the whole chain. The shared Material dialog (renderImportKeyDialog) branches on import_view_mode_: title, warning tone, field label, the live type indicator, and the recognition guard. A key valid for the *other* button (e.g. a spending key pasted into the viewing-key dialog) now shows a redirect hint rather than a generic "unrecognized" error. importPrivateKey gains a startHeight arg, appended to the shielded import RPCs (z_importviewingkey / z_importkey) and ignored for transparent WIF (importprivkey has no start-height param). The scan-height buffer is wiped on open/close alongside the key buffer. i18n: 9 new keys (button label + tooltip, viewing title/note/field, scan label/hint, two wrong-type redirect hints) with translations for all 8 languages; CJK subset rebuilt (+1 glyph). A modal-import-viewkey sweep surface is added for the viewing-mode dialog. Co-Authored-By: Claude Opus 4.8 (1M context) --- res/fonts/NotoSansCJK-Subset.ttf | Bin 624100 -> 624308 bytes res/lang/de.json | 9 +++++ res/lang/es.json | 9 +++++ res/lang/fr.json | 9 +++++ res/lang/ja.json | 9 +++++ res/lang/ko.json | 9 +++++ res/lang/pt.json | 9 +++++ res/lang/ru.json | 9 +++++ res/lang/zh.json | 9 +++++ src/app.cpp | 64 +++++++++++++++++++++++++------ src/app.h | 8 +++- src/app_network.cpp | 6 ++- src/app_sweep.cpp | 4 +- src/ui/pages/settings_page.cpp | 9 ++++- src/util/i18n.cpp | 10 +++++ 15 files changed, 155 insertions(+), 18 deletions(-) diff --git a/res/fonts/NotoSansCJK-Subset.ttf b/res/fonts/NotoSansCJK-Subset.ttf index 7226775926a176266c536a73201d58e8172a36a2..b157a610790559989aae874fd27a39bdb3824b23 100644 GIT binary patch delta 18527 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 X+v3~n%xS!9`|7mY_I$33=KFsD4nI_b delta 18196 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 callback); // callback(success, errorOrEmpty, importedAddress). address is "" on failure or when the RPC // returns none; the import routes to z_importviewingkey / z_importkey / importprivkey by key type. - void importPrivateKey(const std::string& key, + // startHeight > 0 rescans from that block (shielded RPCs only; ignored for transparent WIF). + void importPrivateKey(const std::string& key, int startHeight, std::function callback); // Wallet backup @@ -373,7 +374,8 @@ public: std::string screenshotDir() const; // /screenshots (fixed; sweeps overwrite in place) // Dialog triggers (used by settings page to open modal dialogs) - void showImportKeyDialog() { show_import_key_ = true; } + void showImportKeyDialog() { import_view_mode_ = false; show_import_key_ = true; } // spending + void showImportViewingKeyDialog() { import_view_mode_ = true; show_import_key_ = true; } // watch-only void showExportKeyDialog() { show_export_key_ = true; } void showBackupDialog() { show_backup_ = true; } void showSeedBackupDialog() { show_seed_backup_ = true; } @@ -808,6 +810,8 @@ private: bool import_key_reveal_ = false; // show the key in plaintext (default masked) bool import_in_progress_ = false; // an import + rescan is running (disable/spinner) std::string import_result_address_; // address imported on success (shown as a copy field) + bool import_view_mode_ = false; // dialog mode: false = spending key, true = viewing key + char import_key_scan_height_[16] = {0}; // optional rescan start height (viewing-key mode) std::string backup_status_; bool backup_success_ = false; diff --git a/src/app_network.cpp b/src/app_network.cpp index 34076e1..756332c 100644 --- a/src/app_network.cpp +++ b/src/app_network.cpp @@ -2921,7 +2921,7 @@ void App::exportAllKeys(std::function callba } } -void App::importPrivateKey(const std::string& rawKey, +void App::importPrivateKey(const std::string& rawKey, int startHeight, std::function callback) { if (!state_.connected || !rpc_ || !worker_) { @@ -2947,7 +2947,7 @@ void App::importPrivateKey(const std::string& rawKey, == services::WalletSecurityController::KeyKind::Shielded; // Run on the worker thread — import requests a full rescan (rescan=true), so the // synchronous curl call can take many seconds; never block the UI thread on it. - worker_->post([this, key, viewing, shielded, callback]() -> rpc::RPCWorker::MainCb { + worker_->post([this, key, viewing, shielded, startHeight, callback]() -> rpc::RPCWorker::MainCb { std::string err, addr; try { rpc::RPCClient::TraceScope trace("Settings / Import key"); @@ -2956,6 +2956,8 @@ void App::importPrivateKey(const std::string& rawKey, if (viewing) { method = "z_importviewingkey"; params = {key, "yes"}; } // watch-only else if (shielded) { method = "z_importkey"; params = {key, "yes"}; } else { method = "importprivkey"; params = {key, "", true}; } + // A start height (shielded RPCs only) rescans from that block instead of genesis. + if (startHeight > 0 && (viewing || shielded)) params.push_back(startHeight); nlohmann::json r = rpc_->call(method, params); // z_import* return {type,address}; importprivkey returns the t-address string. if (r.is_object() && r.contains("address") && r["address"].is_string()) diff --git a/src/app_sweep.cpp b/src/app_sweep.cpp index f1bfc6b..742ae7c 100644 --- a/src/app_sweep.cpp +++ b/src/app_sweep.cpp @@ -261,7 +261,9 @@ void App::buildSweepCatalog() // Simple bool-flag modals. add("modal-import-key", ui::NavPage::Overview, - [](App& a) { a.show_import_key_ = true; }, [](App& a) { a.show_import_key_ = false; }); + [](App& a) { a.import_view_mode_ = false; a.show_import_key_ = true; }, [](App& a) { a.show_import_key_ = false; }); + add("modal-import-viewkey", ui::NavPage::Overview, + [](App& a) { a.import_view_mode_ = true; a.show_import_key_ = true; }, [](App& a) { a.show_import_key_ = false; a.import_view_mode_ = false; }); add("modal-export-key", ui::NavPage::Overview, [](App& a) { a.show_export_key_ = true; }, [](App& a) { a.show_export_key_ = false; }); add("modal-backup", ui::NavPage::Overview, diff --git a/src/ui/pages/settings_page.cpp b/src/ui/pages/settings_page.cpp index 5fd70d7..f08c620 100644 --- a/src/ui/pages/settings_page.cpp +++ b/src/ui/pages/settings_page.cpp @@ -1349,12 +1349,14 @@ void RenderSettingsPage(App* app) { float naturalW = 0; for (int i = 0; i < 5; i++) naturalW += ImGui::CalcTextSize(r1[i]).x + btnPadX; + float impViewW = ImGui::CalcTextSize(TR("settings_import_viewkey")).x + btnPadX; + naturalW += impViewW; // the extra "Import viewing key" button (rendered after Import key) float wizW = showFullNodeLifecycleActions ? ImGui::CalcTextSize(wizLabel).x + btnPadX : 0.0f; float bsW = showFullNodeLifecycleActions ? ImGui::CalcTextSize(bsLabel).x + btnPadX : 0.0f; // Full-node-only "Seed phrase" + "Migrate to seed" buttons trail the Backup button. float seedW = showFullNodeLifecycleActions ? ImGui::CalcTextSize(TR("seed_backup_button")).x + btnPadX : 0.0f; float migrateW = showFullNodeLifecycleActions ? ImGui::CalcTextSize(TR("seed_migrate_button")).x + btnPadX : 0.0f; - float totalW = naturalW + sp * 5; + float totalW = naturalW + sp * 6; // 6 base buttons (incl. Import viewing key) if (showFullNodeLifecycleActions) totalW += wizW + bsW + seedW + migrateW + sp * 4; float scale = (totalW > contentW) ? contentW / totalW : 1.0f; @@ -1364,6 +1366,11 @@ void RenderSettingsPage(App* app) { if (TactileButton(r1[0], ImVec2(0, 0), btnFont)) app->showImportKeyDialog(); if (ImGui::IsItemHovered()) material::Tooltip("%s", t1[0]); + // Watch-only shielded viewing-key import (separate button — different key type + scan-height). + ImGui::SameLine(0, scaledSp); + if (TactileButton(TR("settings_import_viewkey"), ImVec2(0, 0), btnFont)) + app->showImportViewingKeyDialog(); + if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_import_viewkey")); ImGui::SameLine(0, scaledSp); if (TactileButton(r1[1], ImVec2(0, 0), btnFont)) app->showExportKeyDialog(); diff --git a/src/util/i18n.cpp b/src/util/i18n.cpp index 5583af2..615337c 100644 --- a/src/util/i18n.cpp +++ b/src/util/i18n.cpp @@ -429,6 +429,7 @@ void I18n::loadBuiltinEnglish() strings_["settings_merge_to_address"] = "Merge to Address..."; strings_["settings_clear_ztx"] = "Clear Z-Tx History"; strings_["settings_import_key"] = "Import Key..."; + strings_["settings_import_viewkey"] = "Import Viewing Key..."; strings_["settings_export_key"] = "Export Key..."; strings_["settings_export_all"] = "Export All..."; strings_["settings_backup"] = "Backup..."; @@ -731,6 +732,7 @@ void I18n::loadBuiltinEnglish() // Settings: additional tooltips (keys/data row) strings_["tt_import_key"] = "Import a private key (zkey or tkey) into this wallet"; + strings_["tt_import_viewkey"] = "Import a shielded viewing key to watch an address (read-only)"; strings_["tt_export_key"] = "Export the private key for the selected address"; strings_["tt_export_all"] = "Export all private keys to a file"; strings_["tt_backup"] = "Create a backup of your wallet.dat file"; @@ -1358,6 +1360,14 @@ void I18n::loadBuiltinEnglish() strings_["import_key_done"] = "Imported. Wallet is rescanning."; strings_["import_key_address"] = "Address:"; strings_["import_key_import"] = "Import"; + // Viewing-key (watch-only) import — separate button + dialog mode. + strings_["import_viewkey_title"] = "Import Viewing Key"; + strings_["import_viewkey_note"] = "Watch-only: a viewing key reveals an address's balance and transactions but cannot spend its funds."; + strings_["import_viewkey_field"] = "Viewing key"; + strings_["import_key_wrong_type"] = "This looks like a viewing key. Use \"Import Viewing Key\" instead."; + strings_["import_viewkey_wrong_type"] = "This looks like a spending key. Use \"Import Key\" instead."; + strings_["import_viewkey_scan_label"] = "Scan from block height (optional)"; + strings_["import_viewkey_scan_hint"] = "0 = rescan from the start"; // --- Key Export Dialog --- strings_["key_export_fetching"] = "Fetching key from wallet...";