fix: allow bakcups to be created even if one of the wallets is corrupted (#2221)
cyan committed
Apr 22, 2025 at 21:41 UTC
3e25be6dcf283219ceee852d056356ef2dde098a
2 files changed
+22
-6
lib/core/backup_service.dart
+14
-6
@@ -265,16 +265,24 @@ class $BackupService {
265
{String keychainSalt = secrets.backupKeychainSalt}) async {
266
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
267
final wallets = await Future.wait(walletInfoSource.values.map((walletInfo) async {
268
- return {
269
- 'name': walletInfo.name,
270
- 'type': walletInfo.type.toString(),
271
- 'password': await keyService.getWalletPassword(walletName: walletInfo.name)
272
- };
268
+ try {
269
+ return {
270
+ 'name': walletInfo.name,
271
+ 'type': walletInfo.type.toString(),
272
+ 'password': await keyService.getWalletPassword(walletName: walletInfo.name)
273
+ };
274
+ } catch (e) {
275
+ return {
276
+ 'name': walletInfo.name,
277
+ 'type': walletInfo.type.toString(),
278
+ 'password': ''
279
+ };
280
+ }
281
}));
282
final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
283
final backupPassword = await _secureStorage.read(key: backupPasswordKey);
284
final data = utf8.encode(
277
- json.encode({'wallets': wallets, backupPasswordKey: backupPassword}));
285
+ json.encode({'wallets': wallets, backupPasswordKey: backupPassword, '_all': await _secureStorage.readAll()}));
286
final encrypted = await _encryptV2(Uint8List.fromList(data), '$keychainSalt$password');
287
288
return encrypted;
tool/configure.dart
+8
@@ -1629,6 +1629,7 @@ abstract class SecureStorage {
1629
Future<void> delete({required String key});
1630
// Legacy
1631
Future<String?> readNoIOptions({required String key});
1632
+ Future<Map<String, String>> readAll();
1633
}""";
1634
const defaultSecureStorage = """
1635
class DefaultSecureStorage extends SecureStorage {
@@ -1667,6 +1668,11 @@ class DefaultSecureStorage extends SecureStorage {
1668
iOptions: useNoIOptions ? IOSOptions() : null,
1669
);
1670
}
1671
+
1672
+ @override
1673
+ Future<Map<String, String>> readAll() async {
1674
+ return await _secureStorage.readAll();
1675
+ }
1676
}""";
1677
const fakeSecureStorage = """
1678
class FakeSecureStorage extends SecureStorage {
@@ -1678,6 +1684,8 @@ class FakeSecureStorage extends SecureStorage {
1684
Future<void> delete({required String key}) async {}
1685
@override
1686
Future<String?> readNoIOptions({required String key}) async => null;
1687
+ @override
1688
+ Future<Map<String, String>> readAll() async => {};
1689
}""";
1690
final outputFile = File(secureStoragePath);
1691
final header = hasFlutterSecureStorage