From b7d9bf8746d62dd991e0c5cdfdc6cd12a15b2364 Mon Sep 17 00:00:00 2001 From: Blazebrain Date: Thu, 18 May 2023 04:15:55 +0100 Subject: [PATCH] Finished setup and initiated initial testing WIP [skip ci] --- cw_bitcoin/lib/bitcoin_wallet_service.dart | 2 +- cw_bitcoin/lib/litecoin_wallet_service.dart | 2 +- cw_core/lib/wallet_service.dart | 2 +- cw_haven/lib/api/wallet_manager.dart | 37 ++--- cw_haven/lib/haven_wallet_service.dart | 5 +- cw_monero/lib/api/wallet_manager.dart | 45 +++--- cw_monero/lib/monero_wallet_service.dart | 52 +++--- lib/core/wallet_creation_service.dart | 43 +++-- .../screens/restore/restore_options_page.dart | 9 +- .../restore/restore_from_qr_vm.dart | 23 +-- lib/view_model/restore/restore_wallet.dart | 9 +- .../restore/wallet_restore_from_qr_code.dart | 6 +- lib/view_model/wallet_creation_vm.dart | 150 +++++++++++++----- lib/view_model/wallet_new_vm.dart | 6 +- 14 files changed, 215 insertions(+), 176 deletions(-) diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 500e50104..a7b86a248 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -80,7 +80,7 @@ class BitcoinWalletService extends WalletService< } @override - Future sweepAllFunds(Node node, String address, String paymentId) { + Future> sweepAllFunds(Node node, String address, String paymentId) { // TODO: implement sweepAllFunds throw UnimplementedError(); } diff --git a/cw_bitcoin/lib/litecoin_wallet_service.dart b/cw_bitcoin/lib/litecoin_wallet_service.dart index 3bf21bdb5..9ba250a44 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -81,7 +81,7 @@ class LitecoinWalletService extends WalletService< } @override - Future sweepAllFunds(Node node, String address, String paymentId) { + Future> sweepAllFunds(Node node, String address, String paymentId) { // TODO: implement sweepAllFunds throw UnimplementedError(); } diff --git a/cw_core/lib/wallet_service.dart b/cw_core/lib/wallet_service.dart index 1402785ad..b08ad9cf7 100644 --- a/cw_core/lib/wallet_service.dart +++ b/cw_core/lib/wallet_service.dart @@ -15,7 +15,7 @@ abstract class WalletService restoreFromKeys(RFK credentials); - Future sweepAllFunds(Node node, String address, String paymentId); + Future> sweepAllFunds(Node node, String address, String paymentId); Future openWallet(String name, String password); diff --git a/cw_haven/lib/api/wallet_manager.dart b/cw_haven/lib/api/wallet_manager.dart index 52b418c5f..19fe56942 100644 --- a/cw_haven/lib/api/wallet_manager.dart +++ b/cw_haven/lib/api/wallet_manager.dart @@ -48,8 +48,8 @@ void createWalletSync( final passwordPointer = password.toNativeUtf8(); final languagePointer = language.toNativeUtf8(); final errorMessagePointer = ''.toNativeUtf8(); - final isWalletCreated = createWalletNative(pathPointer, passwordPointer, - languagePointer, nettype, errorMessagePointer) != + final isWalletCreated = createWalletNative( + pathPointer, passwordPointer, languagePointer, nettype, errorMessagePointer) != 0; calloc.free(pathPointer); @@ -57,8 +57,7 @@ void createWalletSync( calloc.free(languagePointer); if (!isWalletCreated) { - throw WalletCreationException( - message: convertUTF8ToString(pointer: errorMessagePointer)); + throw WalletCreationException(message: convertUTF8ToString(pointer: errorMessagePointer)); } // setupNodeSync(address: "node.moneroworld.com:18089"); @@ -84,12 +83,7 @@ void restoreWalletFromSeedSync( final seedPointer = seed.toNativeUtf8(); final errorMessagePointer = ''.toNativeUtf8(); final isWalletRestored = restoreWalletFromSeedNative( - pathPointer, - passwordPointer, - seedPointer, - nettype, - restoreHeight, - errorMessagePointer) != + pathPointer, passwordPointer, seedPointer, nettype, restoreHeight, errorMessagePointer) != 0; calloc.free(pathPointer); @@ -151,8 +145,7 @@ void loadWallet({required String path, required String password, int nettype = 0 calloc.free(passwordPointer); if (!loaded) { - throw WalletOpeningException( - message: convertUTF8ToString(pointer: errorStringNative())); + throw WalletOpeningException(message: convertUTF8ToString(pointer: errorStringNative())); } } @@ -201,20 +194,15 @@ bool _isWalletExist(String path) => isWalletExistSync(path: path); void openWallet({required String path, required String password, int nettype = 0}) async => loadWallet(path: path, password: password, nettype: nettype); -Future openWalletAsync(Map args) async => - compute(_openWallet, args); +Future openWalletAsync(Map args) async => compute(_openWallet, args); Future createWallet( {required String path, required String password, required String language, int nettype = 0}) async => - compute(_createWallet, { - 'path': path, - 'password': password, - 'language': language, - 'nettype': nettype - }); + compute(_createWallet, + {'path': path, 'password': password, 'language': language, 'nettype': nettype}); Future restoreFromSeed( {required String path, @@ -250,7 +238,7 @@ Future restoreFromKeys( 'restoreHeight': restoreHeight }); -Future sweepFundsToNewWallet({ +Future> sweepFundsToNewWallet({ required Node node, required String address, required String paymentId, @@ -311,9 +299,10 @@ Future sweepFundsToNewWallet({ client.close(); final resBody = json.decode(response.body) as Map; - return !(resBody['result']['offline'] as bool); - } catch (_) { - return false; + return resBody; + } catch (e) { + print(e); + throw Exception(e); } } diff --git a/cw_haven/lib/haven_wallet_service.dart b/cw_haven/lib/haven_wallet_service.dart index bb70e2076..fc582b7f1 100644 --- a/cw_haven/lib/haven_wallet_service.dart +++ b/cw_haven/lib/haven_wallet_service.dart @@ -231,13 +231,14 @@ class HavenWalletService extends WalletService< } @override - Future sweepAllFunds(Node node, String address, String paymentId) async { + Future> sweepAllFunds(Node node, String address, String paymentId) async { try { - await haven_wallet_manager.sweepFundsToNewWallet( + final result = await haven_wallet_manager.sweepFundsToNewWallet( node: node, address: address, paymentId: paymentId, ); + return result; } catch (e) { // TODO: Implement Exception for wallet list service. print('MoneroWalletsManager Error: $e'); diff --git a/cw_monero/lib/api/wallet_manager.dart b/cw_monero/lib/api/wallet_manager.dart index 14f9ba338..471a204d8 100644 --- a/cw_monero/lib/api/wallet_manager.dart +++ b/cw_monero/lib/api/wallet_manager.dart @@ -232,7 +232,7 @@ Future restoreFromKeys( 'restoreHeight': restoreHeight }); -Future sweepFundsToNewWallet({ +Future> sweepFundsToNewWallet({ required Node node, required String address, required String paymentId, @@ -253,24 +253,24 @@ Future sweepFundsToNewWallet({ final rpcUri = node.isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path); final realm = 'monero-rpc'; final body = { - 'method': 'sweep_all', - 'params': { - 'address': address, - 'account_index': accountIndex, - 'subaddr_indices': subaddressIndices, - 'priority': priority, - 'ring_size': ringSize, - 'outputs': outputs, - 'unlock_time': unlockTime, - 'payment_id': paymentId, - 'get_tx_keys': getTxKeys, - 'below_amount': belowAmount, - 'do_not_relay': doNotRelay, - 'get_tx_hex': getTxHex, - 'get_tx_metadata': getTxMetadata, + "method": "sweep_all", + "jsonrpc": "2.0", + "id": "0", + "params": { + "address": address, + "account_index": accountIndex, + "subaddr_indices": subaddressIndices, + "priority": priority, + "ring_size": ringSize, + "outputs": outputs, + "unlock_time": unlockTime, + "payment_id": paymentId, + "get_tx_keys": getTxKeys, + "below_amount": belowAmount, + "do_not_relay": doNotRelay, + "get_tx_hex": getTxHex, + "get_tx_metadata": getTxMetadata, }, - 'jsonrpc': '2.0', - 'id': '0' }; try { @@ -291,11 +291,12 @@ Future sweepFundsToNewWallet({ ); client.close(); - final resBody = json.decode(response.body) as Map; - return !(resBody['result']['offline'] as bool); - } catch (_) { - return false; + + return resBody; + } catch (e) { + print(e); + throw Exception(e); } } diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index adf55d016..35ec5c742 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -50,14 +50,12 @@ class MoneroRestoreWalletFromKeysCredentials extends WalletCredentials { final String spendKey; } -class MoneroWalletService extends WalletService< - MoneroNewWalletCredentials, - MoneroRestoreWalletFromSeedCredentials, - MoneroRestoreWalletFromKeysCredentials> { +class MoneroWalletService extends WalletService { MoneroWalletService(this.walletInfoSource); final Box walletInfoSource; - + static bool walletFilesExist(String path) => !File(path).existsSync() && !File('$path.keys').existsSync(); @@ -69,9 +67,7 @@ class MoneroWalletService extends WalletService< try { final path = await pathForWallet(name: credentials.name, type: getType()); await monero_wallet_manager.createWallet( - path: path, - password: credentials.password!, - language: credentials.language); + path: path, password: credentials.password!, language: credentials.language); final wallet = MoneroWallet(walletInfo: credentials.walletInfo!); await wallet.init(); @@ -104,10 +100,9 @@ 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())); + 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); final isValid = wallet.walletAddresses.validate(); @@ -124,12 +119,10 @@ class MoneroWalletService extends WalletService< // TODO: Implement Exception for wallet list service. if ((e.toString().contains('bad_alloc') || - (e is WalletOpeningException && - (e.message == 'std::bad_alloc' || - e.message.contains('bad_alloc')))) || + (e is WalletOpeningException && + (e.message == 'std::bad_alloc' || e.message.contains('bad_alloc')))) || (e.toString().contains('does not correspond') || - (e is WalletOpeningException && - e.message.contains('does not correspond')))) { + (e is WalletOpeningException && e.message.contains('does not correspond')))) { await restoreOrResetWalletFiles(name); return openWallet(name, password); } @@ -150,8 +143,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( @@ -174,8 +166,7 @@ class MoneroWalletService extends WalletService< } @override - Future restoreFromSeed( - MoneroRestoreWalletFromSeedCredentials credentials) async { + Future restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials) async { try { final path = await pathForWallet(name: credentials.name, type: getType()); await monero_wallet_manager.restoreFromSeed( @@ -193,36 +184,43 @@ class MoneroWalletService extends WalletService< rethrow; } } + @override - Future sweepAllFunds(Node node, String address, String paymentId) async { + Future> sweepAllFunds(Node node, String address, String paymentId) async { try { - await monero_wallet_manager.sweepFundsToNewWallet( + final response = await monero_wallet_manager.sweepFundsToNewWallet( node: node, address: address, paymentId: paymentId, ); + + + if (response['error'] != null) { + throw Exception('${response['error']['message']}'); + } else { + return response; + } } catch (e) { // TODO: Implement Exception for wallet list service. print('MoneroWalletsManager Error: $e'); rethrow; } } + Future repairOldAndroidWallet(String name) async { try { if (!Platform.isAndroid) { 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/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart index 3b28f36c3..5b6a72b72 100644 --- a/lib/core/wallet_creation_service.dart +++ b/lib/core/wallet_creation_service.dart @@ -1,4 +1,5 @@ import 'package:cake_wallet/di.dart'; +import 'package:cw_core/node.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:flutter/foundation.dart'; @@ -39,15 +40,11 @@ class WalletCreationService { bool exists(String name) { final walletName = name.toLowerCase(); - return walletInfoSource - .values - .any((walletInfo) => walletInfo.name.toLowerCase() == walletName); + return walletInfoSource.values.any((walletInfo) => walletInfo.name.toLowerCase() == walletName); } bool typeExists(WalletType type) { - return walletInfoSource - .values - .any((walletInfo) => walletInfo.type == type); + return walletInfoSource.values.any((walletInfo) => walletInfo.type == type); } void checkIfExists(String name) { @@ -60,15 +57,12 @@ class WalletCreationService { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; - await keyService.saveWalletPassword( - password: password, walletName: credentials.name); - final wallet = await _service!.create(credentials); + await keyService.saveWalletPassword(password: password, walletName: credentials.name); + final wallet = await _service!.create(credentials); if (wallet.type == WalletType.monero) { - await sharedPreferences - .setBool( - PreferencesKey.moneroWalletUpdateV1Key(wallet.name), - _isNewMoneroWalletPasswordUpdated); + await sharedPreferences.setBool( + PreferencesKey.moneroWalletUpdateV1Key(wallet.name), _isNewMoneroWalletPasswordUpdated); } return wallet; @@ -78,15 +72,12 @@ class WalletCreationService { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; - await keyService.saveWalletPassword( - password: password, walletName: credentials.name); + await keyService.saveWalletPassword(password: password, walletName: credentials.name); final wallet = await _service!.restoreFromKeys(credentials); if (wallet.type == WalletType.monero) { - await sharedPreferences - .setBool( - PreferencesKey.moneroWalletUpdateV1Key(wallet.name), - _isNewMoneroWalletPasswordUpdated); + await sharedPreferences.setBool( + PreferencesKey.moneroWalletUpdateV1Key(wallet.name), _isNewMoneroWalletPasswordUpdated); } return wallet; @@ -96,17 +87,19 @@ class WalletCreationService { checkIfExists(credentials.name); final password = generateWalletPassword(); credentials.password = password; - await keyService.saveWalletPassword( - password: password, walletName: credentials.name); + await keyService.saveWalletPassword(password: password, walletName: credentials.name); final wallet = await _service!.restoreFromSeed(credentials); if (wallet.type == WalletType.monero) { - await sharedPreferences - .setBool( - PreferencesKey.moneroWalletUpdateV1Key(wallet.name), - _isNewMoneroWalletPasswordUpdated); + await sharedPreferences.setBool( + PreferencesKey.moneroWalletUpdateV1Key(wallet.name), _isNewMoneroWalletPasswordUpdated); } return wallet; } + + Future> sweepAllFunds(Node node, String address, String paymentId) async { + final result = await _service!.sweepAllFunds(node, address, paymentId); + return result; + } } diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 49448bcea..6eac78a7b 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -21,7 +21,6 @@ class RestoreOptionsPage extends BasePage { @override String get title => S.current.restore_restore_wallet; - final bool isNewInstall; final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png'); final imageBackup = Image.asset('assets/images/backup.png'); @@ -38,8 +37,7 @@ class RestoreOptionsPage extends BasePage { child: Column( children: [ RestoreButton( - onPressed: () => Navigator.pushNamed( - context, Routes.restoreWalletFromSeedKeys, + onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletFromSeedKeys, arguments: isNewInstall), image: imageSeedKeys, title: S.of(context).restore_title_from_seed_keys, @@ -74,10 +72,11 @@ class RestoreOptionsPage extends BasePage { //! Next step will be to create a new wallet from this final restoreFromQRViewModel = getIt.get(param1: restoreWallet.type); - await restoreFromQRViewModel.create(restoreWallet: restoreWallet); + await restoreFromQRViewModel.create(restoreWallet: restoreWallet); if (restoreFromQRViewModel.state is FailureState) { + final errorState = restoreFromQRViewModel.state as FailureState; _onWalletCreateFailure(context, - 'Create wallet state: ${restoreFromQRViewModel.state.runtimeType.toString()}'); + 'Create wallet state: ${errorState.error}'); } } catch (e) { _onWalletCreateFailure(context, e.toString()); diff --git a/lib/view_model/restore/restore_from_qr_vm.dart b/lib/view_model/restore/restore_from_qr_vm.dart index 82e385b52..04cc7aa7d 100644 --- a/lib/view_model/restore/restore_from_qr_vm.dart +++ b/lib/view_model/restore/restore_from_qr_vm.dart @@ -25,8 +25,7 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store spendKey = '', wif = '', address = '', - super(appStore, walletInfoSource, walletCreationService, - type: type, isRecovery: true); + super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true); @observable int height; @@ -46,7 +45,8 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store bool get hasRestorationHeight => type == WalletType.monero; @override - WalletCredentials getCredentialsFromRestoredWallet(dynamic options, RestoredWallet restoreWallet) { + WalletCredentials getCredentialsFromRestoredWallet( + dynamic options, RestoredWallet restoreWallet) { final password = generateWalletPassword(); switch (restoreWallet.restoreMode) { @@ -69,6 +69,7 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store throw Exception('Unexpected type: ${restoreWallet.type.toString()}'); } case WalletRestoreMode.seed: + case WalletRestoreMode.txids: switch (restoreWallet.type) { case WalletType.monero: return monero!.createMoneroRestoreWalletFromSeedCredentials( @@ -83,30 +84,20 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store default: throw Exception('Unexpected type: ${type.toString()}'); } - case WalletRestoreMode.txids: - switch (restoreWallet.type) { - case WalletType.monero: - return monero! - .createMoneroNewWalletCredentials(name: name, language: options as String); - case WalletType.bitcoin: - return bitcoin!.createBitcoinNewWalletCredentials(name: name); - case WalletType.litecoin: - return bitcoin!.createBitcoinNewWalletCredentials(name: name); - default: - throw Exception('Unexpected type: ${restoreWallet.type.toString()}'); - } default: throw Exception('Unexpected type: ${type.toString()}'); } } @override - Future processFromRestoredWallet(WalletCredentials credentials, RestoredWallet restoreWallet) async { + Future processFromRestoredWallet( + WalletCredentials credentials, RestoredWallet restoreWallet) async { try { switch (restoreWallet.restoreMode) { case WalletRestoreMode.keys: return walletCreationService.restoreFromKeys(credentials); case WalletRestoreMode.seed: + case WalletRestoreMode.txids: return walletCreationService.restoreFromSeed(credentials); default: throw Exception('Unexpected restore mode: ${restoreWallet.restoreMode.toString()}'); diff --git a/lib/view_model/restore/restore_wallet.dart b/lib/view_model/restore/restore_wallet.dart index 0f872d8cc..b9597e4f5 100644 --- a/lib/view_model/restore/restore_wallet.dart +++ b/lib/view_model/restore/restore_wallet.dart @@ -53,12 +53,17 @@ class RestoredWallet { } factory RestoredWallet.fromTxIds(Map json) { + final mnemonic_seed = json['mnemonic_seed'] as String?; + final seed = json['seed'] as String?; return RestoredWallet( restoreMode: json['mode'] as WalletRestoreMode, type: json['type'] as WalletType, address: json['address'] as String?, - txId: json['tx_payment_id'] as String, - txAmount: json['tx_amount'] as String, + txId: json['txid'] as String, + txAmount: json['tx_amount'] as String?, + mnemonicSeed: mnemonic_seed ?? seed, + spendKey: json['spend_key'] as String?, + viewKey: json['view_key'] as String?, txDescription: json['tx_description'] as String?, recipientName: json['recipient_name'] as String?, ); diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart index c4b772f9c..499f64256 100644 --- a/lib/view_model/restore/wallet_restore_from_qr_code.dart +++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart @@ -125,11 +125,11 @@ class WalletRestoreFromQRCode { static WalletRestoreMode getWalletRestoreMode(Map credentials) { final type = credentials['type'] as WalletType; - if (credentials.containsKey('tx_payment_id')) { - final txIdValue = credentials['tx_payment_id'] as String? ?? ''; + if (credentials.containsKey('txid')) { + final txIdValue = credentials['txid'] as String? ?? ''; return txIdValue.isNotEmpty ? WalletRestoreMode.txids - : throw Exception('Unexpected restore mode: tx_payment_id is invalid'); + : throw Exception('Unexpected restore mode: txid is invalid'); } if (credentials.containsKey('seed')) { diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 78851e790..adb6ddd70 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -1,5 +1,8 @@ import 'package:cake_wallet/core/wallet_creation_service.dart'; import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; +import 'package:cw_core/balance.dart'; +import 'package:cw_core/transaction_history.dart'; +import 'package:cw_core/transaction_info.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; import 'package:cake_wallet/core/execution_state.dart'; @@ -10,6 +13,9 @@ import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/entities/generate_name.dart'; +import 'package:cake_wallet/monero/monero.dart'; +import 'package:cake_wallet/bitcoin/bitcoin.dart'; +import 'package:cake_wallet/haven/haven.dart'; part 'wallet_creation_vm.g.dart'; @@ -33,64 +39,122 @@ abstract class WalletCreationVMBase with Store { final Box _walletInfoSource; final AppStore _appStore; - bool nameExists(String name) - => walletCreationService.exists(name); + bool nameExists(String name) => walletCreationService.exists(name); - bool typeExists(WalletType type) - => walletCreationService.typeExists(type); + bool typeExists(WalletType type) => walletCreationService.typeExists(type); Future create({dynamic options, RestoredWallet? restoreWallet}) async { final type = restoreWallet?.type ?? this.type; try { - state = IsExecutingState(); - if (name.isEmpty) { - name = await generateName(); - } + //! Create a restoredWallet from the scanned wallet parameters + final restoredWallet = + await createNewWalletWithoutSwitching(options: options, restoreWallet: restoreWallet); + print('Restored Wallet Address ' + restoredWallet.walletAddresses.address); - walletCreationService.checkIfExists(name); - final dirPath = await pathForWalletDir(name: name, type: type); - final path = await pathForWallet(name: name, type: type); - final credentials = restoreWallet != null - ? getCredentialsFromRestoredWallet(options, restoreWallet) - : getCredentials(options); - final walletInfo = WalletInfo.external( - id: WalletBase.idFor(name, type), - name: name, - type: type, - isRecovery: isRecovery, - restoreHeight: credentials.height ?? 0, - date: DateTime.now(), - path: path, - dirPath: dirPath, - address: '', - showIntroCakePayCard: (!walletCreationService.typeExists(type)) && type != WalletType.haven); - credentials.walletInfo = walletInfo; + //TODO Get transactions details to verify 10 confirmations - //! Restored - final wallet = restoreWallet != null - ? await processFromRestoredWallet(credentials, restoreWallet) - : await process(credentials); - walletInfo.address = wallet.walletAddresses.address; - await _walletInfoSource.add(walletInfo); - //---- Code to create new + //! Create the newWallet that will received the funds + final newWallet = await createNewWalletWithoutSwitching( + options: options, + regenerateName: true, + ); + final newWalletAddress = newWallet.walletAddresses.address; + print('New Wallet Address ' + newWalletAddress); - //! Before we switch - _appStore.changeCurrentWallet(wallet); + //! Switch to the restoredWallet in order to activate the node connection + _appStore.changeCurrentWallet(restoredWallet); + + //! Sweep all funds from restoredWallet to newWallet + await sweepAllFundsToNewWallet(type, newWalletAddress, restoreWallet?.txId ?? ''); + + //! Switch back to new wallet + _appStore.changeCurrentWallet(newWallet); + + //! Add the new Wallet info to the walletInfoSource + await _walletInfoSource.add(newWallet.walletInfo); + + //! Approve authentication as successful _appStore.authenticationStore.allowed(); state = ExecutedSuccessfullyState(); } catch (e) { state = FailureState(e.toString()); } } - WalletCredentials getCredentials(dynamic options) => + + Future, TransactionInfo>> + createNewWalletWithoutSwitching( + {dynamic options, RestoredWallet? restoreWallet, bool regenerateName = false}) async { + state = IsExecutingState(); + if (name.isEmpty) { + name = await generateName(); + } + + if (regenerateName) { + name = await generateName(); + } + + walletCreationService.checkIfExists(name); + final dirPath = await pathForWalletDir(name: name, type: type); + final path = await pathForWallet(name: name, type: type); + final credentials = restoreWallet != null + ? getCredentialsFromRestoredWallet(options, restoreWallet) + : getCredentials(options); + final walletInfo = WalletInfo.external( + id: WalletBase.idFor(name, type), + name: name, + type: type, + isRecovery: isRecovery, + restoreHeight: credentials.height ?? 0, + date: DateTime.now(), + path: path, + dirPath: dirPath, + address: '', + showIntroCakePayCard: + (!walletCreationService.typeExists(type)) && type != WalletType.haven); + credentials.walletInfo = walletInfo; + + final wallet = restoreWallet != null + ? await processFromRestoredWallet(credentials, restoreWallet) + : await process(credentials); + walletInfo.address = wallet.walletAddresses.address; + + return wallet; + } + + Future> sweepAllFundsToNewWallet( + WalletType type, String address, String paymentId) async { + final currentNode = _appStore.settingsStore.getCurrentNode(type); + final result = await walletCreationService.sweepAllFunds(currentNode, address, paymentId); + return result; + } + + WalletCredentials getCredentials(dynamic options) { + switch (type) { + case WalletType.monero: + return monero! + .createMoneroNewWalletCredentials(name: name, language: options as String? ?? ''); + case WalletType.bitcoin: + return bitcoin!.createBitcoinNewWalletCredentials(name: name); + case WalletType.litecoin: + return bitcoin!.createBitcoinNewWalletCredentials(name: name); + case WalletType.haven: + return haven! + .createHavenNewWalletCredentials(name: name, language: options as String? ?? ''); + default: + throw Exception('Unexpected type: ${type.toString()}'); + } + } + + Future process(WalletCredentials credentials) { + walletCreationService.changeWalletType(type: type); + return walletCreationService.create(credentials); + } + + WalletCredentials getCredentialsFromRestoredWallet( + dynamic options, RestoredWallet restoreWallet) => throw UnimplementedError(); - Future process(WalletCredentials credentials) => - throw UnimplementedError(); - - WalletCredentials getCredentialsFromRestoredWallet(dynamic options, RestoredWallet restoreWallet) => - throw UnimplementedError(); - - Future processFromRestoredWallet(WalletCredentials credentials, RestoredWallet restoreWallet) => + Future processFromRestoredWallet( + WalletCredentials credentials, RestoredWallet restoreWallet) => throw UnimplementedError(); } diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart index dcd57b3ff..f833cba55 100644 --- a/lib/view_model/wallet_new_vm.dart +++ b/lib/view_model/wallet_new_vm.dart @@ -1,8 +1,5 @@ -import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; -import 'package:flutter/foundation.dart'; import 'package:hive/hive.dart'; import 'package:mobx/mobx.dart'; -import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cake_wallet/core/wallet_creation_service.dart'; @@ -10,6 +7,7 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cake_wallet/view_model/wallet_creation_vm.dart'; +import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/haven/haven.dart'; @@ -43,7 +41,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store { return haven!.createHavenNewWalletCredentials( name: name, language: options as String); default: - throw Exception('Unexpected type: ${type.toString()}');; + throw Exception('Unexpected type: ${type.toString()}'); } }