Skip to content

Commit c90c9e9

Browse files
committed
fix: skip wallets with missing data during backup instead of aborting
eg. view-only wallets
1 parent df4b7f9 commit c90c9e9

1 file changed

Lines changed: 59 additions & 50 deletions

File tree

lib/pages/settings_views/global_settings_view/stack_backup_views/helpers/restore_create_backup.dart

Lines changed: 59 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -269,63 +269,72 @@ abstract class SWB {
269269

270270
final List<dynamic> backupWallets = [];
271271
for (final wallet in _wallets.wallets) {
272-
final Map<String, dynamic> backupWallet = {};
273-
backupWallet['name'] = wallet.info.name;
274-
backupWallet['id'] = wallet.walletId;
275-
backupWallet['isFavorite'] = wallet.info.isFavourite;
276-
backupWallet['otherDataJsonString'] = wallet.info.otherDataJsonString;
277-
278-
if (wallet is ViewOnlyOptionInterface && wallet.isViewOnly) {
279-
backupWallet['viewOnlyWalletDataKey'] =
280-
(await wallet.getViewOnlyWalletData()).toJsonEncodedString();
281-
} else if (wallet is MnemonicInterface) {
282-
backupWallet['mnemonic'] = await wallet.getMnemonic();
283-
backupWallet['mnemonicPassphrase'] = await wallet
284-
.getMnemonicPassphrase();
285-
} else if (wallet is PrivateKeyInterface) {
286-
backupWallet['privateKey'] = await wallet.getPrivateKey();
287-
} else if (wallet is BitcoinFrostWallet) {
288-
final String? keys = await wallet.getSerializedKeys();
289-
final String? config = await wallet.getMultisigConfig();
290-
if (keys == null || config == null) {
291-
final String err =
292-
"${wallet.info.coin.identifier} wallet ${wallet.info.name} "
293-
"has null keys or config";
294-
Logging.instance.e(err);
295-
throw Exception(err);
272+
try {
273+
final Map<String, dynamic> backupWallet = {};
274+
backupWallet['name'] = wallet.info.name;
275+
backupWallet['id'] = wallet.walletId;
276+
backupWallet['isFavorite'] = wallet.info.isFavourite;
277+
backupWallet['otherDataJsonString'] = wallet.info.otherDataJsonString;
278+
279+
if (wallet is ViewOnlyOptionInterface && wallet.isViewOnly) {
280+
backupWallet['viewOnlyWalletDataKey'] =
281+
(await wallet.getViewOnlyWalletData()).toJsonEncodedString();
282+
} else if (wallet is MnemonicInterface) {
283+
backupWallet['mnemonic'] = await wallet.getMnemonic();
284+
backupWallet['mnemonicPassphrase'] = await wallet
285+
.getMnemonicPassphrase();
286+
} else if (wallet is PrivateKeyInterface) {
287+
backupWallet['privateKey'] = await wallet.getPrivateKey();
288+
} else if (wallet is BitcoinFrostWallet) {
289+
final String? keys = await wallet.getSerializedKeys();
290+
final String? config = await wallet.getMultisigConfig();
291+
if (keys == null || config == null) {
292+
final String err =
293+
"${wallet.info.coin.identifier} wallet ${wallet.info.name} "
294+
"has null keys or config";
295+
Logging.instance.e(err);
296+
throw Exception(err);
297+
}
298+
//This case should never actually happen in practice unless the whole
299+
// wallet is somehow corrupt
300+
// TODO [prio=low]: solve case in which either keys or config is null.
301+
302+
// Format keys & config as a JSON string and set otherDataJsonString.
303+
final Map<String, dynamic> frostData = {};
304+
frostData["keys"] = keys;
305+
frostData["config"] = config;
306+
backupWallet['frostWalletData'] = jsonEncode(frostData);
296307
}
297-
//This case should never actually happen in practice unless the whole
298-
// wallet is somehow corrupt
299-
// TODO [prio=low]: solve case in which either keys or config is null.
300-
301-
// Format keys & config as a JSON string and set otherDataJsonString.
302-
final Map<String, dynamic> frostData = {};
303-
frostData["keys"] = keys;
304-
frostData["config"] = config;
305-
backupWallet['frostWalletData'] = jsonEncode(frostData);
306-
}
307-
backupWallet['coinName'] = wallet.info.coin.identifier;
308-
backupWallet['storedChainHeight'] = wallet.info.cachedChainHeight;
308+
backupWallet['coinName'] = wallet.info.coin.identifier;
309+
backupWallet['storedChainHeight'] = wallet.info.cachedChainHeight;
309310

310-
// backupWallet['txidList'] = DB.instance.get<dynamic>(
311-
// boxName: wallet.walletId, key: "cachedTxids") as List?;
312-
// the following can cause a deadlock
313-
// (await manager.transactionData).getAllTransactions().keys.toList();
311+
// backupWallet['txidList'] = DB.instance.get<dynamic>(
312+
// boxName: wallet.walletId, key: "cachedTxids") as List?;
313+
// the following can cause a deadlock
314+
// (await manager.transactionData).getAllTransactions().keys.toList();
314315

315-
backupWallet['restoreHeight'] = wallet.info.restoreHeight;
316+
backupWallet['restoreHeight'] = wallet.info.restoreHeight;
316317

317-
final isarNotes = await MainDB.instance.isar.transactionNotes
318-
.where()
319-
.walletIdEqualTo(wallet.walletId)
320-
.findAll();
318+
final isarNotes = await MainDB.instance.isar.transactionNotes
319+
.where()
320+
.walletIdEqualTo(wallet.walletId)
321+
.findAll();
321322

322-
final notes = isarNotes.asMap().map(
323-
(key, value) => MapEntry(value.txid, value.value),
324-
);
323+
final notes = isarNotes.asMap().map(
324+
(key, value) => MapEntry(value.txid, value.value),
325+
);
325326

326-
backupWallet['notes'] = notes;
327+
backupWallet['notes'] = notes;
327328

328-
backupWallets.add(backupWallet);
329+
backupWallets.add(backupWallet);
330+
} catch (e, s) {
331+
Logging.instance.w(
332+
"SWB skipping wallet ${wallet.info.name} "
333+
"(${wallet.info.coin.identifier})",
334+
error: e,
335+
stackTrace: s,
336+
);
337+
}
329338
}
330339
backupJson['wallets'] = backupWallets;
331340

0 commit comments

Comments
 (0)