#pragma once #include // Pure routing decision for resuming a pending migrate-to-seed flow (finding W3-3). Kept free of // App/UI/RPC state so the highest-risk branch — where a reopened migration lands — is unit-testable // and reviewable in isolation. App::showSeedMigrationDialog feeds it the persisted state + live // connectivity and switches on the result. See src/app_network.cpp. namespace dragonx { enum class MigrationResume { Intro, // no pending migration → start fresh at the intro Confirming, // a sweep txid is persisted → resume at the confirm/adopt gate (re-derived from chain) RetrackOpid, // a sweep opid (but no txid yet) is persisted AND we're connected → re-poll it SweepGate, // otherwise → the dismissable Sweep step (reload balance, offer re-sweep) }; // Decide where reopening the migration dialog lands. // // Invariant: the txid outranks the opid — once a sweep resolves to a txid the opid is cleared in the // same settings write, so a persisted txid always means "past the sweep". A persisted opid is only // re-tracked when connected, because the buttonless "Sweeping" spinner relies on the opid poller // (which needs an RPC connection) to ever exit; disconnected, we fall back to the dismissable Sweep // gate (which reloads the balance and, if the earlier sweep already drained it, short-circuits to // adopt) — never trapping the user. inline MigrationResume decideSeedMigrationResume(bool pending, bool haveDest, const std::string& sweepTxid, const std::string& sweepOpid, bool connected) { if (!pending || !haveDest) return MigrationResume::Intro; if (!sweepTxid.empty()) return MigrationResume::Confirming; if (!sweepOpid.empty() && connected) return MigrationResume::RetrackOpid; return MigrationResume::SweepGate; } // At the Sweep step with a ~0 legacy balance, may we offer the direct "no funds -> adopt" short-cut // (swap wallet.dat immediately)? Only when NO sweep has been submitted — a genuinely empty wallet. // If a sweep WAS submitted, a ~0 balance is ambiguous: the sweep tx may be unconfirmed in the mempool // and could revert on a drop/reorg, so adopting now can strand the funds in the moved-aside backup. // In that case adopt must go through the confirmation-gated path (>=1 conf) instead — never swap // wallet.dat on an unconfirmed sweep. (fund-safety: audit) inline bool sweepGateMayAdoptEmptyWallet(bool sweepSubmitted) { return !sweepSubmitted; } } // namespace dragonx