From 26fe28891debf378dbacfb6417f40dbfdccf2716 Mon Sep 17 00:00:00 2001 From: Matthew Fosse Date: Wed, 7 Feb 2024 07:44:29 -0800 Subject: [PATCH] Cw 528 backup wallet files (#1281) * monero wallet backup changes * [skipci] updates * monero fixes * start work for bitcoin/eth * cleanup * [skipci] more cleanup * add all other coins * merge fixes * add corrupted test * build for testing * actually be able to test monero * review fixes * more review fixes --- cw_bitcoin/lib/bitcoin_wallet_service.dart | 54 +++++++------ cw_bitcoin/lib/electrum_wallet.dart | 3 - cw_bitcoin/lib/litecoin_wallet_service.dart | 22 ++++-- .../lib/src/bitcoin_cash_wallet_service.dart | 22 ++++-- cw_core/lib/monero_wallet_utils.dart | 19 ++++- cw_core/lib/wallet_service.dart | 23 +++++- cw_ethereum/lib/ethereum_wallet_service.dart | 32 ++++++-- cw_haven/lib/haven_wallet_service.dart | 1 + cw_monero/lib/monero_wallet.dart | 64 ++++++++++++--- cw_monero/lib/monero_wallet_service.dart | 77 +++++++++---------- cw_nano/lib/nano_wallet_service.dart | 32 ++++++-- cw_polygon/lib/polygon_wallet_service.dart | 32 ++++++-- 12 files changed, 264 insertions(+), 117 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 3a97e0682..736ec1044 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -12,10 +12,8 @@ import 'package:cw_core/wallet_type.dart'; import 'package:hive/hive.dart'; import 'package:collection/collection.dart'; -class BitcoinWalletService extends WalletService< - BitcoinNewWalletCredentials, - BitcoinRestoreWalletFromSeedCredentials, - BitcoinRestoreWalletFromWIFCredentials> { +class BitcoinWalletService extends WalletService { BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -42,28 +40,41 @@ class BitcoinWalletService extends WalletService< @override Future openWallet(String name, String password) async { - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(name, getType()))!; - final wallet = await BitcoinWalletBase.open( - password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); - await wallet.init(); - return wallet; + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!; + try { + final wallet = await BitcoinWalletBase.open( + password: password, + name: name, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + saveBackup(name); + return wallet; + } catch (_) { + await restoreWalletFilesFromBackup(name); + final wallet = await BitcoinWalletBase.open( + password: password, + name: name, + walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + return wallet; + } } @override Future remove(String wallet) async { - File(await pathForWalletDir(name: wallet, type: getType())) - .delete(recursive: true); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(wallet, getType()))!; + File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true); + final walletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!; await walletInfoSource.delete(walletInfo.key); } @override Future rename(String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(currentName, getType()))!; + final currentWalletInfo = walletInfoSource.values + .firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!; final currentWallet = await BitcoinWalletBase.open( password: password, name: currentName, @@ -71,6 +82,7 @@ class BitcoinWalletService extends WalletService< unspentCoinsInfo: unspentCoinsInfoSource); await currentWallet.renameWalletFiles(newName); + await saveBackup(newName); final newWalletInfo = currentWalletInfo; newWalletInfo.id = WalletBase.idFor(newName, getType()); @@ -80,13 +92,11 @@ class BitcoinWalletService extends WalletService< } @override - Future restoreFromKeys( - BitcoinRestoreWalletFromWIFCredentials credentials) async => + Future restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials) async => throw UnimplementedError(); @override - Future restoreFromSeed( - BitcoinRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials) async { if (!validateMnemonic(credentials.mnemonic)) { throw BitcoinMnemonicIsIncorrectException(); } @@ -100,4 +110,4 @@ class BitcoinWalletService extends WalletService< await wallet.init(); return wallet; } -} \ No newline at end of file +} diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 6be525a1f..8a41c1733 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -601,8 +601,6 @@ abstract class ElectrumWalletBase electrumClient.getHistory(scriptHash).then((history) => {scriptHash: history})); final historyResults = await Future.wait(histories); - - historyResults.forEach((history) { history.entries.forEach((historyItem) { if (historyItem.value.isNotEmpty) { @@ -622,7 +620,6 @@ abstract class ElectrumWalletBase } } - addressHashes.forEach((sh, addressRecord) { addressRecord.txCount = newTxCounts[sh] ?? 0; }); diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index b13ac7a7f..69d1dfc7e 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -45,11 +45,22 @@ class LitecoinWalletService extends WalletService< Future openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhereOrNull( (info) => info.id == WalletBase.idFor(name, getType()))!; - final wallet = await LitecoinWalletBase.open( - password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); - await wallet.init(); - return wallet; + + try { + final wallet = await LitecoinWalletBase.open( + password: password, name: name, walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + saveBackup(name); + return wallet; + } catch (_) { + await restoreWalletFilesFromBackup(name); + final wallet = await LitecoinWalletBase.open( + password: password, name: name, walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + return wallet; + } } @override @@ -72,6 +83,7 @@ class LitecoinWalletService extends WalletService< unspentCoinsInfo: unspentCoinsInfoSource); await currentWallet.renameWalletFiles(newName); + await saveBackup(newName); final newWalletInfo = currentWalletInfo; newWalletInfo.id = WalletBase.idFor(newName, getType()); diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart index 8cc469a3a..f66e38ca7 100644 --- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart +++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart @@ -51,11 +51,22 @@ class BitcoinCashWalletService extends WalletService openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhereOrNull( (info) => info.id == WalletBase.idFor(name, getType()))!; - final wallet = await BitcoinCashWalletBase.open( - password: password, name: name, walletInfo: walletInfo, - unspentCoinsInfo: unspentCoinsInfoSource); - await wallet.init(); - return wallet; + + try { + final wallet = await BitcoinCashWalletBase.open( + password: password, name: name, walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + saveBackup(name); + return wallet; + } catch(_) { + await restoreWalletFilesFromBackup(name); + final wallet = await BitcoinCashWalletBase.open( + password: password, name: name, walletInfo: walletInfo, + unspentCoinsInfo: unspentCoinsInfoSource); + await wallet.init(); + return wallet; + } } @override @@ -78,6 +89,7 @@ class BitcoinCashWalletService extends WalletService restoreWalletFiles(String name) async { } } +Future resetCache(String name) async { + await removeCache(name); + + final walletDirPath = await pathForWalletDir(name: name, type: WalletType.monero); + final cacheFilePath = '$walletDirPath/$name'; + final backupCacheFile = File(backupFileName(cacheFilePath)); + if (backupCacheFile.existsSync()) { + await backupCacheFile.copy(cacheFilePath); + } +} + Future backupWalletFilesExists(String name) async { final walletDirPath = await pathForWalletDir(name: name, type: WalletType.monero); final cacheFilePath = '$walletDirPath/$name'; @@ -63,9 +74,9 @@ Future backupWalletFilesExists(String name) async { final backupKeysFile = File(backupFileName(keysFilePath)); final backupAddressListFile = File(backupFileName(addressListFilePath)); - return backupCacheFile.existsSync() - && backupKeysFile.existsSync() - && backupAddressListFile.existsSync(); + return backupCacheFile.existsSync() && + backupKeysFile.existsSync() && + backupAddressListFile.existsSync(); } Future removeCache(String name) async { @@ -85,4 +96,4 @@ Future restoreOrResetWalletFiles(String name) async { } removeCache(name); -} \ No newline at end of file +} diff --git a/cw_core/lib/wallet_service.dart b/cw_core/lib/wallet_service.dart index f6d0ca192..3b4908386 100644 --- a/cw_core/lib/wallet_service.dart +++ b/cw_core/lib/wallet_service.dart @@ -1,7 +1,8 @@ -import 'package:cw_core/node.dart'; +import 'dart:io'; + +import 'package:cw_core/pathForWallet.dart'; 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'; abstract class WalletService remove(String wallet); Future rename(String currentName, String password, String newName); + + Future restoreWalletFilesFromBackup(String name) async { + final backupWalletDirPath = await pathForWalletDir(name: "$name.backup", type: getType()); + final walletDirPath = await pathForWalletDir(name: name, type: getType()); + + if (File(backupWalletDirPath).existsSync()) { + await File(backupWalletDirPath).copy(walletDirPath); + } + } + + Future saveBackup(String name) async { + final backupWalletDirPath = await pathForWalletDir(name: "$name.backup", type: getType()); + final walletDirPath = await pathForWalletDir(name: name, type: getType()); + + if (File(walletDirPath).existsSync()) { + await File(walletDirPath).copy(backupWalletDirPath); + } + } } diff --git a/cw_ethereum/lib/ethereum_wallet_service.dart b/cw_ethereum/lib/ethereum_wallet_service.dart index 1cd776867..5e8c22718 100644 --- a/cw_ethereum/lib/ethereum_wallet_service.dart +++ b/cw_ethereum/lib/ethereum_wallet_service.dart @@ -39,16 +39,31 @@ class EthereumWalletService extends EVMChainWalletService { Future openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); - final wallet = await EthereumWallet.open( - name: name, - password: password, - walletInfo: walletInfo, - ); - await wallet.init(); - await wallet.save(); + try { + final wallet = await EthereumWallet.open( + name: name, + password: password, + walletInfo: walletInfo, + ); - return wallet; + await wallet.init(); + await wallet.save(); + saveBackup(name); + return wallet; + } catch (_) { + + await restoreWalletFilesFromBackup(name); + + final wallet = await EthereumWallet.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + await wallet.init(); + await wallet.save(); + return wallet; + } } @override @@ -59,6 +74,7 @@ class EthereumWalletService extends EVMChainWalletService { password: password, name: currentName, walletInfo: currentWalletInfo); await currentWallet.renameWalletFiles(newName); + await saveBackup(newName); final newWalletInfo = currentWalletInfo; newWalletInfo.id = WalletBase.idFor(newName, getType()); diff --git a/cw_haven/lib/haven_wallet_service.dart b/cw_haven/lib/haven_wallet_service.dart index 0bc20d2a0..dd7713e08 100644 --- a/cw_haven/lib/haven_wallet_service.dart +++ b/cw_haven/lib/haven_wallet_service.dart @@ -163,6 +163,7 @@ class HavenWalletService extends WalletService< final currentWallet = HavenWallet(walletInfo: currentWalletInfo); await currentWallet.renameWalletFiles(newName); + await saveBackup(newName); final newWalletInfo = currentWalletInfo; newWalletInfo.id = WalletBase.idFor(newName, getType()); diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 4b71fb5ff..1a34e4bd6 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -36,6 +36,8 @@ import 'package:mobx/mobx.dart'; part 'monero_wallet.g.dart'; const moneroBlockSize = 1000; +// not sure if this should just be 0 but setting it higher feels safer / should catch more cases: +const MIN_RESTORE_HEIGHT = 1000; class MoneroWallet = MoneroWalletBase with _$MoneroWallet; @@ -79,7 +81,7 @@ abstract class MoneroWalletBase Box unspentCoinsInfo; - void Function(FlutterErrorDetails)? _onError; + void Function(FlutterErrorDetails)? onError; @override late MoneroWalletAddresses walletAddresses; @@ -171,7 +173,26 @@ abstract class MoneroWalletBase Future startSync() async { try { _setInitialHeight(); - } catch (_) {} + } catch (_) { + // our restore height wasn't correct, so lets see if using the backup works: + try { + await resetCache(name); + _setInitialHeight(); + } catch (e) { + // we still couldn't get a valid height from the backup?!: + // try to use the date instead: + try { + _setHeightFromDate(); + } catch (e, s) { + // we still couldn't get a valid sync height :/ + onError?.call(FlutterErrorDetails( + exception: e, + stack: s, + library: this.runtimeType.toString(), + )); + } + } + } try { syncStatus = AttemptingSyncStatus(); @@ -339,6 +360,8 @@ abstract class MoneroWalletBase if (currentAddressListFile.existsSync()) { await currentAddressListFile.rename('$newWalletPath.address.txt'); } + + await backupWalletFiles(newWalletName); } catch (e) { final currentWalletPath = await pathForWallet(name: name, type: type); @@ -402,9 +425,7 @@ abstract class MoneroWalletBase if (coin.spent == 0) { final unspent = MoneroUnspent.fromCoinsInfoRow(coin); if (unspent.hash.isNotEmpty) { - unspent.isChange = transaction_history - .getTransaction(unspent.hash) - .direction == 1; + unspent.isChange = transaction_history.getTransaction(unspent.hash).direction == 1; } unspentCoins.add(unspent); } @@ -418,7 +439,7 @@ abstract class MoneroWalletBase if (unspentCoins.isNotEmpty) { unspentCoins.forEach((coin) { final coinInfoList = unspentCoinsInfo.values.where((element) => - element.walletId.contains(id) && + element.walletId.contains(id) && element.accountIndex == walletAddresses.account!.id && element.keyImage!.contains(coin.keyImage!)); @@ -438,7 +459,7 @@ abstract class MoneroWalletBase _askForUpdateBalance(); } catch (e, s) { print(e.toString()); - _onError?.call(FlutterErrorDetails( + onError?.call(FlutterErrorDetails( exception: e, stack: s, library: this.runtimeType.toString(), @@ -534,18 +555,36 @@ abstract class MoneroWalletBase _listener = monero_wallet.setListeners(_onNewBlock, _onNewTransaction); } + // check if the height is correct: void _setInitialHeight() { if (walletInfo.isRecovery) { return; } - final currentHeight = monero_wallet.getCurrentHeight(); + final height = monero_wallet.getCurrentHeight(); - if (currentHeight <= 1) { - final height = _getHeightByDate(walletInfo.date); + if (height > MIN_RESTORE_HEIGHT) { + // the restore height is probably correct, so we do nothing: + return; + } + + throw Exception("height isn't > $MIN_RESTORE_HEIGHT!"); + } + + void _setHeightFromDate() { + if (walletInfo.isRecovery) { + return; + } + + final height = _getHeightByDate(walletInfo.date); + + if (height > MIN_RESTORE_HEIGHT) { monero_wallet.setRecoveringFromSeed(isRecovery: true); monero_wallet.setRefreshFromBlockHeight(height: height); + return; } + + throw Exception("height isn't > $MIN_RESTORE_HEIGHT!"); } int _getHeightDistance(DateTime date) { @@ -561,7 +600,8 @@ abstract class MoneroWalletBase final heightDistance = _getHeightDistance(date); if (nodeHeight <= 0) { - return 0; + // the node returned 0 (an error state), so lets just restore from cache: + throw Exception("nodeHeight is <= 0!"); } return nodeHeight - heightDistance; @@ -650,7 +690,7 @@ abstract class MoneroWalletBase } @override - void setExceptionHandler(void Function(FlutterErrorDetails) onError) => _onError = onError; + void setExceptionHandler(void Function(FlutterErrorDetails) e) => onError = e; @override String signMessage(String message, {String? address}) { diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 9b9e254d0..3dea7fc0e 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -11,11 +11,13 @@ import 'package:cw_core/get_height_by_date.dart'; import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart'; import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager; import 'package:cw_monero/monero_wallet.dart'; +import 'package:flutter/widgets.dart'; import 'package:hive/hive.dart'; import 'package:polyseed/polyseed.dart'; class MoneroNewWalletCredentials extends WalletCredentials { - MoneroNewWalletCredentials({required String name, required this.language, required this.isPolyseed, String? password}) + MoneroNewWalletCredentials( + {required String name, required this.language, required this.isPolyseed, String? password}) : super(name: name, password: password); final String language; @@ -52,10 +54,8 @@ class MoneroRestoreWalletFromKeysCredentials extends WalletCredentials { final String spendKey; } -class MoneroWalletService extends WalletService< - MoneroNewWalletCredentials, - MoneroRestoreWalletFromSeedCredentials, - MoneroRestoreWalletFromKeysCredentials> { +class MoneroWalletService extends WalletService { MoneroWalletService(this.walletInfoSource, this.unspentCoinsInfoSource); final Box walletInfoSource; @@ -112,6 +112,7 @@ class MoneroWalletService extends WalletService< @override Future openWallet(String name, String password) async { + MoneroWallet? wallet; try { final path = await pathForWallet(name: name, type: getType()); @@ -119,11 +120,10 @@ class MoneroWalletService extends WalletService< await repairOldAndroidWallet(name); } - await monero_wallet_manager - .openWalletAsync({'path': path, 'password': password}); - final walletInfo = walletInfoSource.values.firstWhere( - (info) => info.id == WalletBase.idFor(name, getType())); - final wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); + await monero_wallet_manager.openWalletAsync({'path': path, 'password': password}); + final walletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(name, getType())); + wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); final isValid = wallet.walletAddresses.validate(); if (!isValid) { @@ -135,7 +135,7 @@ class MoneroWalletService extends WalletService< await wallet.init(); return wallet; - } catch (e) { + } catch (e, s) { // TODO: Implement Exception for wallet list service. final bool isBadAlloc = e.toString().contains('bad_alloc') || @@ -156,16 +156,18 @@ class MoneroWalletService extends WalletService< final bool invalidSignature = e.toString().contains('invalid signature') || (e is WalletOpeningException && e.message.contains('invalid signature')); - if (isBadAlloc || - doesNotCorrespond || - isMissingCacheFilesIOS || - isMissingCacheFilesAndroid || - invalidSignature) { - await restoreOrResetWalletFiles(name); - return openWallet(name, password); + if (!isBadAlloc && + !doesNotCorrespond && + !isMissingCacheFilesIOS && + !isMissingCacheFilesAndroid && + !invalidSignature && + wallet != null && + wallet.onError != null) { + wallet.onError!(FlutterErrorDetails(exception: e, stack: s)); } - rethrow; + await restoreOrResetWalletFiles(name); + return openWallet(name, password); } } @@ -185,10 +187,9 @@ class MoneroWalletService extends WalletService< } @override - Future rename( - String currentName, String password, String newName) async { - final currentWalletInfo = walletInfoSource.values.firstWhere( - (info) => info.id == WalletBase.idFor(currentName, getType())); + Future rename(String currentName, String password, String newName) async { + final currentWalletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(currentName, getType())); final currentWallet = MoneroWallet(walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource); @@ -202,8 +203,7 @@ class MoneroWalletService extends WalletService< } @override - Future restoreFromKeys( - MoneroRestoreWalletFromKeysCredentials credentials) async { + Future restoreFromKeys(MoneroRestoreWalletFromKeysCredentials credentials) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await monero_wallet_manager.restoreFromKeys( @@ -227,9 +227,7 @@ class MoneroWalletService extends WalletService< } @override - Future restoreFromSeed( - MoneroRestoreWalletFromSeedCredentials credentials) async { - + Future restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials) async { // Restore from Polyseed if (Polyseed.isValidSeed(credentials.mnemonic)) { return restoreFromPolyseed(credentials); @@ -254,14 +252,16 @@ class MoneroWalletService extends WalletService< } } - Future restoreFromPolyseed(MoneroRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromPolyseed( + MoneroRestoreWalletFromSeedCredentials credentials) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); final polyseedCoin = PolyseedCoin.POLYSEED_MONERO; final lang = PolyseedLang.getByPhrase(credentials.mnemonic); final polyseed = Polyseed.decode(credentials.mnemonic, lang, polyseedCoin); - return _restoreFromPolyseed(path, credentials.password!, polyseed, credentials.walletInfo!, lang); + return _restoreFromPolyseed( + path, credentials.password!, polyseed, credentials.walletInfo!, lang); } catch (e) { // TODO: Implement Exception for wallet list service. print('MoneroWalletsManager Error: $e'); @@ -269,11 +269,11 @@ class MoneroWalletService extends WalletService< } } - Future _restoreFromPolyseed(String path, String password, Polyseed polyseed, - WalletInfo walletInfo, PolyseedLang lang, + Future _restoreFromPolyseed( + String path, String password, Polyseed polyseed, WalletInfo walletInfo, PolyseedLang lang, {PolyseedCoin coin = PolyseedCoin.POLYSEED_MONERO, int? overrideHeight}) async { - final height = overrideHeight ?? getMoneroHeigthByDate( - date: DateTime.fromMillisecondsSinceEpoch(polyseed.birthday * 1000)); + final height = overrideHeight ?? + getMoneroHeigthByDate(date: DateTime.fromMillisecondsSinceEpoch(polyseed.birthday * 1000)); final spendKey = polyseed.generateKey(coin, 32).toHexString(); final seed = polyseed.encode(lang, coin); @@ -288,8 +288,7 @@ class MoneroWalletService extends WalletService< restoreHeight: height, spendKey: spendKey); - final wallet = MoneroWallet( - walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); + final wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); return wallet; @@ -301,16 +300,14 @@ class MoneroWalletService extends WalletService< return; } - final oldAndroidWalletDirPath = - await outdatedAndroidPathForWalletDir(name: name); + final oldAndroidWalletDirPath = await outdatedAndroidPathForWalletDir(name: name); final dir = Directory(oldAndroidWalletDirPath); if (!dir.existsSync()) { return; } - final newWalletDirPath = - await pathForWalletDir(name: name, type: getType()); + final newWalletDirPath = await pathForWalletDir(name: name, type: getType()); dir.listSync().forEach((f) { final file = File(f.path); diff --git a/cw_nano/lib/nano_wallet_service.dart b/cw_nano/lib/nano_wallet_service.dart index 7a66f8c9f..a76f0393d 100644 --- a/cw_nano/lib/nano_wallet_service.dart +++ b/cw_nano/lib/nano_wallet_service.dart @@ -69,6 +69,7 @@ class NanoWalletService extends WalletService openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); - final wallet = await NanoWalletBase.open( - name: name, - password: password, - walletInfo: walletInfo, - ); - await wallet.init(); - await wallet.save(); - return wallet; + try { + final wallet = await NanoWalletBase.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + + await wallet.init(); + await wallet.save(); + saveBackup(name); + return wallet; + } catch (_) { + await restoreWalletFilesFromBackup(name); + final wallet = await NanoWalletBase.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + + await wallet.init(); + await wallet.save(); + return wallet; + } } } diff --git a/cw_polygon/lib/polygon_wallet_service.dart b/cw_polygon/lib/polygon_wallet_service.dart index 451dc7288..0199a1552 100644 --- a/cw_polygon/lib/polygon_wallet_service.dart +++ b/cw_polygon/lib/polygon_wallet_service.dart @@ -42,16 +42,31 @@ class PolygonWalletService extends EVMChainWalletService { Future openWallet(String name, String password) async { final walletInfo = walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType())); - final wallet = await PolygonWallet.open( - name: name, - password: password, - walletInfo: walletInfo, - ); - await wallet.init(); - await wallet.save(); + try { + final wallet = await PolygonWallet.open( + name: name, + password: password, + walletInfo: walletInfo, + ); - return wallet; + await wallet.init(); + await wallet.save(); + saveBackup(name); + return wallet; + } catch (_) { + await restoreWalletFilesFromBackup(name); + + final wallet = await PolygonWallet.open( + name: name, + password: password, + walletInfo: walletInfo, + ); + + await wallet.init(); + await wallet.save(); + return wallet; + } } @override @@ -100,6 +115,7 @@ class PolygonWalletService extends EVMChainWalletService { password: password, name: currentName, walletInfo: currentWalletInfo); await currentWallet.renameWalletFiles(newName); + await saveBackup(newName); final newWalletInfo = currentWalletInfo; newWalletInfo.id = WalletBase.idFor(newName, getType());