Skip to content

feat(gui): wallet setup wizard, named wallets, and wallet switcher#1148

Open
binarybaron wants to merge 7 commits into
masterfrom
feat/wallet-setup-wizard
Open

feat(gui): wallet setup wizard, named wallets, and wallet switcher#1148
binarybaron wants to merge 7 commits into
masterfrom
feat/wallet-setup-wizard

Conversation

@binarybaron

@binarybaron binarybaron commented Jul 2, 2026

Copy link
Copy Markdown

No description provided.

binarybaron added 2 commits July 2, 2026 10:37
Applied from stash 85824882 (feat/bob-concurrent-swaps) onto master.

- Seed selection dialog is now a step-based wizard driven by a single
  state machine (mode flows in a FLOWS table, reducer with guarded
  transitions): create a wallet with user-chosen name/directory and a
  mandatory seed backup step, restore from seed with word autocomplete,
  or open a wallet file (drag & drop + recent wallets).
- New wallets are stored under a user-chosen name instead of a unix
  timestamp; creation refuses to overwrite an existing wallet
  (<name> and <name>.keys checked without extension truncation).
- Wallet switcher on the Monero wallet page: records a
  PendingWalletAction marker consumed on next startup, then relaunches.
- New Tauri commands: get_seed_words (vendored English wordlist,
  verified identical to monero/src/mnemonics/english.h),
  get_recent_wallets, set_pending_wallet.
Review findings from three parallel reviewers, applied:

Backend:
- Wallet create/open failures (e.g. duplicate wallet name) no longer
  abort context initialization: the open loop treats every per-attempt
  failure as one outcome and re-prompts the seed chooser, matching the
  existing password-rejection recovery.
- Pending-wallet marker: atomic write (tmp + rename), corrupt markers
  are discarded with a warning instead of failing startup, and an Open
  marker pointing at a deleted wallet falls back to the chooser.
- new_wallet_path hoisted to module level; also rejects empty names and
  non-absolute directories at the IPC trust boundary.
- TauriEmitter::request_seed_selection_with_recent_wallets renamed to
  request_seed_selection, taking SeedSelectionDetails directly.
- SetPendingWalletArgs derives the data dir via eigenwallet_data::new,
  same source as the startup reader.

Wizard (state machine completed):
- Form fields moved into the editing variant; backingUp carries the
  editing state for rollback and owns the backup confirmation; reset
  rebuilds everything so no password/seed leaks across requests.
- walletCreationStarted guarded to RandomSeed@nameLocation.
- Async seed validation tagged with the seed it belongs to (no stale
  responses), primary/legacy buttons surface errors via snackbar.
- BackupSeedStep: checkbox controlled by parent; a failed seed fetch
  unlocks Finish instead of hard-locking the modal; 5 retries not 60.
- NameLocationStep: no error styling on pristine name field.

Switcher:
- Failed relaunch neutralizes the marker so a later manual launch
  cannot silently switch wallets.
- Picking a .keys file resolves to the wallet file itself.
- Confirm dialog keeps its copy while fading out; explicit warning when
  a funds-locked swap is running; chip label capped at 220px.
- NewPasswordInput setPassword prop loosened to (password: string) =>
  void (it never used functional updates).
Comment thread src-gui/src/renderer/components/modal/seed-selection/OpenWalletStep.tsx Outdated
Scope the PR down to the setup wizard. Removed:
- WalletSwitcher component and its MoneroWalletPage overlay
- get_recent_wallets / set_pending_wallet Tauri commands and their
  request types
- PendingWalletAction and the pending_wallet marker read/write plus
  resolve_startup_seed_choice (startup asks the chooser directly again)

Kept from the switcher review where it still applies:
- OpenWalletStep resolves a picked/dropped <name>.keys file to the
  wallet file itself
- NameLocationStep Browse now uses PromiseInvokeButton (async folder
  picker with error snackbar) instead of a bare Button
Trims the wizard further: the restore step is a plain multiline
TextField again (as on master). Removes SeedPhraseInput, the
get_seed_words command and request types, and the vendored 1626-word
English wordlist (swap/src/cli/api/seed_words.rs). Seed validity is
still checked via the existing check_seed command.
const path = event.payload.paths[0];
// Users commonly pick the `<name>.keys` file; the wallet is the
// file without that extension.
if (path) setWalletPath(path.replace(/\.keys$/, ""));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keys suffix strips wallet basename

Medium Severity

Drag-and-drop and the file picker always remove a trailing .keys from the chosen path. That is correct when the user selects the keys sidecar, but if the wallet’s on-disk name itself ends with .keys (allowed by the name step), selecting the main wallet file strips that suffix and sends the wrong wallet_path to open.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 99882c5. Configure here.

The init flow now lives in swap/src/cli/api/wallet_setup.rs as an
explicit state machine:

    ChooseSeed -> OpenWallet -> BackupSeed -> Finish

Every state that needs user input blocks on a Tauri approval; failures
and password rejections fall back to ChooseSeed. New SeedBackup
approval (ApprovalRequestType::SeedBackup) carries the freshly created
wallet's seed + restore height from Rust, so the GUI no longer polls
moneroWalletAvailable and re-fetches the seed with retries.

Frontend consequences:
- BackupSeedStep is purely presentational (props in, checkbox out);
  the retry loop, failure state, and availability gating are gone.
- The dialog renders whichever backend request is pending (SeedBackup
  -> backup step, SeedSelection -> wizard) plus a local spinner while
  the wallet is being created; its reducer shrinks to pure wizard
  navigation (mode/step/fields) - backingUp/finished phases, rollback
  resume state, and creation events are deleted.
- useIsMoneroWalletAvailable removed (last consumer gone).

Same UI look throughout: dialog shell, breadcrumbs, steps unchanged.

The legacy-wallet helpers and their tests move along into
wallet_setup.rs; mod wallet in api.rs keeps only init_bitcoin_wallet.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3100afd. Configure here.

? ("wizard" as const)
: waitingForWallet
? ("waiting" as const)
: null;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spinner blocks after skipped backup

High Severity

After creating a wallet, waitingForWallet keeps the setup dialog open until a SeedBackup approval arrives. If the backend skips that step (for example when reading the seed fails and startup continues anyway), no approval is emitted and waitingForWallet is never cleared, so the modal stays on “Creating your new wallet…” over a loaded app.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3100afd. Configure here.

binarybaron added 2 commits July 2, 2026 11:46
Reorder the RandomSeed flow in the FLOWS table: chooseMode ->
nameLocation -> randomPassword -> backupSeed. The password step now
carries the createWallet action; everything else derives from the
table.
The reset effect for the SeedBackup approval had the approval object in
its dependency array; the object's identity changes on every store
update (approvals are re-emitted during startup), so the effect re-ran
constantly and cleared backupConfirmed. Key it on the stable request_id
with the same ref guard the selection reset uses.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant