- Improve code for backup cache (#2216)

* - Improve code for backup cache - Backup all Cached values without manually adding each one * Exclude some cache keys from backup [skip ci] * Exclude some cache keys from backup [skip ci]

Omar Hatem committed Apr 19, 2025 at 01:13 UTC e09d9aadfa58be8fc734800bbfec1cb64fb3b72b
1 file changed +37 -204
lib/core/backup_service.dart
+37 -204
@@ -1,6 +1,5 @@
1 import 'dart:convert';
2 import 'dart:io';
3 -import 'dart:typed_data';
3 import 'package:cake_wallet/core/secure_storage.dart';
4 import 'package:cake_wallet/entities/get_encryption_key.dart';
5 import 'package:cake_wallet/entities/transaction_description.dart';
@@ -164,6 +163,31 @@ class $BackupService {
163 }
164
165 final data = json.decode(preferencesFile.readAsStringSync()) as Map<String, dynamic>;
166 +
167 + try { // shouldn't throw an error but just in case, so it doesn't stop the backup restore
168 + for (var entry in data.entries) {
169 + String key = entry.key;
170 + dynamic value = entry.value;
171 +
172 + // Check the type of the value and save accordingly
173 + if (value is String) {
174 + await sharedPreferences.setString(key, value);
175 + } else if (value is int) {
176 + await sharedPreferences.setInt(key, value);
177 + } else if (value is double) {
178 + await sharedPreferences.setDouble(key, value);
179 + } else if (value is bool) {
180 + await sharedPreferences.setBool(key, value);
181 + } else if (value is List<String>) {
182 + await sharedPreferences.setStringList(key, value);
183 + } else {
184 + if (kDebugMode) {
185 + printV('Skipping individual save for key "$key": Unsupported type (${value.runtimeType}). Value: $value');
186 + }
187 + }
188 + }
189 + } catch (_) {}
190 +
191 String currentWalletName = data[PreferencesKey.currentWalletName] as String;
192 int currentWalletType = data[PreferencesKey.currentWalletType] as int;
193
@@ -175,151 +199,10 @@ class $BackupService {
199 currentWalletType = serializeToInt(correctWallets.first.type);
200 }
201
178 - final currentNodeId = data[PreferencesKey.currentNodeIdKey] as int?;
179 - final currentBalanceDisplayMode = data[PreferencesKey.currentBalanceDisplayModeKey] as int?;
180 - final currentFiatCurrency = data[PreferencesKey.currentFiatCurrencyKey] as String?;
181 - final shouldSaveRecipientAddress = data[PreferencesKey.shouldSaveRecipientAddressKey] as bool?;
182 - final isAppSecure = data[PreferencesKey.isAppSecureKey] as bool?;
183 - final disableTradeOption = data[PreferencesKey.disableTradeOption] as bool?;
184 - final currentTransactionPriorityKeyLegacy =
185 - data[PreferencesKey.currentTransactionPriorityKeyLegacy] as int?;
186 - final currentBitcoinElectrumSererId =
187 - data[PreferencesKey.currentBitcoinElectrumSererIdKey] as int?;
188 - final currentLanguageCode = data[PreferencesKey.currentLanguageCode] as String?;
189 - final displayActionListMode = data[PreferencesKey.displayActionListModeKey] as int?;
190 - final fiatApiMode = data[PreferencesKey.currentFiatApiModeKey] as int?;
191 - final currentTheme = data[PreferencesKey.currentTheme] as int?;
192 - final exchangeStatus = data[PreferencesKey.exchangeStatusKey] as int?;
193 - final currentDefaultSettingsMigrationVersion =
194 - data[PreferencesKey.currentDefaultSettingsMigrationVersion] as int?;
195 - final moneroTransactionPriority = data[PreferencesKey.moneroTransactionPriority] as int?;
196 - final bitcoinTransactionPriority = data[PreferencesKey.bitcoinTransactionPriority] as int?;
197 - final sortBalanceTokensBy = data[PreferencesKey.sortBalanceBy] as int?;
198 - final pinNativeTokenAtTop = data[PreferencesKey.pinNativeTokenAtTop] as bool?;
199 - final useEtherscan = data[PreferencesKey.useEtherscan] as bool?;
200 - final defaultNanoRep = data[PreferencesKey.defaultNanoRep] as String?;
201 - final defaultBananoRep = data[PreferencesKey.defaultBananoRep] as String?;
202 - final lookupsTwitter = data[PreferencesKey.lookupsTwitter] as bool?;
203 - final lookupsMastodon = data[PreferencesKey.lookupsMastodon] as bool?;
204 - final lookupsYatService = data[PreferencesKey.lookupsYatService] as bool?;
205 - final lookupsUnstoppableDomains = data[PreferencesKey.lookupsUnstoppableDomains] as bool?;
206 - final lookupsOpenAlias = data[PreferencesKey.lookupsOpenAlias] as bool?;
207 - final lookupsENS = data[PreferencesKey.lookupsENS] as bool?;
208 - final lookupsWellKnown = data[PreferencesKey.lookupsWellKnown] as bool?;
209 - final syncAll = data[PreferencesKey.syncAllKey] as bool?;
210 - final syncMode = data[PreferencesKey.syncModeKey] as int?;
211 - final autoGenerateSubaddressStatus =
212 - data[PreferencesKey.autoGenerateSubaddressStatusKey] as int?;
213 -
214 - await sharedPreferences.setString(PreferencesKey.currentWalletName, currentWalletName);
215 -
216 - if (currentNodeId != null)
217 - await sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, currentNodeId);
218 -
219 - if (currentBalanceDisplayMode != null)
220 - await sharedPreferences.setInt(
221 - PreferencesKey.currentBalanceDisplayModeKey, currentBalanceDisplayMode);
222 -
223 - await sharedPreferences.setInt(PreferencesKey.currentWalletType, currentWalletType);
224 -
225 - if (currentFiatCurrency != null)
226 - await sharedPreferences.setString(
227 - PreferencesKey.currentFiatCurrencyKey, currentFiatCurrency);
228 -
229 - if (shouldSaveRecipientAddress != null)
230 - await sharedPreferences.setBool(
231 - PreferencesKey.shouldSaveRecipientAddressKey, shouldSaveRecipientAddress);
232 -
233 - if (isAppSecure != null)
234 - await sharedPreferences.setBool(PreferencesKey.isAppSecureKey, isAppSecure);
235 -
236 - if (disableTradeOption != null)
237 - await sharedPreferences.setBool(PreferencesKey.disableTradeOption, disableTradeOption);
238 -
239 - if (currentTransactionPriorityKeyLegacy != null)
240 - await sharedPreferences.setInt(
241 - PreferencesKey.currentTransactionPriorityKeyLegacy, currentTransactionPriorityKeyLegacy);
242 -
243 - if (currentBitcoinElectrumSererId != null)
244 - await sharedPreferences.setInt(
245 - PreferencesKey.currentBitcoinElectrumSererIdKey, currentBitcoinElectrumSererId);
246 -
247 - if (currentLanguageCode != null)
248 - await sharedPreferences.setString(PreferencesKey.currentLanguageCode, currentLanguageCode);
249 -
250 - if (displayActionListMode != null)
251 - await sharedPreferences.setInt(
252 - PreferencesKey.displayActionListModeKey, displayActionListMode);
253 -
254 - if (fiatApiMode != null)
255 - await sharedPreferences.setInt(PreferencesKey.currentFiatApiModeKey, fiatApiMode);
256 - if (autoGenerateSubaddressStatus != null)
257 - await sharedPreferences.setInt(
258 - PreferencesKey.autoGenerateSubaddressStatusKey, autoGenerateSubaddressStatus);
259 -
260 - if (currentTheme != null && DeviceInfo.instance.isMobile) {
261 - await sharedPreferences.setInt(PreferencesKey.currentTheme, currentTheme);
262 - // enforce dark theme on desktop platforms until the design is ready:
263 - } else if (DeviceInfo.instance.isDesktop) {
202 + if (DeviceInfo.instance.isDesktop) {
203 await sharedPreferences.setInt(PreferencesKey.currentTheme, ThemeList.darkTheme.raw);
204 }
205
267 - if (exchangeStatus != null)
268 - await sharedPreferences.setInt(PreferencesKey.exchangeStatusKey, exchangeStatus);
269 -
270 - if (currentDefaultSettingsMigrationVersion != null)
271 - await sharedPreferences.setInt(PreferencesKey.currentDefaultSettingsMigrationVersion,
272 - currentDefaultSettingsMigrationVersion);
273 -
274 - if (moneroTransactionPriority != null)
275 - await sharedPreferences.setInt(
276 - PreferencesKey.moneroTransactionPriority, moneroTransactionPriority);
277 -
278 - if (bitcoinTransactionPriority != null)
279 - await sharedPreferences.setInt(
280 - PreferencesKey.bitcoinTransactionPriority, bitcoinTransactionPriority);
281 -
282 - if (sortBalanceTokensBy != null)
283 - await sharedPreferences.setInt(PreferencesKey.sortBalanceBy, sortBalanceTokensBy);
284 -
285 - if (pinNativeTokenAtTop != null)
286 - await sharedPreferences.setBool(PreferencesKey.pinNativeTokenAtTop, pinNativeTokenAtTop);
287 -
288 - if (useEtherscan != null)
289 - await sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan);
290 -
291 - if (defaultNanoRep != null)
292 - await sharedPreferences.setString(PreferencesKey.defaultNanoRep, defaultNanoRep);
293 -
294 - if (defaultBananoRep != null)
295 - await sharedPreferences.setString(PreferencesKey.defaultBananoRep, defaultBananoRep);
296 -
297 - if (syncAll != null) await sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll);
298 - if (lookupsTwitter != null)
299 - await sharedPreferences.setBool(PreferencesKey.lookupsTwitter, lookupsTwitter);
300 -
301 - if (lookupsMastodon != null)
302 - await sharedPreferences.setBool(PreferencesKey.lookupsMastodon, lookupsMastodon);
303 -
304 - if (lookupsYatService != null)
305 - await sharedPreferences.setBool(PreferencesKey.lookupsYatService, lookupsYatService);
306 -
307 - if (lookupsUnstoppableDomains != null)
308 - await sharedPreferences.setBool(
309 - PreferencesKey.lookupsUnstoppableDomains, lookupsUnstoppableDomains);
310 -
311 - if (lookupsOpenAlias != null)
312 - await sharedPreferences.setBool(PreferencesKey.lookupsOpenAlias, lookupsOpenAlias);
313 -
314 - if (lookupsENS != null) await sharedPreferences.setBool(PreferencesKey.lookupsENS, lookupsENS);
315 -
316 - if (lookupsWellKnown != null)
317 - await sharedPreferences.setBool(PreferencesKey.lookupsWellKnown, lookupsWellKnown);
318 -
319 - if (syncAll != null) await sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll);
320 -
321 - if (syncMode != null) await sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode);
322 -
206 await preferencesFile.delete();
207 }
208
@@ -378,11 +261,6 @@ class $BackupService {
261 await keyService.saveWalletPassword(walletName: name, password: password);
262 }
263
381 - @Deprecated('Use v2 instead')
382 - Future<Uint8List> _exportKeychainDumpV1(String password,
383 - {required String nonce, String keychainSalt = secrets.backupKeychainSalt}) async =>
384 - throw Exception('Deprecated');
385 -
264 Future<Uint8List> exportKeychainDumpV2(String password,
265 {String keychainSalt = secrets.backupKeychainSalt}) async {
266 final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
@@ -402,59 +280,18 @@ class $BackupService {
280 return encrypted;
281 }
282
283 + static const List<String> _excludedPrefsKeys = [
284 + PreferencesKey.currentPinLength,
285 + PreferencesKey.showCameraConsent,
286 + PreferencesKey.lastSeenAppVersion,
287 + PreferencesKey.failedTotpTokenTrials,
288 + ];
289 +
290 Future<String> exportPreferencesJSON() async {
406 - final preferences = <String, dynamic>{
407 - PreferencesKey.currentWalletName:
408 - sharedPreferences.getString(PreferencesKey.currentWalletName),
409 - PreferencesKey.currentNodeIdKey: sharedPreferences.getInt(PreferencesKey.currentNodeIdKey),
410 - PreferencesKey.currentBalanceDisplayModeKey:
411 - sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey),
412 - PreferencesKey.currentWalletType: sharedPreferences.getInt(PreferencesKey.currentWalletType),
413 - PreferencesKey.currentFiatCurrencyKey:
414 - sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey),
415 - PreferencesKey.shouldSaveRecipientAddressKey:
416 - sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey),
417 - PreferencesKey.disableTradeOption: sharedPreferences.getBool(PreferencesKey.disableTradeOption),
418 - PreferencesKey.currentTransactionPriorityKeyLegacy:
419 - sharedPreferences.getInt(PreferencesKey.currentTransactionPriorityKeyLegacy),
420 - PreferencesKey.currentBitcoinElectrumSererIdKey:
421 - sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey),
422 - PreferencesKey.currentLanguageCode:
423 - sharedPreferences.getString(PreferencesKey.currentLanguageCode),
424 - PreferencesKey.displayActionListModeKey:
425 - sharedPreferences.getInt(PreferencesKey.displayActionListModeKey),
426 - PreferencesKey.currentTheme: sharedPreferences.getInt(PreferencesKey.currentTheme),
427 - PreferencesKey.exchangeStatusKey: sharedPreferences.getInt(PreferencesKey.exchangeStatusKey),
428 - PreferencesKey.currentDefaultSettingsMigrationVersion:
429 - sharedPreferences.getInt(PreferencesKey.currentDefaultSettingsMigrationVersion),
430 - PreferencesKey.bitcoinTransactionPriority:
431 - sharedPreferences.getInt(PreferencesKey.bitcoinTransactionPriority),
432 - PreferencesKey.moneroTransactionPriority:
433 - sharedPreferences.getInt(PreferencesKey.moneroTransactionPriority),
434 - PreferencesKey.currentFiatApiModeKey:
435 - sharedPreferences.getInt(PreferencesKey.currentFiatApiModeKey),
436 - PreferencesKey.sortBalanceBy: sharedPreferences.getInt(PreferencesKey.sortBalanceBy),
437 - PreferencesKey.pinNativeTokenAtTop:
438 - sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop),
439 - PreferencesKey.useEtherscan: sharedPreferences.getBool(PreferencesKey.useEtherscan),
440 - PreferencesKey.defaultNanoRep: sharedPreferences.getString(PreferencesKey.defaultNanoRep),
441 - PreferencesKey.defaultBananoRep:
442 - sharedPreferences.getString(PreferencesKey.defaultBananoRep),
443 - PreferencesKey.lookupsTwitter: sharedPreferences.getBool(PreferencesKey.lookupsTwitter),
444 - PreferencesKey.lookupsMastodon: sharedPreferences.getBool(PreferencesKey.lookupsMastodon),
445 - PreferencesKey.lookupsYatService:
446 - sharedPreferences.getBool(PreferencesKey.lookupsYatService),
447 - PreferencesKey.lookupsUnstoppableDomains:
448 - sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains),
449 - PreferencesKey.lookupsOpenAlias: sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias),
450 - PreferencesKey.lookupsENS: sharedPreferences.getBool(PreferencesKey.lookupsENS),
451 - PreferencesKey.lookupsWellKnown:
452 - sharedPreferences.getBool(PreferencesKey.lookupsWellKnown),
453 - PreferencesKey.syncModeKey: sharedPreferences.getInt(PreferencesKey.syncModeKey),
454 - PreferencesKey.syncAllKey: sharedPreferences.getBool(PreferencesKey.syncAllKey),
455 - PreferencesKey.autoGenerateSubaddressStatusKey:
456 - sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey),
457 - };
291 + final preferences = <String, dynamic>{};
292 + sharedPreferences.getKeys().forEach((key) => preferences[key] = sharedPreferences.get(key));
293 +
294 + _excludedPrefsKeys.forEach((key) => preferences.remove(key));
295
296 return json.encode(preferences);
297 }
@@ -466,10 +303,6 @@ class $BackupService {
303 return Uint8List.fromList(bytes);
304 }
305
469 - @Deprecated('Use v2 instead')
470 - Future<Uint8List> _encryptV1(Uint8List data, String secretKeySource, String nonceBase64) async =>
471 - throw Exception('Deprecated');
472 -
306 Future<Uint8List> _decryptV1(Uint8List data, String secretKeySource, String nonceBase64,
307 {int macLength = 16}) async {
308 final secretKeyHash = await Cryptography.instance.sha256().hash(utf8.encode(secretKeySource));