Fix restore height showing up as 0 for new wallet
What changed, and why it matters
This commit fixes a UI bug where a newly created wallet's 'restore height' was displayed as 0 instead of the current blockchain height. The restore height tells the wallet from which point in the blockchain to start scanning for transactions. Showing 0 was incorrect and could mislead users, but it did not expose funds or allow unauthorized access. The fix stores the correct height when a wallet is created and reads it back reliably.
No security action required. Treat as a normal bug-fix release. If desired, verify that the persisted restore height is cleared on wallet deletion (the patch does this) and that no stale value carries over when a user creates a new wallet after deleting an old one.
Security signals we found
No cryptographic, authentication, or authorization changes
No input validation or parsing changes affecting untrusted data
Fixes a UI/display inconsistency for newly created wallets
Adds persistence of wallet restore height to SharedPreferences
No network, IPC, or privilege boundary changes
Evidence from the diff
The patch refactors SharedPreferences access into a service and adds a persisted walletRestoreHeight key. When createWallet() generates a new polyseed, it now saves currentHeight to SharedPreferences and awaits store(). A new getRestoreHeight() method returns the wallet’s refresh-from-block-height if available, otherwise falls back to the persisted value. The LwsKeysScreen now uses this method instead of reading the raw wallet value and defaulting to the current blockchain height. The bug was a display/logic issue, not a cryptographic or access-control flaw.
Changed components
lib/models/wallet_model.dartlib/screens/lws_keys.dartlib/services/shared_preferences_service.dartInspect captured patch +36 / −19
diff --git a/lib/models/wallet_model.dart b/lib/models/wallet_model.dart
index f5813f0..8432c98 100644
--- a/lib/models/wallet_model.dart
+++ b/lib/models/wallet_model.dart
@@ -284,13 +284,17 @@ class WalletModel with ChangeNotifier {
);
}
- SharedPreferences prefs = await SharedPreferences.getInstance();
- prefs.setInt('txHistoryCount', _txHistory!.length);
+ await SharedPreferencesService.set<int>(
+ SharedPreferencesKeys.txHistoryCount,
+ _txHistory!.length,
+ );
}
Future<int> getPersistedTxHistoryCount() async {
- SharedPreferences prefs = await SharedPreferences.getInstance();
- return prefs.getInt('txHistoryCount') ?? 0;
+ return await SharedPreferencesService.get<int>(
+ SharedPreferencesKeys.txHistoryCount,
+ ) ??
+ 0;
}
void setConnection({
@@ -387,13 +391,30 @@ class WalletModel with ChangeNotifier {
final polyseed = await Isolate.run(() => monero.Wallet_createPolyseed());
final currentHeight = await getCurrentBlockchainHeight();
await restoreFromMnemonic(polyseed, currentHeight);
+ await SharedPreferencesService.set<int>(
+ SharedPreferencesKeys.walletRestoreHeight,
+ currentHeight,
+ );
await refresh();
await connectToDaemon();
- store();
+ await store();
return polyseed;
}
+ Future<int> getRestoreHeight() async {
+ var w2RestoreHeight = _w2Wallet!.getRefreshFromBlockHeight();
+
+ if (w2RestoreHeight > 0) {
+ return w2RestoreHeight;
+ }
+
+ return await SharedPreferencesService.get<int>(
+ SharedPreferencesKeys.walletRestoreHeight,
+ ) ??
+ 0;
+ }
+
Future<int> getCurrentHeight() {
final wmFfiAddr = _w2WalletManager.ffiAddress();
@@ -518,8 +539,10 @@ class WalletModel with ChangeNotifier {
final path = await getWalletPath();
await File(path).delete();
- final prefs = await SharedPreferences.getInstance();
- prefs.remove('txHistoryCount');
+ await SharedPreferencesService.remove(SharedPreferencesKeys.txHistoryCount);
+ await SharedPreferencesService.remove(
+ SharedPreferencesKeys.walletRestoreHeight,
+ );
}
Future<bool> hasExistingWallet() async {
diff --git a/lib/screens/lws_keys.dart b/lib/screens/lws_keys.dart
index 9428ee8..11a410e 100644
--- a/lib/screens/lws_keys.dart
+++ b/lib/screens/lws_keys.dart
@@ -4,7 +4,6 @@ import 'package:provider/provider.dart';
import 'package:monero_light_wallet/l10n/app_localizations.dart';
import 'package:monero_light_wallet/models/wallet_model.dart';
-import 'package:monero_light_wallet/util/height.dart';
class LwsKeysScreen extends StatefulWidget {
const LwsKeysScreen({super.key});
@@ -24,18 +23,11 @@ class _LwsKeysScreenState extends State<LwsKeysScreen> {
Future<void> _loadRestoreHeight() async {
final wallet = Provider.of<WalletModel>(context, listen: false);
- final restoreHeight = wallet.w2Wallet!.getRefreshFromBlockHeight();
+ final restoreHeight = await wallet.getRestoreHeight();
- if (restoreHeight > 0) {
- setState(() {
- _restoreHeight = _restoreHeight;
- });
- } else {
- final currentHeight = await getCurrentBlockchainHeight();
- setState(() {
- _restoreHeight = currentHeight;
- });
- }
+ setState(() {
+ _restoreHeight = restoreHeight;
+ });
}
@override
diff --git a/lib/services/shared_preferences_service.dart b/lib/services/shared_preferences_service.dart
index 890e9d9..0f89040 100644
--- a/lib/services/shared_preferences_service.dart
+++ b/lib/services/shared_preferences_service.dart
@@ -10,6 +10,8 @@ class SharedPreferencesKeys {
static const String connectionUseTor = 'connectionUseTor';
static const String connectionUseSsl = 'connectionUseSsl';
static const String showReceiveSubaddress = 'showReceiveSubaddress';
+ static const String walletRestoreHeight = 'walletRestoreHeight';
+ static const String txHistoryCount = 'txHistoryCount';
}
class SharedPreferencesService {
Why this scored 19/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.