diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart index 398d68fc2..500e50104 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_service.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic_is_incorrect_exception.dart'; import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart'; +import 'package:cw_core/node.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_service.dart'; @@ -77,4 +78,10 @@ class BitcoinWalletService extends WalletService< await wallet.init(); return wallet; } + + @override + 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 2093647fd..3bf21bdb5 100644 --- a/cw_bitcoin/lib/litecoin_wallet_service.dart +++ b/cw_bitcoin/lib/litecoin_wallet_service.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'package:cw_core/node.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:hive/hive.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; @@ -78,4 +79,10 @@ class LitecoinWalletService extends WalletService< await wallet.init(); return wallet; } + + @override + 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 f66f39583..1402785ad 100644 --- a/cw_core/lib/wallet_service.dart +++ b/cw_core/lib/wallet_service.dart @@ -2,8 +2,11 @@ import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_type.dart'; +import 'node.dart'; + abstract class WalletService { + RFS extends WalletCredentials, + RFK extends WalletCredentials> { WalletType getType(); Future create(N credentials); @@ -12,6 +15,8 @@ abstract class WalletService restoreFromKeys(RFK credentials); + Future sweepAllFunds(Node node, String address, String paymentId); + Future openWallet(String name, String password); Future isWalletExit(String name); diff --git a/cw_haven/lib/api/wallet_manager.dart b/cw_haven/lib/api/wallet_manager.dart index 627fc226a..52b418c5f 100644 --- a/cw_haven/lib/api/wallet_manager.dart +++ b/cw_haven/lib/api/wallet_manager.dart @@ -1,4 +1,7 @@ +import 'dart:convert'; import 'dart:ffi'; +import 'dart:io'; +import 'package:cw_core/node.dart'; import 'package:ffi/ffi.dart'; import 'package:flutter/foundation.dart'; import 'package:cw_haven/api/convert_utf8_to_string.dart'; @@ -6,6 +9,8 @@ import 'package:cw_haven/api/signatures.dart'; import 'package:cw_haven/api/types.dart'; import 'package:cw_haven/api/haven_api.dart'; import 'package:cw_haven/api/wallet.dart'; +import 'package:http/http.dart' as http; +import 'package:http/io_client.dart' as ioc; import 'package:cw_haven/api/exceptions/wallet_opening_exception.dart'; import 'package:cw_haven/api/exceptions/wallet_creation_exception.dart'; import 'package:cw_haven/api/exceptions/wallet_restore_from_keys_exception.dart'; @@ -245,4 +250,71 @@ Future restoreFromKeys( 'restoreHeight': restoreHeight }); +Future sweepFundsToNewWallet({ + required Node node, + required String address, + required String paymentId, + List subaddressIndices = const [], + int accountIndex = 0, + int priority = 0, + int ringSize = 0, + int outputs = 0, + int unlockTime = 1, + bool getTxKeys = false, + bool doNotRelay = false, + bool getTxHex = false, + bool getTxMetadata = false, + int belowAmount = 0, +}) async { + final uri = Uri.http(node.uriRaw, ''); + final path = '/json_rpc'; + final rpcUri = Uri.https(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, + }, + 'jsonrpc': '2.0', + 'id': '0' + }; + + try { + final authenticatingClient = HttpClient(); + + authenticatingClient.addCredentials( + rpcUri, + realm, + HttpClientDigestCredentials(node.login ?? '', node.password ?? ''), + ); + + final http.Client client = ioc.IOClient(authenticatingClient); + + final response = await client.post( + rpcUri, + headers: {'Content-Type': 'application/json'}, + body: json.encode(body), + ); + + client.close(); + + final resBody = json.decode(response.body) as Map; + return !(resBody['result']['offline'] as bool); + } catch (_) { + return false; + } +} + Future isWalletExist({required String path}) => compute(_isWalletExist, path); diff --git a/cw_haven/lib/haven_wallet_service.dart b/cw_haven/lib/haven_wallet_service.dart index 137ade78f..bb70e2076 100644 --- a/cw_haven/lib/haven_wallet_service.dart +++ b/cw_haven/lib/haven_wallet_service.dart @@ -1,5 +1,6 @@ import 'dart:io'; import 'package:collection/collection.dart'; +import 'package:cw_core/node.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/monero_wallet_utils.dart'; import 'package:hive/hive.dart'; @@ -228,4 +229,19 @@ class HavenWalletService extends WalletService< print(e.toString()); } } + + @override + Future sweepAllFunds(Node node, String address, String paymentId) async { + try { + await haven_wallet_manager.sweepFundsToNewWallet( + node: node, + address: address, + paymentId: paymentId, + ); + } catch (e) { + // TODO: Implement Exception for wallet list service. + print('MoneroWalletsManager Error: $e'); + rethrow; + } + } } diff --git a/cw_monero/lib/api/wallet_manager.dart b/cw_monero/lib/api/wallet_manager.dart index fb91c2ac1..3ff731a8e 100644 --- a/cw_monero/lib/api/wallet_manager.dart +++ b/cw_monero/lib/api/wallet_manager.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:ffi'; import 'dart:io'; +import 'package:cw_core/node.dart'; import 'package:ffi/ffi.dart'; import 'package:flutter/foundation.dart'; import 'package:cw_monero/api/convert_utf8_to_string.dart'; @@ -232,25 +233,23 @@ Future restoreFromKeys( 'restoreHeight': restoreHeight }); -Future restoreFromTxIdS({ - required String uriRaw, +Future sweepFundsToNewWallet({ + required Node node, required String address, + required String paymentId, List subaddressIndices = const [], int accountIndex = 0, int priority = 0, int ringSize = 0, int outputs = 0, int unlockTime = 1, - required String paymentId, bool getTxKeys = false, bool doNotRelay = false, bool getTxHex = false, bool getTxMetadata = false, int belowAmount = 0, - String? username, - String? password, }) async { - final uri = Uri.http(uriRaw, ''); + final uri = Uri.http(node.uriRaw, ''); final path = '/json_rpc'; final rpcUri = Uri.https(uri.authority, path); final realm = 'monero-rpc'; @@ -281,7 +280,7 @@ Future restoreFromTxIdS({ authenticatingClient.addCredentials( rpcUri, realm, - HttpClientDigestCredentials(username ?? '', password ?? ''), + HttpClientDigestCredentials(node.login ?? '', node.password ?? ''), ); final http.Client client = ioc.IOClient(authenticatingClient); diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 095fe83bb..adf55d016 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -1,4 +1,5 @@ import 'dart:io'; +import 'package:cw_core/node.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/monero_wallet_utils.dart'; import 'package:hive/hive.dart'; @@ -192,7 +193,20 @@ class MoneroWalletService extends WalletService< rethrow; } } - + @override + Future sweepAllFunds(Node node, String address, String paymentId) async { + try { + await monero_wallet_manager.sweepFundsToNewWallet( + node: node, + address: address, + paymentId: paymentId, + ); + } catch (e) { + // TODO: Implement Exception for wallet list service. + print('MoneroWalletsManager Error: $e'); + rethrow; + } + } Future repairOldAndroidWallet(String name) async { try { if (!Platform.isAndroid) {