fix: handle already-joined vault on QR scan instead of hanging#4287
Merged
Conversation
Joining a QR for an existing seed-phrase vault on a device that already has it threw DuplicateVaultException after keygen, leaving the success screen stuck on an infinite spinner. Detect the duplicate by hexChainCode in JoinKeygenViewModel and route to the existing vault's Home before keygen starts. As a defence in depth, KeygenViewModel.saveVault now catches DuplicateVaultException on the non-override path and routes to Home so the success screen cannot hang on save failure. Co-Authored-By: aminsato <Amin.saradar@yahoo.com>
Contributor
📝 WalkthroughWalkthroughAdds duplicate-vault detection to the keygen join/save flows: JoinKeygenViewModel checks decoded join payload against existing vaults by Changes
Sequence Diagram(s)sequenceDiagram
participant UI as JoinKeygenScreen
participant VM as JoinKeygenViewModel
participant Repo as VaultRepository
participant Nav as Navigator
participant Keygen as KeygenSession/Mediator
UI->>VM: submit decoded join payload (hexChainCode)
VM->>Repo: read existingVaults()
alt matching hexChainCode found
VM-->>UI: set JoinKeygenUiModel(alreadyJoined)
UI->>Nav: openExistingVault(vaultId, clearBackStack=true)
else no match
VM->>Keygen: start keygen/session
Keygen->>VM: produce Vault (pubKeyECDSA)
VM->>Repo: saveVault(vault)
alt DuplicateVaultException thrown
VM->>Repo: getByEcdsa(pubKeyECDSA) -> existingVault
VM->>Keygen: stopMediator()
VM->>Nav: openExistingVault(existingVault.id, clearBackStack=true)
else saved successfully
VM->>Nav: navigate to new vault home
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Replaces the silent redirect with an info screen that names the existing vault and offers an explicit 'Open vault' button, so the user understands what happened. Adds the two new strings (info text and button label) to all 10 supported locales. Co-Authored-By: aminsato <Amin.saradar@yahoo.com>
Co-Authored-By: aminsato <Amin.saradar@yahoo.com>
Collaborator
Author
|
@codetabbitai full review |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #4282 — joining a QR for an existing seed-phrase vault on a device that already has it threw
DuplicateVaultExceptionafter keygen completed, leaving the Vault created successfully screen stuck on an infinite spinner.JoinKeygenViewModel(KEYGEN/KeyImport branch) now compares the QR'shexChainCodeagainst existing vaults before doing anything. If a match is found, it skips mediator discovery + keygen entirely and routes toRoute.Home(openVaultId = existingVault.id). The non-blank guard prevents matching legacy vaults that have an empty stored chain code.KeygenViewModel.saveVault()now catchesDuplicateVaultExceptionon the non-override path (onlyKEYGEN/KeyImportcan hit it; reshare/migrate useupsert). On catch it looks up the existing vault bypubKeyECDSA, stops the mediator service, and routes to Home — so the success screen never hangs even if the earlyhexChainCodecheck ever misses (e.g. the QR carries an empty chain code, or another flow saved the vault concurrently).Screen_recording_20260426_050958.webm
Why two layers
The early
hexChainCodecheck is the user-friendly path: skip the whole join when we already know the vault is here. The save-side catch protects the cases the early check can miss — initiating-device flows, blank/legacy chain codes, races against another save — so we never regress to the original infinite spinner.Test plan
DuplicateVaultException).🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
New Features
Localization