restore method

  1. @override
Future<WalletSession> restore(
  1. List<String> mnemonicWords, {
  2. DateTime? approximateCreationTime,
})
override

RESTORE an existing wallet from its BIP39 recovery phrase — the ONE sanctioned INBOUND key crossing (spec §3.3; counterpart to the outbound revealMnemonic). mnemonicWords are the recovery words in order.

THE LOWERCASE CONTRACT (a HARD money-reliability requirement): the words MUST already be lowercased + trimmed — the SDK keeps the audited bip39 parser whole and does NOT case-fold, so a mis-cased/space-padded word is rejected as a typed invalidMnemonic carrying its INDEX and a CORRECT backup would fail to restore. The OnboardingController enforces this at its startRestore chokepoint via normalizeMnemonicInput; this method trusts that contract (it does not re-normalize — re-casing key material is the controller's single responsibility, kept off the device adapter).

approximateCreationTime is the OPTIONAL wallet-creation time used to floor the restore scan (faster than a full history scan). The adapter converts it to a birthday HEIGHT via the SDK's conservative estimateBirthday and the configured network, then rides it on config.birthdayHeight (the ONE source of truth — create/open read the same field). null means "I don't know": the scan floors to Sapling activation — a full, slower, but money-SAFE scan that never silently skips older funds (NEVER ~tip).

LOCAL-ONLY, same BOUNDEDNESS CONTRACT as createGenerated: BIP39 validation + seed seal + SQLCipher provision are disk + keychain; the first chain round-trip is the sync engine's job. NON-CLOBBER: throws (typed) walletAlreadyExists over a completed wallet (the sealed seed is NEVER overwritten) and seedMismatch if a DIFFERENT phrase is restored over an interrupted-create remnant — both are structural in the SDK, so the boot fork (restore offered only from Welcome, i.e. walletExists() == false) rarely sees them.

KEY RESIDUE (§10): the inbound word-list copy lives in Dart memory (which cannot be zeroized) only until Rust owns it as a SeedSource; the same minimal, documented residue as the outbound reveal — minimised, not eliminated. No BIP39 passphrase ("25th word") is exposed here: the reference app restores standard phrases (matching its passphrase-free create path); a passphrase wallet is an expert case, deferred (manager-flagged).

Implementation

@override
Future<WalletSession> restore(
  List<String> mnemonicWords, {
  DateTime? approximateCreationTime,
}) async {
  restoreCount++;
  lastRestoreWords = mnemonicWords;
  lastRestoreCreationTime = approximateCreationTime;
  if (holdRestore != null) await holdRestore!.future;
  if (failRestore != null) throw failRestore!;
  exists = true; // a restored wallet now exists on disk
  return session;
}