feat(settings): split import into separate key + viewing-key buttons
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) <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
@@ -441,8 +441,15 @@
|
|||||||
"import_key_type_zview": "Abgeschirmter Anzeigeschlüssel (nur Lesen)",
|
"import_key_type_zview": "Abgeschirmter Anzeigeschlüssel (nur Lesen)",
|
||||||
"import_key_warn": "Importieren Sie nur einen Schlüssel, der Ihnen gehört — er gewährt Zugriff auf dessen Guthaben.",
|
"import_key_warn": "Importieren Sie nur einen Schlüssel, der Ihnen gehört — er gewährt Zugriff auf dessen Guthaben.",
|
||||||
"import_key_warning": "Warnung: Teilen Sie niemals Ihre privaten Schlüssel! Das Importieren von Schlüsseln aus nicht vertrauenswürdigen Quellen kann Ihr Wallet gefährden.",
|
"import_key_warning": "Warnung: Teilen Sie niemals Ihre privaten Schlüssel! Das Importieren von Schlüsseln aus nicht vertrauenswürdigen Quellen kann Ihr Wallet gefährden.",
|
||||||
|
"import_key_wrong_type": "Das sieht nach einem Anzeigeschlüssel aus. Verwenden Sie stattdessen \"Anzeigeschlüssel importieren\".",
|
||||||
"import_key_z_format": "Z-Adresse Ausgabeschlüssel (secret-extended-key-...)",
|
"import_key_z_format": "Z-Adresse Ausgabeschlüssel (secret-extended-key-...)",
|
||||||
"import_private_key": "Privaten Schlüssel importieren...",
|
"import_private_key": "Privaten Schlüssel importieren...",
|
||||||
|
"import_viewkey_field": "Anzeigeschlüssel",
|
||||||
|
"import_viewkey_note": "Nur Lesen: Ein Anzeigeschlüssel zeigt Guthaben und Transaktionen einer Adresse, kann deren Mittel aber nicht ausgeben.",
|
||||||
|
"import_viewkey_scan_hint": "0 = von Anfang an neu scannen",
|
||||||
|
"import_viewkey_scan_label": "Ab Blockhöhe scannen (optional)",
|
||||||
|
"import_viewkey_title": "Anzeigeschlüssel importieren",
|
||||||
|
"import_viewkey_wrong_type": "Das sieht nach einem Ausgabeschlüssel aus. Verwenden Sie stattdessen \"Schlüssel importieren\".",
|
||||||
"incorrect_passphrase": "Falsches Passwort",
|
"incorrect_passphrase": "Falsches Passwort",
|
||||||
"incorrect_pin": "Falsche PIN",
|
"incorrect_pin": "Falsche PIN",
|
||||||
"insufficient_funds": "Unzureichendes Guthaben für diesen Betrag plus Gebühr.",
|
"insufficient_funds": "Unzureichendes Guthaben für diesen Betrag plus Gebühr.",
|
||||||
@@ -1105,6 +1112,7 @@
|
|||||||
"settings_gradient_desc": "Strukturierte Hintergründe durch sanfte Verläufe ersetzen",
|
"settings_gradient_desc": "Strukturierte Hintergründe durch sanfte Verläufe ersetzen",
|
||||||
"settings_idle_after": "nach",
|
"settings_idle_after": "nach",
|
||||||
"settings_import_key": "Schlüssel importieren...",
|
"settings_import_key": "Schlüssel importieren...",
|
||||||
|
"settings_import_viewkey": "Anzeigeschlüssel importieren...",
|
||||||
"settings_language_note": "Hinweis: Manche Texte erfordern einen Neustart zur Aktualisierung",
|
"settings_language_note": "Hinweis: Manche Texte erfordern einen Neustart zur Aktualisierung",
|
||||||
"settings_lock_now": "Jetzt sperren",
|
"settings_lock_now": "Jetzt sperren",
|
||||||
"settings_locked": "Gesperrt",
|
"settings_locked": "Gesperrt",
|
||||||
@@ -1252,6 +1260,7 @@
|
|||||||
"tt_font_scale": "Alle Texte und UI skalieren (1.0x = Standard, bis 1.5x).",
|
"tt_font_scale": "Alle Texte und UI skalieren (1.0x = Standard, bis 1.5x).",
|
||||||
"tt_idle_delay": "Wie lange vor dem Start des Minings gewartet werden soll",
|
"tt_idle_delay": "Wie lange vor dem Start des Minings gewartet werden soll",
|
||||||
"tt_import_key": "Einen privaten Schlüssel (zkey oder tkey) in diese Wallet importieren",
|
"tt_import_key": "Einen privaten Schlüssel (zkey oder tkey) in diese Wallet importieren",
|
||||||
|
"tt_import_viewkey": "Einen abgeschirmten Anzeigeschlüssel importieren, um eine Adresse anzusehen (nur Lesen)",
|
||||||
"tt_keep_daemon": "Der Daemon wird beim Ausführen des Einrichtungsassistenten gestoppt",
|
"tt_keep_daemon": "Der Daemon wird beim Ausführen des Einrichtungsassistenten gestoppt",
|
||||||
"tt_language": "Schnittstellensprache der Wallet-UI",
|
"tt_language": "Schnittstellensprache der Wallet-UI",
|
||||||
"tt_layout_hotkey": "Hotkey: Links-/Rechts-Pfeiltasten zum Wechseln der Balance-Layouts",
|
"tt_layout_hotkey": "Hotkey: Links-/Rechts-Pfeiltasten zum Wechseln der Balance-Layouts",
|
||||||
|
|||||||
@@ -441,8 +441,15 @@
|
|||||||
"import_key_type_zview": "Clave de visualización blindada (solo lectura)",
|
"import_key_type_zview": "Clave de visualización blindada (solo lectura)",
|
||||||
"import_key_warn": "Importa solo una clave que te pertenezca: da acceso a sus fondos.",
|
"import_key_warn": "Importa solo una clave que te pertenezca: da acceso a sus fondos.",
|
||||||
"import_key_warning": "Advertencia: ¡Nunca compartas tus claves privadas! Importar claves de fuentes no confiables puede comprometer tu cartera.",
|
"import_key_warning": "Advertencia: ¡Nunca compartas tus claves privadas! Importar claves de fuentes no confiables puede comprometer tu cartera.",
|
||||||
|
"import_key_wrong_type": "Esto parece una clave de visualización. Usa \"Importar clave de visualización\" en su lugar.",
|
||||||
"import_key_z_format": "Claves de gasto de direcciones Z (secret-extended-key-...)",
|
"import_key_z_format": "Claves de gasto de direcciones Z (secret-extended-key-...)",
|
||||||
"import_private_key": "Importar Clave Privada...",
|
"import_private_key": "Importar Clave Privada...",
|
||||||
|
"import_viewkey_field": "Clave de visualización",
|
||||||
|
"import_viewkey_note": "Solo lectura: una clave de visualización revela el saldo y las transacciones de una dirección, pero no puede gastar sus fondos.",
|
||||||
|
"import_viewkey_scan_hint": "0 = volver a escanear desde el inicio",
|
||||||
|
"import_viewkey_scan_label": "Escanear desde la altura de bloque (opcional)",
|
||||||
|
"import_viewkey_title": "Importar clave de visualización",
|
||||||
|
"import_viewkey_wrong_type": "Esto parece una clave de gasto. Usa \"Importar clave\" en su lugar.",
|
||||||
"incorrect_passphrase": "Contraseña incorrecta",
|
"incorrect_passphrase": "Contraseña incorrecta",
|
||||||
"incorrect_pin": "PIN incorrecto",
|
"incorrect_pin": "PIN incorrecto",
|
||||||
"insufficient_funds": "Fondos insuficientes para este monto más la comisión.",
|
"insufficient_funds": "Fondos insuficientes para este monto más la comisión.",
|
||||||
@@ -1105,6 +1112,7 @@
|
|||||||
"settings_gradient_desc": "Reemplazar fondos con texturas por degradados suaves",
|
"settings_gradient_desc": "Reemplazar fondos con texturas por degradados suaves",
|
||||||
"settings_idle_after": "después de",
|
"settings_idle_after": "después de",
|
||||||
"settings_import_key": "Importar clave...",
|
"settings_import_key": "Importar clave...",
|
||||||
|
"settings_import_viewkey": "Importar clave de visualización...",
|
||||||
"settings_language_note": "Nota: Parte del texto requiere reinicio para actualizarse",
|
"settings_language_note": "Nota: Parte del texto requiere reinicio para actualizarse",
|
||||||
"settings_lock_now": "Bloquear ahora",
|
"settings_lock_now": "Bloquear ahora",
|
||||||
"settings_locked": "Bloqueado",
|
"settings_locked": "Bloqueado",
|
||||||
@@ -1252,6 +1260,7 @@
|
|||||||
"tt_font_scale": "Escalar todo el texto y la interfaz (1.0x = predeterminado, hasta 1.5x).",
|
"tt_font_scale": "Escalar todo el texto y la interfaz (1.0x = predeterminado, hasta 1.5x).",
|
||||||
"tt_idle_delay": "Cuánto tiempo esperar antes de empezar a minar",
|
"tt_idle_delay": "Cuánto tiempo esperar antes de empezar a minar",
|
||||||
"tt_import_key": "Importar una clave privada (zkey o tkey) en esta billetera",
|
"tt_import_key": "Importar una clave privada (zkey o tkey) en esta billetera",
|
||||||
|
"tt_import_viewkey": "Importar una clave de visualización blindada para observar una dirección (solo lectura)",
|
||||||
"tt_keep_daemon": "El daemon se detendrá cuando ejecute el asistente de configuración",
|
"tt_keep_daemon": "El daemon se detendrá cuando ejecute el asistente de configuración",
|
||||||
"tt_language": "Idioma de la interfaz de la billetera",
|
"tt_language": "Idioma de la interfaz de la billetera",
|
||||||
"tt_layout_hotkey": "Atajo: teclas de flecha izquierda/derecha para cambiar diseños de Balance",
|
"tt_layout_hotkey": "Atajo: teclas de flecha izquierda/derecha para cambiar diseños de Balance",
|
||||||
|
|||||||
@@ -441,8 +441,15 @@
|
|||||||
"import_key_type_zview": "Clé de visualisation blindée (lecture seule)",
|
"import_key_type_zview": "Clé de visualisation blindée (lecture seule)",
|
||||||
"import_key_warn": "N'importez qu'une clé qui vous appartient — elle donne accès à ses fonds.",
|
"import_key_warn": "N'importez qu'une clé qui vous appartient — elle donne accès à ses fonds.",
|
||||||
"import_key_warning": "Attention : Ne partagez jamais vos clés privées ! L'importation de clés provenant de sources non fiables peut compromettre votre portefeuille.",
|
"import_key_warning": "Attention : Ne partagez jamais vos clés privées ! L'importation de clés provenant de sources non fiables peut compromettre votre portefeuille.",
|
||||||
|
"import_key_wrong_type": "Ceci ressemble à une clé de visualisation. Utilisez plutôt « Importer la clé de visualisation ».",
|
||||||
"import_key_z_format": "Clés de dépenses z-adresse (secret-extended-key-...)",
|
"import_key_z_format": "Clés de dépenses z-adresse (secret-extended-key-...)",
|
||||||
"import_private_key": "Importer une clé privée...",
|
"import_private_key": "Importer une clé privée...",
|
||||||
|
"import_viewkey_field": "Clé de visualisation",
|
||||||
|
"import_viewkey_note": "Lecture seule : une clé de visualisation révèle le solde et les transactions d'une adresse, mais ne peut pas dépenser ses fonds.",
|
||||||
|
"import_viewkey_scan_hint": "0 = réanalyser depuis le début",
|
||||||
|
"import_viewkey_scan_label": "Analyser à partir de la hauteur de bloc (facultatif)",
|
||||||
|
"import_viewkey_title": "Importer la clé de visualisation",
|
||||||
|
"import_viewkey_wrong_type": "Ceci ressemble à une clé de dépense. Utilisez plutôt « Importer la clé ».",
|
||||||
"incorrect_passphrase": "Mot de passe incorrect",
|
"incorrect_passphrase": "Mot de passe incorrect",
|
||||||
"incorrect_pin": "PIN incorrect",
|
"incorrect_pin": "PIN incorrect",
|
||||||
"insufficient_funds": "Fonds insuffisants pour ce montant plus les frais.",
|
"insufficient_funds": "Fonds insuffisants pour ce montant plus les frais.",
|
||||||
@@ -1105,6 +1112,7 @@
|
|||||||
"settings_gradient_desc": "Remplacer les arrière-plans texturés par des dégradés lisses",
|
"settings_gradient_desc": "Remplacer les arrière-plans texturés par des dégradés lisses",
|
||||||
"settings_idle_after": "après",
|
"settings_idle_after": "après",
|
||||||
"settings_import_key": "Importer la clé...",
|
"settings_import_key": "Importer la clé...",
|
||||||
|
"settings_import_viewkey": "Importer la clé de visualisation...",
|
||||||
"settings_language_note": "Remarque : Certains textes nécessitent un redémarrage pour se mettre à jour",
|
"settings_language_note": "Remarque : Certains textes nécessitent un redémarrage pour se mettre à jour",
|
||||||
"settings_lock_now": "Verrouiller maintenant",
|
"settings_lock_now": "Verrouiller maintenant",
|
||||||
"settings_locked": "Verrouillé",
|
"settings_locked": "Verrouillé",
|
||||||
@@ -1252,6 +1260,7 @@
|
|||||||
"tt_font_scale": "Mettre à l'échelle tout le texte et l'interface (1.0x = par défaut, jusqu'à 1.5x).",
|
"tt_font_scale": "Mettre à l'échelle tout le texte et l'interface (1.0x = par défaut, jusqu'à 1.5x).",
|
||||||
"tt_idle_delay": "Combien de temps attendre avant de commencer le minage",
|
"tt_idle_delay": "Combien de temps attendre avant de commencer le minage",
|
||||||
"tt_import_key": "Importer une clé privée (zkey ou tkey) dans ce portefeuille",
|
"tt_import_key": "Importer une clé privée (zkey ou tkey) dans ce portefeuille",
|
||||||
|
"tt_import_viewkey": "Importer une clé de visualisation blindée pour observer une adresse (lecture seule)",
|
||||||
"tt_keep_daemon": "Le daemon s'arrêtera lors de l'exécution de l'assistant de configuration",
|
"tt_keep_daemon": "Le daemon s'arrêtera lors de l'exécution de l'assistant de configuration",
|
||||||
"tt_language": "Langue de l'interface du portefeuille",
|
"tt_language": "Langue de l'interface du portefeuille",
|
||||||
"tt_layout_hotkey": "Raccourci : touches fléchées gauche/droite pour changer les dispositions de Balance",
|
"tt_layout_hotkey": "Raccourci : touches fléchées gauche/droite pour changer les dispositions de Balance",
|
||||||
|
|||||||
@@ -441,8 +441,15 @@
|
|||||||
"import_key_type_zview": "シールド閲覧鍵(監視のみ)",
|
"import_key_type_zview": "シールド閲覧鍵(監視のみ)",
|
||||||
"import_key_warn": "自分が所有する鍵のみをインポートしてください — その資金へのアクセスを許可します。",
|
"import_key_warn": "自分が所有する鍵のみをインポートしてください — その資金へのアクセスを許可します。",
|
||||||
"import_key_warning": "警告:秘密鍵を決して共有しないでください!信頼できないソースからの鍵のインポートはウォレットを危険にさらす可能性があります。",
|
"import_key_warning": "警告:秘密鍵を決して共有しないでください!信頼できないソースからの鍵のインポートはウォレットを危険にさらす可能性があります。",
|
||||||
|
"import_key_wrong_type": "これは閲覧鍵のようです。代わりに「閲覧鍵をインポート」を使用してください。",
|
||||||
"import_key_z_format": "Zアドレス支出鍵 (secret-extended-key-...)",
|
"import_key_z_format": "Zアドレス支出鍵 (secret-extended-key-...)",
|
||||||
"import_private_key": "秘密鍵をインポート...",
|
"import_private_key": "秘密鍵をインポート...",
|
||||||
|
"import_viewkey_field": "閲覧鍵",
|
||||||
|
"import_viewkey_note": "監視のみ:閲覧鍵はアドレスの残高と取引を表示できますが、資金を送金することはできません。",
|
||||||
|
"import_viewkey_scan_hint": "0 = 最初から再スキャン",
|
||||||
|
"import_viewkey_scan_label": "スキャン開始ブロック高(任意)",
|
||||||
|
"import_viewkey_title": "閲覧鍵をインポート",
|
||||||
|
"import_viewkey_wrong_type": "これは支払い鍵のようです。代わりに「鍵をインポート」を使用してください。",
|
||||||
"incorrect_passphrase": "パスフレーズが正しくありません",
|
"incorrect_passphrase": "パスフレーズが正しくありません",
|
||||||
"incorrect_pin": "PINが正しくありません",
|
"incorrect_pin": "PINが正しくありません",
|
||||||
"insufficient_funds": "この金額と手数料に対して残高が不足しています。",
|
"insufficient_funds": "この金額と手数料に対して残高が不足しています。",
|
||||||
@@ -1105,6 +1112,7 @@
|
|||||||
"settings_gradient_desc": "テクスチャ背景を滑らかなグラデーションに置換",
|
"settings_gradient_desc": "テクスチャ背景を滑らかなグラデーションに置換",
|
||||||
"settings_idle_after": "経過後",
|
"settings_idle_after": "経過後",
|
||||||
"settings_import_key": "鍵をインポート...",
|
"settings_import_key": "鍵をインポート...",
|
||||||
|
"settings_import_viewkey": "閲覧鍵をインポート...",
|
||||||
"settings_language_note": "注意:一部のテキストは更新に再起動が必要です",
|
"settings_language_note": "注意:一部のテキストは更新に再起動が必要です",
|
||||||
"settings_lock_now": "今すぐロック",
|
"settings_lock_now": "今すぐロック",
|
||||||
"settings_locked": "ロック済み",
|
"settings_locked": "ロック済み",
|
||||||
@@ -1252,6 +1260,7 @@
|
|||||||
"tt_font_scale": "すべてのテキストと UI をスケーリング(1.0x = デフォルト、最大 1.5x)。",
|
"tt_font_scale": "すべてのテキストと UI をスケーリング(1.0x = デフォルト、最大 1.5x)。",
|
||||||
"tt_idle_delay": "マイニング開始前の待機時間",
|
"tt_idle_delay": "マイニング開始前の待機時間",
|
||||||
"tt_import_key": "このウォレットに秘密鍵(zkey または tkey)をインポート",
|
"tt_import_key": "このウォレットに秘密鍵(zkey または tkey)をインポート",
|
||||||
|
"tt_import_viewkey": "シールド閲覧鍵をインポートしてアドレスを閲覧(読み取り専用)",
|
||||||
"tt_keep_daemon": "セットアップウィザード実行時にデーモンは停止します",
|
"tt_keep_daemon": "セットアップウィザード実行時にデーモンは停止します",
|
||||||
"tt_language": "ウォレット UI のインターフェース言語",
|
"tt_language": "ウォレット UI のインターフェース言語",
|
||||||
"tt_layout_hotkey": "ホットキー:左右矢印キーでバランスレイアウトを切り替え",
|
"tt_layout_hotkey": "ホットキー:左右矢印キーでバランスレイアウトを切り替え",
|
||||||
|
|||||||
@@ -441,8 +441,15 @@
|
|||||||
"import_key_type_zview": "차폐 조회 키 (읽기 전용)",
|
"import_key_type_zview": "차폐 조회 키 (읽기 전용)",
|
||||||
"import_key_warn": "본인이 소유한 키만 가져오세요 — 해당 자금에 접근할 수 있습니다.",
|
"import_key_warn": "본인이 소유한 키만 가져오세요 — 해당 자금에 접근할 수 있습니다.",
|
||||||
"import_key_warning": "경고: 개인 키를 절대 공유하지 마세요! 신뢰할 수 없는 소스의 키를 가져오면 지갑이 위험해질 수 있습니다.",
|
"import_key_warning": "경고: 개인 키를 절대 공유하지 마세요! 신뢰할 수 없는 소스의 키를 가져오면 지갑이 위험해질 수 있습니다.",
|
||||||
|
"import_key_wrong_type": "조회 키인 것 같습니다. 대신 \"조회 키 가져오기\"를 사용하세요.",
|
||||||
"import_key_z_format": "Z 주소 지출 키 (secret-extended-key-...)",
|
"import_key_z_format": "Z 주소 지출 키 (secret-extended-key-...)",
|
||||||
"import_private_key": "개인 키 가져오기...",
|
"import_private_key": "개인 키 가져오기...",
|
||||||
|
"import_viewkey_field": "조회 키",
|
||||||
|
"import_viewkey_note": "읽기 전용: 조회 키는 주소의 잔액과 거래를 보여주지만 자금을 사용할 수는 없습니다.",
|
||||||
|
"import_viewkey_scan_hint": "0 = 처음부터 다시 스캔",
|
||||||
|
"import_viewkey_scan_label": "스캔 시작 블록 높이(선택 사항)",
|
||||||
|
"import_viewkey_title": "조회 키 가져오기",
|
||||||
|
"import_viewkey_wrong_type": "지출 키인 것 같습니다. 대신 \"키 가져오기\"를 사용하세요.",
|
||||||
"incorrect_passphrase": "잘못된 암호",
|
"incorrect_passphrase": "잘못된 암호",
|
||||||
"incorrect_pin": "잘못된 PIN",
|
"incorrect_pin": "잘못된 PIN",
|
||||||
"insufficient_funds": "이 금액과 수수료를 위한 잔액이 부족합니다.",
|
"insufficient_funds": "이 금액과 수수료를 위한 잔액이 부족합니다.",
|
||||||
@@ -1105,6 +1112,7 @@
|
|||||||
"settings_gradient_desc": "텍스처 배경을 부드러운 그라데이션으로 교체",
|
"settings_gradient_desc": "텍스처 배경을 부드러운 그라데이션으로 교체",
|
||||||
"settings_idle_after": "후",
|
"settings_idle_after": "후",
|
||||||
"settings_import_key": "키 가져오기...",
|
"settings_import_key": "키 가져오기...",
|
||||||
|
"settings_import_viewkey": "조회 키 가져오기...",
|
||||||
"settings_language_note": "참고: 일부 텍스트는 업데이트하려면 다시 시작해야 합니다",
|
"settings_language_note": "참고: 일부 텍스트는 업데이트하려면 다시 시작해야 합니다",
|
||||||
"settings_lock_now": "지금 잠금",
|
"settings_lock_now": "지금 잠금",
|
||||||
"settings_locked": "잠김",
|
"settings_locked": "잠김",
|
||||||
@@ -1252,6 +1260,7 @@
|
|||||||
"tt_font_scale": "모든 텍스트 및 UI 크기 조정 (1.0x = 기본, 최대 1.5x).",
|
"tt_font_scale": "모든 텍스트 및 UI 크기 조정 (1.0x = 기본, 최대 1.5x).",
|
||||||
"tt_idle_delay": "채굴 시작 전 대기 시간",
|
"tt_idle_delay": "채굴 시작 전 대기 시간",
|
||||||
"tt_import_key": "이 지갑에 개인키 (zkey 또는 tkey) 가져오기",
|
"tt_import_key": "이 지갑에 개인키 (zkey 또는 tkey) 가져오기",
|
||||||
|
"tt_import_viewkey": "차폐 조회 키를 가져와 주소를 조회(읽기 전용)",
|
||||||
"tt_keep_daemon": "설정 마법사를 실행하면 데몬이 여전히 중지됩니다",
|
"tt_keep_daemon": "설정 마법사를 실행하면 데몬이 여전히 중지됩니다",
|
||||||
"tt_language": "지갑 UI 인터페이스 언어",
|
"tt_language": "지갑 UI 인터페이스 언어",
|
||||||
"tt_layout_hotkey": "단축키: 좌/우 화살표 키로 잔액 레이아웃 전환",
|
"tt_layout_hotkey": "단축키: 좌/우 화살표 키로 잔액 레이아웃 전환",
|
||||||
|
|||||||
@@ -441,8 +441,15 @@
|
|||||||
"import_key_type_zview": "Chave de visualização blindada (somente leitura)",
|
"import_key_type_zview": "Chave de visualização blindada (somente leitura)",
|
||||||
"import_key_warn": "Importe apenas uma chave que você possui — ela concede acesso aos seus fundos.",
|
"import_key_warn": "Importe apenas uma chave que você possui — ela concede acesso aos seus fundos.",
|
||||||
"import_key_warning": "Aviso: Nunca compartilhe suas chaves privadas! Importar chaves de fontes não confiáveis pode comprometer sua carteira.",
|
"import_key_warning": "Aviso: Nunca compartilhe suas chaves privadas! Importar chaves de fontes não confiáveis pode comprometer sua carteira.",
|
||||||
|
"import_key_wrong_type": "Isto parece uma chave de visualização. Use \"Importar chave de visualização\".",
|
||||||
"import_key_z_format": "Chaves de gasto de z-endereço (secret-extended-key-...)",
|
"import_key_z_format": "Chaves de gasto de z-endereço (secret-extended-key-...)",
|
||||||
"import_private_key": "Importar Chave Privada...",
|
"import_private_key": "Importar Chave Privada...",
|
||||||
|
"import_viewkey_field": "Chave de visualização",
|
||||||
|
"import_viewkey_note": "Somente leitura: uma chave de visualização revela o saldo e as transações de um endereço, mas não pode gastar seus fundos.",
|
||||||
|
"import_viewkey_scan_hint": "0 = reescanear desde o início",
|
||||||
|
"import_viewkey_scan_label": "Escanear a partir da altura do bloco (opcional)",
|
||||||
|
"import_viewkey_title": "Importar chave de visualização",
|
||||||
|
"import_viewkey_wrong_type": "Isto parece uma chave de gasto. Use \"Importar chave\".",
|
||||||
"incorrect_passphrase": "Senha incorreta",
|
"incorrect_passphrase": "Senha incorreta",
|
||||||
"incorrect_pin": "PIN incorreto",
|
"incorrect_pin": "PIN incorreto",
|
||||||
"insufficient_funds": "Fundos insuficientes para este valor mais taxa.",
|
"insufficient_funds": "Fundos insuficientes para este valor mais taxa.",
|
||||||
@@ -1105,6 +1112,7 @@
|
|||||||
"settings_gradient_desc": "Substituir fundos texturizados por gradientes suaves",
|
"settings_gradient_desc": "Substituir fundos texturizados por gradientes suaves",
|
||||||
"settings_idle_after": "após",
|
"settings_idle_after": "após",
|
||||||
"settings_import_key": "Importar chave...",
|
"settings_import_key": "Importar chave...",
|
||||||
|
"settings_import_viewkey": "Importar chave de visualização...",
|
||||||
"settings_language_note": "Nota: Alguns textos requerem reinício para atualizar",
|
"settings_language_note": "Nota: Alguns textos requerem reinício para atualizar",
|
||||||
"settings_lock_now": "Bloquear agora",
|
"settings_lock_now": "Bloquear agora",
|
||||||
"settings_locked": "Bloqueado",
|
"settings_locked": "Bloqueado",
|
||||||
@@ -1252,6 +1260,7 @@
|
|||||||
"tt_font_scale": "Escalar todo o texto e interface (1.0x = padrão, até 1.5x).",
|
"tt_font_scale": "Escalar todo o texto e interface (1.0x = padrão, até 1.5x).",
|
||||||
"tt_idle_delay": "Quanto tempo esperar antes de iniciar a mineração",
|
"tt_idle_delay": "Quanto tempo esperar antes de iniciar a mineração",
|
||||||
"tt_import_key": "Importar uma chave privada (zkey ou tkey) nesta carteira",
|
"tt_import_key": "Importar uma chave privada (zkey ou tkey) nesta carteira",
|
||||||
|
"tt_import_viewkey": "Importar uma chave de visualização blindada para observar um endereço (somente leitura)",
|
||||||
"tt_keep_daemon": "O daemon será parado ao executar o assistente de configuração",
|
"tt_keep_daemon": "O daemon será parado ao executar o assistente de configuração",
|
||||||
"tt_language": "Idioma da interface da carteira",
|
"tt_language": "Idioma da interface da carteira",
|
||||||
"tt_layout_hotkey": "Atalho: teclas de seta esquerda/direita para alternar layouts de Saldo",
|
"tt_layout_hotkey": "Atalho: teclas de seta esquerda/direita para alternar layouts de Saldo",
|
||||||
|
|||||||
@@ -441,8 +441,15 @@
|
|||||||
"import_key_type_zview": "Экранированный ключ просмотра (только чтение)",
|
"import_key_type_zview": "Экранированный ключ просмотра (только чтение)",
|
||||||
"import_key_warn": "Импортируйте только свой ключ — он даёт доступ к его средствам.",
|
"import_key_warn": "Импортируйте только свой ключ — он даёт доступ к его средствам.",
|
||||||
"import_key_warning": "Предупреждение: Никогда не делитесь своими приватными ключами! Импорт ключей из ненадёжных источников может скомпрометировать ваш кошелёк.",
|
"import_key_warning": "Предупреждение: Никогда не делитесь своими приватными ключами! Импорт ключей из ненадёжных источников может скомпрометировать ваш кошелёк.",
|
||||||
|
"import_key_wrong_type": "Похоже, это ключ просмотра. Используйте «Импорт ключа просмотра».",
|
||||||
"import_key_z_format": "Ключи расходования z-адресов (secret-extended-key-...)",
|
"import_key_z_format": "Ключи расходования z-адресов (secret-extended-key-...)",
|
||||||
"import_private_key": "Импорт приватного ключа...",
|
"import_private_key": "Импорт приватного ключа...",
|
||||||
|
"import_viewkey_field": "Ключ просмотра",
|
||||||
|
"import_viewkey_note": "Только чтение: ключ просмотра показывает баланс и транзакции адреса, но не может тратить его средства.",
|
||||||
|
"import_viewkey_scan_hint": "0 = повторное сканирование с начала",
|
||||||
|
"import_viewkey_scan_label": "Сканировать с высоты блока (необязательно)",
|
||||||
|
"import_viewkey_title": "Импорт ключа просмотра",
|
||||||
|
"import_viewkey_wrong_type": "Похоже, это ключ расходования. Используйте «Импортировать ключ».",
|
||||||
"incorrect_passphrase": "Неверный пароль",
|
"incorrect_passphrase": "Неверный пароль",
|
||||||
"incorrect_pin": "Неверный PIN",
|
"incorrect_pin": "Неверный PIN",
|
||||||
"insufficient_funds": "Недостаточно средств для этой суммы плюс комиссия.",
|
"insufficient_funds": "Недостаточно средств для этой суммы плюс комиссия.",
|
||||||
@@ -1105,6 +1112,7 @@
|
|||||||
"settings_gradient_desc": "Заменить текстурные фоны плавными градиентами",
|
"settings_gradient_desc": "Заменить текстурные фоны плавными градиентами",
|
||||||
"settings_idle_after": "через",
|
"settings_idle_after": "через",
|
||||||
"settings_import_key": "Импортировать ключ...",
|
"settings_import_key": "Импортировать ключ...",
|
||||||
|
"settings_import_viewkey": "Импортировать ключ просмотра...",
|
||||||
"settings_language_note": "Примечание: Некоторый текст требует перезапуска для обновления",
|
"settings_language_note": "Примечание: Некоторый текст требует перезапуска для обновления",
|
||||||
"settings_lock_now": "Заблокировать сейчас",
|
"settings_lock_now": "Заблокировать сейчас",
|
||||||
"settings_locked": "Заблокирован",
|
"settings_locked": "Заблокирован",
|
||||||
@@ -1252,6 +1260,7 @@
|
|||||||
"tt_font_scale": "Масштабировать весь текст и интерфейс (1.0x = по умолчанию, до 1.5x).",
|
"tt_font_scale": "Масштабировать весь текст и интерфейс (1.0x = по умолчанию, до 1.5x).",
|
||||||
"tt_idle_delay": "Сколько ждать перед началом майнинга",
|
"tt_idle_delay": "Сколько ждать перед началом майнинга",
|
||||||
"tt_import_key": "Импортировать приватный ключ (zkey или tkey) в этот кошелёк",
|
"tt_import_key": "Импортировать приватный ключ (zkey или tkey) в этот кошелёк",
|
||||||
|
"tt_import_viewkey": "Импортировать экранированный ключ просмотра для наблюдения за адресом (только чтение)",
|
||||||
"tt_keep_daemon": "Демон будет остановлен при запуске мастера настройки",
|
"tt_keep_daemon": "Демон будет остановлен при запуске мастера настройки",
|
||||||
"tt_language": "Язык интерфейса кошелька",
|
"tt_language": "Язык интерфейса кошелька",
|
||||||
"tt_layout_hotkey": "Горячая клавиша: стрелки влево/вправо для переключения раскладок Баланса",
|
"tt_layout_hotkey": "Горячая клавиша: стрелки влево/вправо для переключения раскладок Баланса",
|
||||||
|
|||||||
@@ -441,8 +441,15 @@
|
|||||||
"import_key_type_zview": "屏蔽查看密钥(仅查看)",
|
"import_key_type_zview": "屏蔽查看密钥(仅查看)",
|
||||||
"import_key_warn": "只导入你自己拥有的密钥——它可访问该地址的资金。",
|
"import_key_warn": "只导入你自己拥有的密钥——它可访问该地址的资金。",
|
||||||
"import_key_warning": "警告:切勿分享您的私钥!从不可信来源导入密钥可能会危及您的钱包安全。",
|
"import_key_warning": "警告:切勿分享您的私钥!从不可信来源导入密钥可能会危及您的钱包安全。",
|
||||||
|
"import_key_wrong_type": "这看起来像查看密钥。请改用\"导入查看密钥\"。",
|
||||||
"import_key_z_format": "Z 地址花费密钥 (secret-extended-key-...)",
|
"import_key_z_format": "Z 地址花费密钥 (secret-extended-key-...)",
|
||||||
"import_private_key": "导入私钥...",
|
"import_private_key": "导入私钥...",
|
||||||
|
"import_viewkey_field": "查看密钥",
|
||||||
|
"import_viewkey_note": "仅查看:查看密钥可显示地址的余额和交易,但无法花费其资金。",
|
||||||
|
"import_viewkey_scan_hint": "0 = 从头重新扫描",
|
||||||
|
"import_viewkey_scan_label": "从区块高度开始扫描(可选)",
|
||||||
|
"import_viewkey_title": "导入查看密钥",
|
||||||
|
"import_viewkey_wrong_type": "这看起来像花费密钥。请改用\"导入密钥\"。",
|
||||||
"incorrect_passphrase": "密码错误",
|
"incorrect_passphrase": "密码错误",
|
||||||
"incorrect_pin": "PIN 错误",
|
"incorrect_pin": "PIN 错误",
|
||||||
"insufficient_funds": "余额不足以支付此金额加手续费。",
|
"insufficient_funds": "余额不足以支付此金额加手续费。",
|
||||||
@@ -1105,6 +1112,7 @@
|
|||||||
"settings_gradient_desc": "用平滑渐变替换纹理背景",
|
"settings_gradient_desc": "用平滑渐变替换纹理背景",
|
||||||
"settings_idle_after": "之后",
|
"settings_idle_after": "之后",
|
||||||
"settings_import_key": "导入密钥...",
|
"settings_import_key": "导入密钥...",
|
||||||
|
"settings_import_viewkey": "导入查看密钥...",
|
||||||
"settings_language_note": "注意:部分文本需要重启才能更新",
|
"settings_language_note": "注意:部分文本需要重启才能更新",
|
||||||
"settings_lock_now": "立即锁定",
|
"settings_lock_now": "立即锁定",
|
||||||
"settings_locked": "已锁定",
|
"settings_locked": "已锁定",
|
||||||
@@ -1252,6 +1260,7 @@
|
|||||||
"tt_font_scale": "缩放所有文本和界面(1.0x = 默认,最大 1.5x)。",
|
"tt_font_scale": "缩放所有文本和界面(1.0x = 默认,最大 1.5x)。",
|
||||||
"tt_idle_delay": "开始挖矿前等待多长时间",
|
"tt_idle_delay": "开始挖矿前等待多长时间",
|
||||||
"tt_import_key": "将私钥(zkey 或 tkey)导入此钱包",
|
"tt_import_key": "将私钥(zkey 或 tkey)导入此钱包",
|
||||||
|
"tt_import_viewkey": "导入屏蔽查看密钥以查看某个地址(只读)",
|
||||||
"tt_keep_daemon": "运行设置向导时守护进程仍会停止",
|
"tt_keep_daemon": "运行设置向导时守护进程仍会停止",
|
||||||
"tt_language": "钱包界面语言",
|
"tt_language": "钱包界面语言",
|
||||||
"tt_layout_hotkey": "快捷键:左/右箭头键切换余额布局",
|
"tt_layout_hotkey": "快捷键:左/右箭头键切换余额布局",
|
||||||
|
|||||||
58
src/app.cpp
58
src/app.cpp
@@ -2758,9 +2758,10 @@ void App::renderImportKeyDialog()
|
|||||||
{
|
{
|
||||||
namespace m = ui::material;
|
namespace m = ui::material;
|
||||||
float dp = ui::Layout::dpiScale();
|
float dp = ui::Layout::dpiScale();
|
||||||
|
const bool viewMode = import_view_mode_; // watch-only shielded viewing key vs. spending key
|
||||||
|
|
||||||
m::OverlayDialogSpec ov;
|
m::OverlayDialogSpec ov;
|
||||||
ov.title = TR("import_key_title");
|
ov.title = viewMode ? TR("import_viewkey_title") : TR("import_key_title");
|
||||||
ov.p_open = &show_import_key_;
|
ov.p_open = &show_import_key_;
|
||||||
ov.style = m::OverlayStyle::BlurFloat;
|
ov.style = m::OverlayStyle::BlurFloat;
|
||||||
ov.cardWidth = 520.0f;
|
ov.cardWidth = 520.0f;
|
||||||
@@ -2773,12 +2774,24 @@ void App::renderImportKeyDialog()
|
|||||||
import_status_.clear();
|
import_status_.clear();
|
||||||
import_result_address_.clear();
|
import_result_address_.clear();
|
||||||
import_key_reveal_ = false;
|
import_key_reveal_ = false;
|
||||||
|
sodium_memzero(import_key_scan_height_, sizeof(import_key_scan_height_));
|
||||||
}
|
}
|
||||||
// Esc dismisses (this overlay has no built-in Esc handling).
|
// Esc dismisses (this overlay has no built-in Esc handling).
|
||||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) show_import_key_ = false;
|
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) show_import_key_ = false;
|
||||||
|
|
||||||
// Handle-with-care note.
|
// Handle-with-care note. A spending key grants access to funds (strong warning); a viewing key
|
||||||
|
// is watch-only (milder, informational eye note).
|
||||||
|
if (viewMode) {
|
||||||
|
ImGui::PushFont(m::Type().iconSmall());
|
||||||
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(m::OnSurfaceMedium()), ICON_MD_VISIBILITY);
|
||||||
|
ImGui::PopFont();
|
||||||
|
ImGui::SameLine(0, 6.0f * dp);
|
||||||
|
ImGui::PushTextWrapPos(0.0f);
|
||||||
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(m::OnSurfaceMedium()), "%s", TR("import_viewkey_note"));
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
|
} else {
|
||||||
m::DialogWarningHeader(TR("import_key_warn"));
|
m::DialogWarningHeader(TR("import_key_warn"));
|
||||||
|
}
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
||||||
// A running node is required — say so up front instead of failing only after Import.
|
// A running node is required — say so up front instead of failing only after Import.
|
||||||
@@ -2788,7 +2801,7 @@ void App::renderImportKeyDialog()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Masked key field with a reveal (eye) toggle + Paste/Clear.
|
// Masked key field with a reveal (eye) toggle + Paste/Clear.
|
||||||
ImGui::TextUnformatted(TR("import_key_field"));
|
ImGui::TextUnformatted(viewMode ? TR("import_viewkey_field") : TR("import_key_field"));
|
||||||
float eyeW = ImGui::GetFrameHeight();
|
float eyeW = ImGui::GetFrameHeight();
|
||||||
ImGui::SetNextItemWidth(-(eyeW + ui::Layout::spacingSm()));
|
ImGui::SetNextItemWidth(-(eyeW + ui::Layout::spacingSm()));
|
||||||
ImGuiInputTextFlags flags = import_key_reveal_ ? 0 : ImGuiInputTextFlags_Password;
|
ImGuiInputTextFlags flags = import_key_reveal_ ? 0 : ImGuiInputTextFlags_Password;
|
||||||
@@ -2815,14 +2828,18 @@ void App::renderImportKeyDialog()
|
|||||||
std::string keyTrim(import_key_input_);
|
std::string keyTrim(import_key_input_);
|
||||||
while (!keyTrim.empty() && (keyTrim.front()==' '||keyTrim.front()=='\t'||keyTrim.front()=='\n'||keyTrim.front()=='\r')) keyTrim.erase(keyTrim.begin());
|
while (!keyTrim.empty() && (keyTrim.front()==' '||keyTrim.front()=='\t'||keyTrim.front()=='\n'||keyTrim.front()=='\r')) keyTrim.erase(keyTrim.begin());
|
||||||
while (!keyTrim.empty() && (keyTrim.back()==' '||keyTrim.back()=='\t'||keyTrim.back()=='\n'||keyTrim.back()=='\r')) keyTrim.pop_back();
|
while (!keyTrim.empty() && (keyTrim.back()==' '||keyTrim.back()=='\t'||keyTrim.back()=='\n'||keyTrim.back()=='\r')) keyTrim.pop_back();
|
||||||
bool recognized = services::WalletSecurityController::isRecognizedImportKey(keyTrim);
|
bool isView = services::WalletSecurityController::isViewingKey(keyTrim);
|
||||||
bool viewing = services::WalletSecurityController::isViewingKey(keyTrim);
|
bool isSpend = services::WalletSecurityController::isRecognizedPrivateKey(keyTrim);
|
||||||
bool shielded = services::WalletSecurityController::classifyPrivateKey(keyTrim)
|
bool shielded = services::WalletSecurityController::classifyPrivateKey(keyTrim)
|
||||||
== services::WalletSecurityController::KeyKind::Shielded;
|
== services::WalletSecurityController::KeyKind::Shielded;
|
||||||
|
// Each button accepts only its own key type; a key valid for the OTHER button is flagged with a
|
||||||
|
// redirect hint rather than lumped in with truly unrecognized input.
|
||||||
|
bool recognized = viewMode ? isView : isSpend;
|
||||||
|
bool wrongType = viewMode ? isSpend : isView;
|
||||||
|
|
||||||
if (!keyTrim.empty()) {
|
if (!keyTrim.empty()) {
|
||||||
if (recognized) {
|
if (recognized) {
|
||||||
const char* label = viewing ? TR("import_key_type_zview")
|
const char* label = viewMode ? TR("import_key_type_zview")
|
||||||
: shielded ? TR("import_key_type_zspend")
|
: shielded ? TR("import_key_type_zspend")
|
||||||
: TR("import_key_type_tkey");
|
: TR("import_key_type_tkey");
|
||||||
ImGui::PushFont(m::Type().iconSmall());
|
ImGui::PushFont(m::Type().iconSmall());
|
||||||
@@ -2831,15 +2848,32 @@ void App::renderImportKeyDialog()
|
|||||||
ImGui::SameLine(0, 4.0f * dp);
|
ImGui::SameLine(0, 4.0f * dp);
|
||||||
ImGui::TextColored(m::SuccessVec4(), "%s", label);
|
ImGui::TextColored(m::SuccessVec4(), "%s", label);
|
||||||
} else {
|
} else {
|
||||||
|
const char* msg = wrongType
|
||||||
|
? (viewMode ? TR("import_viewkey_wrong_type") : TR("import_key_wrong_type"))
|
||||||
|
: TR("import_key_type_unknown");
|
||||||
ImGui::PushFont(m::Type().iconSmall());
|
ImGui::PushFont(m::Type().iconSmall());
|
||||||
ImGui::TextColored(ImVec4(0.8f, 0.6f, 0.0f, 1.0f), ICON_MD_HELP);
|
ImGui::TextColored(ImVec4(0.8f, 0.6f, 0.0f, 1.0f), wrongType ? ICON_MD_WARNING : ICON_MD_HELP);
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
ImGui::SameLine(0, 4.0f * dp);
|
ImGui::SameLine(0, 4.0f * dp);
|
||||||
ImGui::TextColored(ImVec4(0.8f, 0.6f, 0.0f, 1.0f), "%s", TR("import_key_type_unknown"));
|
ImGui::PushTextWrapPos(0.0f);
|
||||||
|
ImGui::TextColored(ImVec4(0.8f, 0.6f, 0.0f, 1.0f), "%s", msg);
|
||||||
|
ImGui::PopTextWrapPos();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// Optional scan-from height (viewing keys only — z_importviewingkey takes a start height, so a
|
||||||
|
// watch-only import of a recent address needn't rescan the whole chain).
|
||||||
|
if (viewMode) {
|
||||||
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(m::OnSurfaceMedium()), "%s", TR("import_viewkey_scan_label"));
|
||||||
|
ImGui::SetNextItemWidth(140.0f * dp);
|
||||||
|
ImGui::InputText("##importscanheight", import_key_scan_height_, sizeof(import_key_scan_height_),
|
||||||
|
ImGuiInputTextFlags_CharsDecimal);
|
||||||
|
ImGui::SameLine(0, ui::Layout::spacingSm());
|
||||||
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(m::OnSurfaceDisabled()), "%s", TR("import_viewkey_scan_hint"));
|
||||||
|
ImGui::Spacing();
|
||||||
|
}
|
||||||
|
|
||||||
// Progress / result / error.
|
// Progress / result / error.
|
||||||
if (import_in_progress_) {
|
if (import_in_progress_) {
|
||||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(m::Primary()), "%s%s",
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(m::Primary()), "%s%s",
|
||||||
@@ -2873,7 +2907,12 @@ void App::renderImportKeyDialog()
|
|||||||
import_success_ = false;
|
import_success_ = false;
|
||||||
import_status_.clear();
|
import_status_.clear();
|
||||||
import_result_address_.clear();
|
import_result_address_.clear();
|
||||||
importPrivateKey(std::string(import_key_input_),
|
int startHeight = 0; // viewing-key only; 0 = full rescan (also the transparent/spending default)
|
||||||
|
if (viewMode && import_key_scan_height_[0]) {
|
||||||
|
startHeight = std::atoi(import_key_scan_height_);
|
||||||
|
if (startHeight < 0) startHeight = 0;
|
||||||
|
}
|
||||||
|
importPrivateKey(std::string(import_key_input_), startHeight,
|
||||||
[this](bool ok, const std::string& err, const std::string& addr) {
|
[this](bool ok, const std::string& err, const std::string& addr) {
|
||||||
import_in_progress_ = false;
|
import_in_progress_ = false;
|
||||||
import_success_ = ok;
|
import_success_ = ok;
|
||||||
@@ -2894,6 +2933,7 @@ void App::renderImportKeyDialog()
|
|||||||
// show_import_key_ mid-frame). in_progress is left to the callback to clear.
|
// show_import_key_ mid-frame). in_progress is left to the callback to clear.
|
||||||
if (!show_import_key_) {
|
if (!show_import_key_) {
|
||||||
sodium_memzero(import_key_input_, sizeof(import_key_input_));
|
sodium_memzero(import_key_input_, sizeof(import_key_input_));
|
||||||
|
sodium_memzero(import_key_scan_height_, sizeof(import_key_scan_height_));
|
||||||
import_status_.clear();
|
import_status_.clear();
|
||||||
import_result_address_.clear();
|
import_result_address_.clear();
|
||||||
import_success_ = false;
|
import_success_ = false;
|
||||||
|
|||||||
@@ -302,7 +302,8 @@ public:
|
|||||||
void exportAllKeys(std::function<void(const std::string&, int, int)> callback);
|
void exportAllKeys(std::function<void(const std::string&, int, int)> callback);
|
||||||
// callback(success, errorOrEmpty, importedAddress). address is "" on failure or when the RPC
|
// 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.
|
// 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<void(bool, const std::string&, const std::string&)> callback);
|
std::function<void(bool, const std::string&, const std::string&)> callback);
|
||||||
|
|
||||||
// Wallet backup
|
// Wallet backup
|
||||||
@@ -373,7 +374,8 @@ public:
|
|||||||
std::string screenshotDir() const; // <config>/screenshots (fixed; sweeps overwrite in place)
|
std::string screenshotDir() const; // <config>/screenshots (fixed; sweeps overwrite in place)
|
||||||
|
|
||||||
// Dialog triggers (used by settings page to open modal dialogs)
|
// 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 showExportKeyDialog() { show_export_key_ = true; }
|
||||||
void showBackupDialog() { show_backup_ = true; }
|
void showBackupDialog() { show_backup_ = true; }
|
||||||
void showSeedBackupDialog() { show_seed_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_key_reveal_ = false; // show the key in plaintext (default masked)
|
||||||
bool import_in_progress_ = false; // an import + rescan is running (disable/spinner)
|
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)
|
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_;
|
std::string backup_status_;
|
||||||
bool backup_success_ = false;
|
bool backup_success_ = false;
|
||||||
|
|
||||||
|
|||||||
@@ -2921,7 +2921,7 @@ void App::exportAllKeys(std::function<void(const std::string&, int, int)> callba
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::importPrivateKey(const std::string& rawKey,
|
void App::importPrivateKey(const std::string& rawKey, int startHeight,
|
||||||
std::function<void(bool, const std::string&, const std::string&)> callback)
|
std::function<void(bool, const std::string&, const std::string&)> callback)
|
||||||
{
|
{
|
||||||
if (!state_.connected || !rpc_ || !worker_) {
|
if (!state_.connected || !rpc_ || !worker_) {
|
||||||
@@ -2947,7 +2947,7 @@ void App::importPrivateKey(const std::string& rawKey,
|
|||||||
== services::WalletSecurityController::KeyKind::Shielded;
|
== services::WalletSecurityController::KeyKind::Shielded;
|
||||||
// Run on the worker thread — import requests a full rescan (rescan=true), so the
|
// 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.
|
// 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;
|
std::string err, addr;
|
||||||
try {
|
try {
|
||||||
rpc::RPCClient::TraceScope trace("Settings / Import key");
|
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
|
if (viewing) { method = "z_importviewingkey"; params = {key, "yes"}; } // watch-only
|
||||||
else if (shielded) { method = "z_importkey"; params = {key, "yes"}; }
|
else if (shielded) { method = "z_importkey"; params = {key, "yes"}; }
|
||||||
else { method = "importprivkey"; params = {key, "", true}; }
|
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);
|
nlohmann::json r = rpc_->call(method, params);
|
||||||
// z_import* return {type,address}; importprivkey returns the t-address string.
|
// z_import* return {type,address}; importprivkey returns the t-address string.
|
||||||
if (r.is_object() && r.contains("address") && r["address"].is_string())
|
if (r.is_object() && r.contains("address") && r["address"].is_string())
|
||||||
|
|||||||
@@ -261,7 +261,9 @@ void App::buildSweepCatalog()
|
|||||||
|
|
||||||
// Simple bool-flag modals.
|
// Simple bool-flag modals.
|
||||||
add("modal-import-key", ui::NavPage::Overview,
|
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,
|
add("modal-export-key", ui::NavPage::Overview,
|
||||||
[](App& a) { a.show_export_key_ = true; }, [](App& a) { a.show_export_key_ = false; });
|
[](App& a) { a.show_export_key_ = true; }, [](App& a) { a.show_export_key_ = false; });
|
||||||
add("modal-backup", ui::NavPage::Overview,
|
add("modal-backup", ui::NavPage::Overview,
|
||||||
|
|||||||
@@ -1349,12 +1349,14 @@ void RenderSettingsPage(App* app) {
|
|||||||
float naturalW = 0;
|
float naturalW = 0;
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
naturalW += ImGui::CalcTextSize(r1[i]).x + btnPadX;
|
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 wizW = showFullNodeLifecycleActions ? ImGui::CalcTextSize(wizLabel).x + btnPadX : 0.0f;
|
||||||
float bsW = showFullNodeLifecycleActions ? ImGui::CalcTextSize(bsLabel).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.
|
// 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 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 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;
|
if (showFullNodeLifecycleActions) totalW += wizW + bsW + seedW + migrateW + sp * 4;
|
||||||
|
|
||||||
float scale = (totalW > contentW) ? contentW / totalW : 1.0f;
|
float scale = (totalW > contentW) ? contentW / totalW : 1.0f;
|
||||||
@@ -1364,6 +1366,11 @@ void RenderSettingsPage(App* app) {
|
|||||||
if (TactileButton(r1[0], ImVec2(0, 0), btnFont))
|
if (TactileButton(r1[0], ImVec2(0, 0), btnFont))
|
||||||
app->showImportKeyDialog();
|
app->showImportKeyDialog();
|
||||||
if (ImGui::IsItemHovered()) material::Tooltip("%s", t1[0]);
|
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);
|
ImGui::SameLine(0, scaledSp);
|
||||||
if (TactileButton(r1[1], ImVec2(0, 0), btnFont))
|
if (TactileButton(r1[1], ImVec2(0, 0), btnFont))
|
||||||
app->showExportKeyDialog();
|
app->showExportKeyDialog();
|
||||||
|
|||||||
@@ -429,6 +429,7 @@ void I18n::loadBuiltinEnglish()
|
|||||||
strings_["settings_merge_to_address"] = "Merge to Address...";
|
strings_["settings_merge_to_address"] = "Merge to Address...";
|
||||||
strings_["settings_clear_ztx"] = "Clear Z-Tx History";
|
strings_["settings_clear_ztx"] = "Clear Z-Tx History";
|
||||||
strings_["settings_import_key"] = "Import Key...";
|
strings_["settings_import_key"] = "Import Key...";
|
||||||
|
strings_["settings_import_viewkey"] = "Import Viewing Key...";
|
||||||
strings_["settings_export_key"] = "Export Key...";
|
strings_["settings_export_key"] = "Export Key...";
|
||||||
strings_["settings_export_all"] = "Export All...";
|
strings_["settings_export_all"] = "Export All...";
|
||||||
strings_["settings_backup"] = "Backup...";
|
strings_["settings_backup"] = "Backup...";
|
||||||
@@ -731,6 +732,7 @@ void I18n::loadBuiltinEnglish()
|
|||||||
|
|
||||||
// Settings: additional tooltips (keys/data row)
|
// Settings: additional tooltips (keys/data row)
|
||||||
strings_["tt_import_key"] = "Import a private key (zkey or tkey) into this wallet";
|
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_key"] = "Export the private key for the selected address";
|
||||||
strings_["tt_export_all"] = "Export all private keys to a file";
|
strings_["tt_export_all"] = "Export all private keys to a file";
|
||||||
strings_["tt_backup"] = "Create a backup of your wallet.dat 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_done"] = "Imported. Wallet is rescanning.";
|
||||||
strings_["import_key_address"] = "Address:";
|
strings_["import_key_address"] = "Address:";
|
||||||
strings_["import_key_import"] = "Import";
|
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 ---
|
// --- Key Export Dialog ---
|
||||||
strings_["key_export_fetching"] = "Fetching key from wallet...";
|
strings_["key_export_fetching"] = "Fetching key from wallet...";
|
||||||
|
|||||||
Reference in New Issue
Block a user