Fix restoring duplicate hardware wallet (#2673)
What changed, and why it matters
This commit fixes a bug where restoring the same hardware wallet twice could create duplicate wallet entries. The change makes the wallet creation code reuse a single WalletInfo object instead of creating a separate copy, ensuring that saving updates the existing record rather than potentially writing a new one. There is no direct evidence of a security vulnerability such as theft of funds; the issue appears to be a data-integrity/duplicate-record bug.
Treat as a routine bug fix. Review whether duplicate WalletInfo records could cause user confusion, incorrect balance display, or wallet-selection issues. No immediate security patch urgency is indicated by the diff alone.
Security signals we found
Bug fix for duplicate wallet records during hardware wallet restore
Removal of unused Hive import
Change in object identity/reference handling for wallet metadata
Evidence from the diff
In lib/view_model/wallet_creation_vm.dart the code previously constructed a WalletInfo.external(…) object, assigned it to a local variable walletInfo, then assigned that local to credentials.walletInfo. After processing the wallet it mutated walletInfo and saved it. The patch removes the local variable and assigns the WalletInfo directly to credentials.walletInfo, then mutates and saves credentials.walletInfo!. The import of package:hive/hive.dart is also removed as unused. The stated purpose is to prevent duplicate hardware-wallet restoration. The diff does not show any cryptographic, authentication, or access-control changes; it is a state-consistency fix.
Changed components
lib/view_model/wallet_creation_vm.dartWalletInfo persistence during hardware wallet restore/creationInspect captured patch +6 / −9
diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart
index 7338db5f..a8b71b97 100644
--- a/lib/view_model/wallet_creation_vm.dart
+++ b/lib/view_model/wallet_creation_vm.dart
@@ -17,7 +17,6 @@ import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
-import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:polyseed/polyseed.dart';
@@ -94,7 +93,7 @@ abstract class WalletCreationVMBase with Store {
final diId = await di!.save();
credentials.derivationInfo = di;
- final walletInfo = WalletInfo.external(
+ credentials.walletInfo = WalletInfo.external(
id: WalletBase.idFor(name, type),
name: name,
type: type,
@@ -109,16 +108,14 @@ abstract class WalletCreationVMBase with Store {
hardwareWalletType: credentials.hardwareWalletType,
);
- credentials.walletInfo = walletInfo;
- // await walletInfo.save();
- printV("derivationInfo: ${(await walletInfo.getDerivationInfo()).toJson()}");
+ printV("derivationInfo: ${(await credentials.walletInfo!.getDerivationInfo()).toJson()}");
final wallet = await process(credentials);
final isNonSeedWallet = isRecovery ? wallet.seed == null : false;
- walletInfo.isNonSeedWallet = isNonSeedWallet;
- walletInfo.hashedWalletIdentifier = createHashedWalletIdentifier(wallet);
- walletInfo.address = wallet.walletAddresses.address;
- await walletInfo.save();
+ credentials.walletInfo!.isNonSeedWallet = isNonSeedWallet;
+ credentials.walletInfo!.hashedWalletIdentifier = createHashedWalletIdentifier(wallet);
+ credentials.walletInfo!.address = wallet.walletAddresses.address;
+ await credentials.walletInfo!.save();
await _appStore.changeCurrentWallet(wallet);
_appStore.authenticationStore.allowedCreate();
state = ExecutedSuccessfullyState();
Why this scored 30/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.