diff --git a/cw_bitcoin/lib/electrum_transaction_history.dart b/cw_bitcoin/lib/electrum_transaction_history.dart index be039fa36..d478c3b12 100644 --- a/cw_bitcoin/lib/electrum_transaction_history.dart +++ b/cw_bitcoin/lib/electrum_transaction_history.dart @@ -1,10 +1,11 @@ import 'dart:convert'; + +import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:mobx/mobx.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_bitcoin/file.dart'; -import 'package:cw_bitcoin/electrum_transaction_info.dart'; part 'electrum_transaction_history.g.dart'; diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart index 903fa14cc..85053133f 100644 --- a/cw_bitcoin/lib/electrum_wallet.dart +++ b/cw_bitcoin/lib/electrum_wallet.dart @@ -18,7 +18,6 @@ import 'package:cw_bitcoin/electrum_balance.dart'; import 'package:cw_bitcoin/electrum_transaction_history.dart'; import 'package:cw_bitcoin/electrum_transaction_info.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; -import 'package:cw_bitcoin/file.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/utils.dart'; @@ -30,6 +29,7 @@ import 'package:cw_core/sync_status.dart'; import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_priority.dart'; import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:flutter/foundation.dart'; diff --git a/cw_bitcoin/lib/electrum_wallet_snapshot.dart b/cw_bitcoin/lib/electrum_wallet_snapshot.dart index def991ebe..86d3e2fed 100644 --- a/cw_bitcoin/lib/electrum_wallet_snapshot.dart +++ b/cw_bitcoin/lib/electrum_wallet_snapshot.dart @@ -1,8 +1,8 @@ import 'dart:convert'; import 'package:cw_bitcoin/bitcoin_address_record.dart'; import 'package:cw_bitcoin/electrum_balance.dart'; -import 'package:cw_bitcoin/file.dart'; import 'package:cw_core/pathForWallet.dart'; +import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_type.dart'; class ElectrumWallletSnapshot { @@ -56,4 +56,4 @@ class ElectrumWallletSnapshot { regularAddressIndex: regularAddressIndex, changeAddressIndex: changeAddressIndex); } -} \ No newline at end of file +} diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml index 693d5af7a..e90f9cda4 100644 --- a/cw_bitcoin/pubspec.yaml +++ b/cw_bitcoin/pubspec.yaml @@ -30,7 +30,6 @@ dependencies: rxdart: ^0.27.5 unorm_dart: ^0.2.0 cryptography: ^2.0.5 - encrypt: ^5.0.1 dev_dependencies: flutter_test: diff --git a/cw_core/lib/get_height_by_date.dart b/cw_core/lib/get_height_by_date.dart index a680e6c25..6f3ccaf68 100644 --- a/cw_core/lib/get_height_by_date.dart +++ b/cw_core/lib/get_height_by_date.dart @@ -118,7 +118,10 @@ final dates = { "2023-6": 2898234, "2023-7": 2919771, "2023-8": 2942045, - "2023-9": 2964280 + "2023-9": 2964280, + "2023-10": 2985937, + "2023-11": 3008178, + "2023-12": 3029759 }; int getMoneroHeigthByDate({required DateTime date}) { diff --git a/cw_bitcoin/lib/file.dart b/cw_core/lib/utils/file.dart similarity index 66% rename from cw_bitcoin/lib/file.dart rename to cw_core/lib/utils/file.dart index 8fd236ec3..0b1c5cffd 100644 --- a/cw_bitcoin/lib/file.dart +++ b/cw_core/lib/utils/file.dart @@ -2,17 +2,8 @@ import 'dart:io'; import 'package:cw_core/key.dart'; import 'package:encrypt/encrypt.dart' as encrypt; -Future write( - {required String path, - required String password, - required String data}) async { - final keys = extractKeys(password); - final key = encrypt.Key.fromBase64(keys.first); - final iv = encrypt.IV.fromBase64(keys.last); - final encrypted = await encode(key: key, iv: iv, data: data); - final f = File(path); - f.writeAsStringSync(encrypted); -} +Future write({required String path, required String password, required String data}) async => + writeData(path: path, password: password, data: data); Future writeData( {required String path, diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index 7ad873647..6162375b2 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -385,6 +385,9 @@ extern "C" (uint64_t)restoreHeight, std::string(spendKey)); + // Cache Raw to support Polyseed + wallet->setCacheAttribute("cakewallet.seed", std::string(seed)); + int status; std::string errorString; @@ -396,9 +399,6 @@ extern "C" return false; } - // Cache Raw to support Polyseed - wallet->setCacheAttribute("cakewallet.seed", std::string(seed)); - change_current_wallet(wallet); return true; } diff --git a/cw_monero/lib/monero_wallet.dart b/cw_monero/lib/monero_wallet.dart index 71c7e3967..924a987cd 100644 --- a/cw_monero/lib/monero_wallet.dart +++ b/cw_monero/lib/monero_wallet.dart @@ -97,7 +97,8 @@ abstract class MoneroWalletBase ObservableMap balance; @override - String get seed => monero_wallet.getSeed(); + String get seed => _seed; + String _seed = monero_wallet.getSeed(); @override MoneroWalletKeys get keys => MoneroWalletKeys( @@ -113,7 +114,11 @@ abstract class MoneroWalletBase Timer? _autoSaveTimer; List unspentCoins; - Future init() async { + Future init({String seedFallback = ""}) async { + if (_seed.isEmpty) { + _seed = seedFallback; + } + await walletAddresses.init(); balance = ObservableMap.of({ currency: MoneroBalance( diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 077ab4e54..c71d43e83 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:cw_core/monero_wallet_utils.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/unspent_coins_info.dart'; +import 'package:cw_core/utils/file.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; @@ -77,8 +78,12 @@ class MoneroWalletService extends WalletService< final polyseed = Polyseed.create(); final lang = PolyseedLang.getByEnglishName(credentials.language); + final heightOverride = + getMoneroHeigthByDate(date: DateTime.now().subtract(Duration(days: 2))); + return _restoreFromPolyseed( - path, credentials.password!, polyseed, credentials.walletInfo!, lang); + path, credentials.password!, polyseed, credentials.walletInfo!, lang, + overrideHeight: heightOverride); } await monero_wallet_manager.createWallet( @@ -129,7 +134,12 @@ class MoneroWalletService extends WalletService< return openWallet(name, password); } - await wallet.init(); + if (wallet.seed.isEmpty) { + final seedFallback = await _getSeedBackup(path, password); + await wallet.init(seedFallback: seedFallback); + } else { + await wallet.init(); + } return wallet; } catch (e) { @@ -268,10 +278,11 @@ class MoneroWalletService extends WalletService< Future _restoreFromPolyseed(String path, String password, Polyseed polyseed, WalletInfo walletInfo, PolyseedLang lang, - {PolyseedCoin coin = PolyseedCoin.POLYSEED_MONERO}) async { - final height = getMoneroHeigthByDate( + {PolyseedCoin coin = PolyseedCoin.POLYSEED_MONERO, int? overrideHeight}) async { + final height = overrideHeight ?? getMoneroHeigthByDate( date: DateTime.fromMillisecondsSinceEpoch(polyseed.birthday * 1000)); final spendKey = keyToHexString(polyseed.generateKey(coin, 32)); + final seed = polyseed.encode(lang, coin); walletInfo.isRecovery = true; walletInfo.restoreHeight = height; @@ -279,10 +290,13 @@ class MoneroWalletService extends WalletService< await monero_wallet_manager.restoreFromSpendKey( path: path, password: password, - seed: polyseed.encode(lang, coin), + seed: seed, language: lang.nameEnglish, restoreHeight: height, spendKey: spendKey); + + await writeData(path: "$path.seed", password: password, data: seed); + final wallet = MoneroWallet( walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource); await wallet.init(); @@ -290,6 +304,13 @@ class MoneroWalletService extends WalletService< return wallet; } + Future _getSeedBackup(String path, String password) async { + final seedFilePath = "$path.seed"; + final seedFile = File(seedFilePath); + if (!seedFile.existsSync()) return ""; + return read(path: seedFilePath, password: password); + } + Future repairOldAndroidWallet(String name) async { try { if (!Platform.isAndroid) { diff --git a/cw_monero/macos/Classes/monero_api.cpp b/cw_monero/macos/Classes/monero_api.cpp index a5ca13822..6fabc29fd 100644 --- a/cw_monero/macos/Classes/monero_api.cpp +++ b/cw_monero/macos/Classes/monero_api.cpp @@ -385,6 +385,9 @@ extern "C" (uint64_t)restoreHeight, std::string(spendKey)); + // Cache Raw to support Polyseed + wallet->setCacheAttribute("cakewallet.seed", std::string(seed)); + int status; std::string errorString; @@ -396,9 +399,6 @@ extern "C" return false; } - // Cache Raw to support Polyseed - wallet->setCacheAttribute("cakewallet.seed", std::string(seed)); - change_current_wallet(wallet); return true; }