#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; } } // namespace dragonx