// DragonX Wallet - ImGui Edition // Copyright 2024-2026 The Hush Developers // Released under the GPLv3 // // seed_phrase.h — shared, pure helpers for validating a pasted BIP39 recovery phrase. // One source of truth for the seed-length contract so the lite-restore gates (first-run // wizard + Settings) cannot drift apart. No I/O, no secrets retained — safe for both variants. #pragma once #include namespace dragonx { namespace util { // Normalize a pasted recovery phrase for consistent word counting AND backend submission: // - every run of Unicode/ASCII whitespace (incl. NBSP U+00A0, en/em spaces U+2000–200A, // U+202F, U+205F, ideographic U+3000, NEL, tab/newline) collapses to a single ASCII space, // - zero-width marks (U+200B/C/D, U+FEFF BOM) are stripped, // - leading/trailing space is trimmed. // Word bytes are copied verbatim — only these exact whitespace byte-sequences are substituted. // The lite backend (tiny-bip39) splits on the literal ASCII space and does NO Unicode folding, so // a phrase pasted with NBSPs (common from PDFs/note apps) is otherwise unrestorable; normalizing // before submit makes the words space-separated and recoverable. std::string normalizeSeedPhrase(const std::string& raw); // Count ASCII-whitespace-separated words. Pair with normalizeSeedPhrase so exotic spacing counts right. int seedPhraseWordCount(const std::string& phrase); // True if `words` is a complete recovery phrase the DragonX backends accept. DragonX seeds are // 24-word / 256-bit / 32-byte-entropy ONLY: the SDXL lite backend's LightWallet::new copies the // phrase entropy into a fixed [u8;32] (a shorter valid-BIP39 phrase — 12/15/18/21 words — makes it // panic, uncaught, across the restore FFI), and the full-node daemon likewise generates 24 words. // Both lite-restore gates MUST use this so a crash-inducing length is refused client-side. bool isCompleteRecoveryPhrase(int words); } // namespace util } // namespace dragonx