New full-node wallets now get a real 24-word recovery phrase, and users can reveal/back it up from Settings. - Pass -usemnemonic=1 to dragonxd. The daemon reads it only inside GenerateNewSeed() when a wallet has no seed yet, so it is inert on existing wallets (safe to pass unconditionally) and makes every freshly-created wallet mnemonic-backed — its phrase is then exportable via z_exportmnemonic and portable to SDXLite/ObsidianDragonLite. (Existing/legacy wallets are unaffected and keep using the chat identity's z_exportkey fallback.) - App::exportSeedPhrase() wraps z_exportmnemonic on the RPC worker with sodium_memzero wiping on every path; it flags the daemon's "not derived from a mnemonic" error as a legacy wallet rather than a failure. - New "Back up seed phrase" modal (Settings -> Backup & Data, full-node gated): reveals the phrase in a numbered word grid, copy (45s clipboard auto-clear) + save-to-file (0600), wipes the secret on every close path incl. dismiss-mid-fetch. Shared ui/windows/seed_display.h grid helper. - One-time nudge (settings flag seed_backup_reminded) toasts mnemonic-wallet users to back up their phrase; legacy wallets are not nagged. - 15 new strings translated into all 8 languages (additive, 957->972 keys); CJK subset font rebuilt for the new glyphs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
47 lines
1.4 KiB
C++
47 lines
1.4 KiB
C++
#pragma once
|
|
|
|
// Shared helpers for rendering a BIP39 seed phrase as a numbered word grid and for
|
|
// splitting a whitespace-separated phrase into words. Used by the full-node seed-phrase
|
|
// backup dialog and the "migrate to a seed wallet" flow so both present the phrase the
|
|
// same way the lite welcome wizard does.
|
|
|
|
#include <cstdio>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "imgui.h"
|
|
|
|
namespace dragonx {
|
|
namespace ui {
|
|
|
|
// Split a whitespace-separated seed phrase into its individual words.
|
|
inline std::vector<std::string> SplitSeedWords(const std::string& phrase)
|
|
{
|
|
std::vector<std::string> words;
|
|
std::string cur;
|
|
for (char c : phrase) {
|
|
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
|
if (!cur.empty()) { words.push_back(cur); cur.clear(); }
|
|
} else {
|
|
cur.push_back(c);
|
|
}
|
|
}
|
|
if (!cur.empty()) words.push_back(cur);
|
|
return words;
|
|
}
|
|
|
|
// Render the words as a numbered 4-column grid (matches the lite welcome wizard layout).
|
|
inline void RenderSeedWordGrid(const std::vector<std::string>& words, float colSpacingPx = 130.0f)
|
|
{
|
|
for (size_t i = 0; i < words.size(); ++i) {
|
|
char cell[96];
|
|
std::snprintf(cell, sizeof(cell), "%2zu. %s", i + 1, words[i].c_str());
|
|
ImGui::TextUnformatted(cell);
|
|
if ((i % 4) != 3 && i + 1 < words.size())
|
|
ImGui::SameLine(((i % 4) + 1) * colSpacingPx);
|
|
}
|
|
}
|
|
|
|
} // namespace ui
|
|
} // namespace dragonx
|