Finished setup and initiated initial testing WIP [skip ci]

This commit is contained in:
Blazebrain 2023-05-18 04:15:55 +01:00
parent 8c609f09a1
commit b7d9bf8746
14 changed files with 215 additions and 176 deletions

View file

@ -80,7 +80,7 @@ class BitcoinWalletService extends WalletService<
} }
@override @override
Future<void> sweepAllFunds(Node node, String address, String paymentId) { Future<Map<String, dynamic>> sweepAllFunds(Node node, String address, String paymentId) {
// TODO: implement sweepAllFunds // TODO: implement sweepAllFunds
throw UnimplementedError(); throw UnimplementedError();
} }

View file

@ -81,7 +81,7 @@ class LitecoinWalletService extends WalletService<
} }
@override @override
Future<void> sweepAllFunds(Node node, String address, String paymentId) { Future<Map<String, dynamic>> sweepAllFunds(Node node, String address, String paymentId) {
// TODO: implement sweepAllFunds // TODO: implement sweepAllFunds
throw UnimplementedError(); throw UnimplementedError();
} }

View file

@ -15,7 +15,7 @@ abstract class WalletService<N extends WalletCredentials,
Future<WalletBase> restoreFromKeys(RFK credentials); Future<WalletBase> restoreFromKeys(RFK credentials);
Future<void> sweepAllFunds(Node node, String address, String paymentId); Future<Map<String, dynamic>> sweepAllFunds(Node node, String address, String paymentId);
Future<WalletBase> openWallet(String name, String password); Future<WalletBase> openWallet(String name, String password);

View file

@ -48,8 +48,8 @@ void createWalletSync(
final passwordPointer = password.toNativeUtf8(); final passwordPointer = password.toNativeUtf8();
final languagePointer = language.toNativeUtf8(); final languagePointer = language.toNativeUtf8();
final errorMessagePointer = ''.toNativeUtf8(); final errorMessagePointer = ''.toNativeUtf8();
final isWalletCreated = createWalletNative(pathPointer, passwordPointer, final isWalletCreated = createWalletNative(
languagePointer, nettype, errorMessagePointer) != pathPointer, passwordPointer, languagePointer, nettype, errorMessagePointer) !=
0; 0;
calloc.free(pathPointer); calloc.free(pathPointer);
@ -57,8 +57,7 @@ void createWalletSync(
calloc.free(languagePointer); calloc.free(languagePointer);
if (!isWalletCreated) { if (!isWalletCreated) {
throw WalletCreationException( throw WalletCreationException(message: convertUTF8ToString(pointer: errorMessagePointer));
message: convertUTF8ToString(pointer: errorMessagePointer));
} }
// setupNodeSync(address: "node.moneroworld.com:18089"); // setupNodeSync(address: "node.moneroworld.com:18089");
@ -84,12 +83,7 @@ void restoreWalletFromSeedSync(
final seedPointer = seed.toNativeUtf8(); final seedPointer = seed.toNativeUtf8();
final errorMessagePointer = ''.toNativeUtf8(); final errorMessagePointer = ''.toNativeUtf8();
final isWalletRestored = restoreWalletFromSeedNative( final isWalletRestored = restoreWalletFromSeedNative(
pathPointer, pathPointer, passwordPointer, seedPointer, nettype, restoreHeight, errorMessagePointer) !=
passwordPointer,
seedPointer,
nettype,
restoreHeight,
errorMessagePointer) !=
0; 0;
calloc.free(pathPointer); calloc.free(pathPointer);
@ -151,8 +145,7 @@ void loadWallet({required String path, required String password, int nettype = 0
calloc.free(passwordPointer); calloc.free(passwordPointer);
if (!loaded) { if (!loaded) {
throw WalletOpeningException( throw WalletOpeningException(message: convertUTF8ToString(pointer: errorStringNative()));
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 => void openWallet({required String path, required String password, int nettype = 0}) async =>
loadWallet(path: path, password: password, nettype: nettype); loadWallet(path: path, password: password, nettype: nettype);
Future<void> openWalletAsync(Map<String, String> args) async => Future<void> openWalletAsync(Map<String, String> args) async => compute(_openWallet, args);
compute(_openWallet, args);
Future<void> createWallet( Future<void> createWallet(
{required String path, {required String path,
required String password, required String password,
required String language, required String language,
int nettype = 0}) async => int nettype = 0}) async =>
compute(_createWallet, { compute(_createWallet,
'path': path, {'path': path, 'password': password, 'language': language, 'nettype': nettype});
'password': password,
'language': language,
'nettype': nettype
});
Future<void> restoreFromSeed( Future<void> restoreFromSeed(
{required String path, {required String path,
@ -250,7 +238,7 @@ Future<void> restoreFromKeys(
'restoreHeight': restoreHeight 'restoreHeight': restoreHeight
}); });
Future<bool> sweepFundsToNewWallet({ Future<Map<String, dynamic>> sweepFundsToNewWallet({
required Node node, required Node node,
required String address, required String address,
required String paymentId, required String paymentId,
@ -311,9 +299,10 @@ Future<bool> sweepFundsToNewWallet({
client.close(); client.close();
final resBody = json.decode(response.body) as Map<String, dynamic>; final resBody = json.decode(response.body) as Map<String, dynamic>;
return !(resBody['result']['offline'] as bool); return resBody;
} catch (_) { } catch (e) {
return false; print(e);
throw Exception(e);
} }
} }

View file

@ -231,13 +231,14 @@ class HavenWalletService extends WalletService<
} }
@override @override
Future<void> sweepAllFunds(Node node, String address, String paymentId) async { Future<Map<String, dynamic>> sweepAllFunds(Node node, String address, String paymentId) async {
try { try {
await haven_wallet_manager.sweepFundsToNewWallet( final result = await haven_wallet_manager.sweepFundsToNewWallet(
node: node, node: node,
address: address, address: address,
paymentId: paymentId, paymentId: paymentId,
); );
return result;
} catch (e) { } catch (e) {
// TODO: Implement Exception for wallet list service. // TODO: Implement Exception for wallet list service.
print('MoneroWalletsManager Error: $e'); print('MoneroWalletsManager Error: $e');

View file

@ -232,7 +232,7 @@ Future<void> restoreFromKeys(
'restoreHeight': restoreHeight 'restoreHeight': restoreHeight
}); });
Future<bool> sweepFundsToNewWallet({ Future<Map<String, dynamic>> sweepFundsToNewWallet({
required Node node, required Node node,
required String address, required String address,
required String paymentId, required String paymentId,
@ -253,24 +253,24 @@ Future<bool> sweepFundsToNewWallet({
final rpcUri = node.isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path); final rpcUri = node.isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path);
final realm = 'monero-rpc'; final realm = 'monero-rpc';
final body = { final body = {
'method': 'sweep_all', "method": "sweep_all",
'params': { "jsonrpc": "2.0",
'address': address, "id": "0",
'account_index': accountIndex, "params": {
'subaddr_indices': subaddressIndices, "address": address,
'priority': priority, "account_index": accountIndex,
'ring_size': ringSize, "subaddr_indices": subaddressIndices,
'outputs': outputs, "priority": priority,
'unlock_time': unlockTime, "ring_size": ringSize,
'payment_id': paymentId, "outputs": outputs,
'get_tx_keys': getTxKeys, "unlock_time": unlockTime,
'below_amount': belowAmount, "payment_id": paymentId,
'do_not_relay': doNotRelay, "get_tx_keys": getTxKeys,
'get_tx_hex': getTxHex, "below_amount": belowAmount,
'get_tx_metadata': getTxMetadata, "do_not_relay": doNotRelay,
"get_tx_hex": getTxHex,
"get_tx_metadata": getTxMetadata,
}, },
'jsonrpc': '2.0',
'id': '0'
}; };
try { try {
@ -291,11 +291,12 @@ Future<bool> sweepFundsToNewWallet({
); );
client.close(); client.close();
final resBody = json.decode(response.body) as Map<String, dynamic>; final resBody = json.decode(response.body) as Map<String, dynamic>;
return !(resBody['result']['offline'] as bool);
} catch (_) { return resBody;
return false; } catch (e) {
print(e);
throw Exception(e);
} }
} }

View file

@ -50,10 +50,8 @@ class MoneroRestoreWalletFromKeysCredentials extends WalletCredentials {
final String spendKey; final String spendKey;
} }
class MoneroWalletService extends WalletService< class MoneroWalletService extends WalletService<MoneroNewWalletCredentials,
MoneroNewWalletCredentials, MoneroRestoreWalletFromSeedCredentials, MoneroRestoreWalletFromKeysCredentials> {
MoneroRestoreWalletFromSeedCredentials,
MoneroRestoreWalletFromKeysCredentials> {
MoneroWalletService(this.walletInfoSource); MoneroWalletService(this.walletInfoSource);
final Box<WalletInfo> walletInfoSource; final Box<WalletInfo> walletInfoSource;
@ -69,9 +67,7 @@ class MoneroWalletService extends WalletService<
try { try {
final path = await pathForWallet(name: credentials.name, type: getType()); final path = await pathForWallet(name: credentials.name, type: getType());
await monero_wallet_manager.createWallet( await monero_wallet_manager.createWallet(
path: path, path: path, password: credentials.password!, language: credentials.language);
password: credentials.password!,
language: credentials.language);
final wallet = MoneroWallet(walletInfo: credentials.walletInfo!); final wallet = MoneroWallet(walletInfo: credentials.walletInfo!);
await wallet.init(); await wallet.init();
@ -104,10 +100,9 @@ class MoneroWalletService extends WalletService<
await repairOldAndroidWallet(name); await repairOldAndroidWallet(name);
} }
await monero_wallet_manager await monero_wallet_manager.openWalletAsync({'path': path, 'password': password});
.openWalletAsync({'path': path, 'password': password}); final walletInfo = walletInfoSource.values
final walletInfo = walletInfoSource.values.firstWhere( .firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
(info) => info.id == WalletBase.idFor(name, getType()));
final wallet = MoneroWallet(walletInfo: walletInfo); final wallet = MoneroWallet(walletInfo: walletInfo);
final isValid = wallet.walletAddresses.validate(); final isValid = wallet.walletAddresses.validate();
@ -125,11 +120,9 @@ class MoneroWalletService extends WalletService<
if ((e.toString().contains('bad_alloc') || if ((e.toString().contains('bad_alloc') ||
(e is WalletOpeningException && (e is WalletOpeningException &&
(e.message == 'std::bad_alloc' || (e.message == 'std::bad_alloc' || e.message.contains('bad_alloc')))) ||
e.message.contains('bad_alloc')))) ||
(e.toString().contains('does not correspond') || (e.toString().contains('does not correspond') ||
(e is WalletOpeningException && (e is WalletOpeningException && e.message.contains('does not correspond')))) {
e.message.contains('does not correspond')))) {
await restoreOrResetWalletFiles(name); await restoreOrResetWalletFiles(name);
return openWallet(name, password); return openWallet(name, password);
} }
@ -150,8 +143,7 @@ class MoneroWalletService extends WalletService<
} }
@override @override
Future<MoneroWallet> restoreFromKeys( Future<MoneroWallet> restoreFromKeys(MoneroRestoreWalletFromKeysCredentials credentials) async {
MoneroRestoreWalletFromKeysCredentials credentials) async {
try { try {
final path = await pathForWallet(name: credentials.name, type: getType()); final path = await pathForWallet(name: credentials.name, type: getType());
await monero_wallet_manager.restoreFromKeys( await monero_wallet_manager.restoreFromKeys(
@ -174,8 +166,7 @@ class MoneroWalletService extends WalletService<
} }
@override @override
Future<MoneroWallet> restoreFromSeed( Future<MoneroWallet> restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials) async {
MoneroRestoreWalletFromSeedCredentials credentials) async {
try { try {
final path = await pathForWallet(name: credentials.name, type: getType()); final path = await pathForWallet(name: credentials.name, type: getType());
await monero_wallet_manager.restoreFromSeed( await monero_wallet_manager.restoreFromSeed(
@ -193,36 +184,43 @@ class MoneroWalletService extends WalletService<
rethrow; rethrow;
} }
} }
@override @override
Future<void> sweepAllFunds(Node node, String address, String paymentId) async { Future<Map<String, dynamic>> sweepAllFunds(Node node, String address, String paymentId) async {
try { try {
await monero_wallet_manager.sweepFundsToNewWallet( final response = await monero_wallet_manager.sweepFundsToNewWallet(
node: node, node: node,
address: address, address: address,
paymentId: paymentId, paymentId: paymentId,
); );
if (response['error'] != null) {
throw Exception('${response['error']['message']}');
} else {
return response;
}
} catch (e) { } catch (e) {
// TODO: Implement Exception for wallet list service. // TODO: Implement Exception for wallet list service.
print('MoneroWalletsManager Error: $e'); print('MoneroWalletsManager Error: $e');
rethrow; rethrow;
} }
} }
Future<void> repairOldAndroidWallet(String name) async { Future<void> repairOldAndroidWallet(String name) async {
try { try {
if (!Platform.isAndroid) { if (!Platform.isAndroid) {
return; return;
} }
final oldAndroidWalletDirPath = final oldAndroidWalletDirPath = await outdatedAndroidPathForWalletDir(name: name);
await outdatedAndroidPathForWalletDir(name: name);
final dir = Directory(oldAndroidWalletDirPath); final dir = Directory(oldAndroidWalletDirPath);
if (!dir.existsSync()) { if (!dir.existsSync()) {
return; return;
} }
final newWalletDirPath = final newWalletDirPath = await pathForWalletDir(name: name, type: getType());
await pathForWalletDir(name: name, type: getType());
dir.listSync().forEach((f) { dir.listSync().forEach((f) {
final file = File(f.path); final file = File(f.path);

View file

@ -1,4 +1,5 @@
import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/di.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_info.dart';
import 'package:cake_wallet/entities/preferences_key.dart'; import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
@ -39,15 +40,11 @@ class WalletCreationService {
bool exists(String name) { bool exists(String name) {
final walletName = name.toLowerCase(); final walletName = name.toLowerCase();
return walletInfoSource return walletInfoSource.values.any((walletInfo) => walletInfo.name.toLowerCase() == walletName);
.values
.any((walletInfo) => walletInfo.name.toLowerCase() == walletName);
} }
bool typeExists(WalletType type) { bool typeExists(WalletType type) {
return walletInfoSource return walletInfoSource.values.any((walletInfo) => walletInfo.type == type);
.values
.any((walletInfo) => walletInfo.type == type);
} }
void checkIfExists(String name) { void checkIfExists(String name) {
@ -60,15 +57,12 @@ class WalletCreationService {
checkIfExists(credentials.name); checkIfExists(credentials.name);
final password = generateWalletPassword(); final password = generateWalletPassword();
credentials.password = password; credentials.password = password;
await keyService.saveWalletPassword( await keyService.saveWalletPassword(password: password, walletName: credentials.name);
password: password, walletName: credentials.name);
final wallet = await _service!.create(credentials); final wallet = await _service!.create(credentials);
if (wallet.type == WalletType.monero) { if (wallet.type == WalletType.monero) {
await sharedPreferences await sharedPreferences.setBool(
.setBool( PreferencesKey.moneroWalletUpdateV1Key(wallet.name), _isNewMoneroWalletPasswordUpdated);
PreferencesKey.moneroWalletUpdateV1Key(wallet.name),
_isNewMoneroWalletPasswordUpdated);
} }
return wallet; return wallet;
@ -78,15 +72,12 @@ class WalletCreationService {
checkIfExists(credentials.name); checkIfExists(credentials.name);
final password = generateWalletPassword(); final password = generateWalletPassword();
credentials.password = password; credentials.password = password;
await keyService.saveWalletPassword( await keyService.saveWalletPassword(password: password, walletName: credentials.name);
password: password, walletName: credentials.name);
final wallet = await _service!.restoreFromKeys(credentials); final wallet = await _service!.restoreFromKeys(credentials);
if (wallet.type == WalletType.monero) { if (wallet.type == WalletType.monero) {
await sharedPreferences await sharedPreferences.setBool(
.setBool( PreferencesKey.moneroWalletUpdateV1Key(wallet.name), _isNewMoneroWalletPasswordUpdated);
PreferencesKey.moneroWalletUpdateV1Key(wallet.name),
_isNewMoneroWalletPasswordUpdated);
} }
return wallet; return wallet;
@ -96,17 +87,19 @@ class WalletCreationService {
checkIfExists(credentials.name); checkIfExists(credentials.name);
final password = generateWalletPassword(); final password = generateWalletPassword();
credentials.password = password; credentials.password = password;
await keyService.saveWalletPassword( await keyService.saveWalletPassword(password: password, walletName: credentials.name);
password: password, walletName: credentials.name);
final wallet = await _service!.restoreFromSeed(credentials); final wallet = await _service!.restoreFromSeed(credentials);
if (wallet.type == WalletType.monero) { if (wallet.type == WalletType.monero) {
await sharedPreferences await sharedPreferences.setBool(
.setBool( PreferencesKey.moneroWalletUpdateV1Key(wallet.name), _isNewMoneroWalletPasswordUpdated);
PreferencesKey.moneroWalletUpdateV1Key(wallet.name),
_isNewMoneroWalletPasswordUpdated);
} }
return wallet; return wallet;
} }
Future<Map<String, dynamic>> sweepAllFunds(Node node, String address, String paymentId) async {
final result = await _service!.sweepAllFunds(node, address, paymentId);
return result;
}
} }

View file

@ -21,7 +21,6 @@ class RestoreOptionsPage extends BasePage {
@override @override
String get title => S.current.restore_restore_wallet; String get title => S.current.restore_restore_wallet;
final bool isNewInstall; final bool isNewInstall;
final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png'); final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png');
final imageBackup = Image.asset('assets/images/backup.png'); final imageBackup = Image.asset('assets/images/backup.png');
@ -38,8 +37,7 @@ class RestoreOptionsPage extends BasePage {
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
RestoreButton( RestoreButton(
onPressed: () => Navigator.pushNamed( onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletFromSeedKeys,
context, Routes.restoreWalletFromSeedKeys,
arguments: isNewInstall), arguments: isNewInstall),
image: imageSeedKeys, image: imageSeedKeys,
title: S.of(context).restore_title_from_seed_keys, title: S.of(context).restore_title_from_seed_keys,
@ -76,8 +74,9 @@ class RestoreOptionsPage extends BasePage {
getIt.get<WalletRestorationFromQRVM>(param1: restoreWallet.type); getIt.get<WalletRestorationFromQRVM>(param1: restoreWallet.type);
await restoreFromQRViewModel.create(restoreWallet: restoreWallet); await restoreFromQRViewModel.create(restoreWallet: restoreWallet);
if (restoreFromQRViewModel.state is FailureState) { if (restoreFromQRViewModel.state is FailureState) {
final errorState = restoreFromQRViewModel.state as FailureState;
_onWalletCreateFailure(context, _onWalletCreateFailure(context,
'Create wallet state: ${restoreFromQRViewModel.state.runtimeType.toString()}'); 'Create wallet state: ${errorState.error}');
} }
} catch (e) { } catch (e) {
_onWalletCreateFailure(context, e.toString()); _onWalletCreateFailure(context, e.toString());

View file

@ -25,8 +25,7 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
spendKey = '', spendKey = '',
wif = '', wif = '',
address = '', address = '',
super(appStore, walletInfoSource, walletCreationService, super(appStore, walletInfoSource, walletCreationService, type: type, isRecovery: true);
type: type, isRecovery: true);
@observable @observable
int height; int height;
@ -46,7 +45,8 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
bool get hasRestorationHeight => type == WalletType.monero; bool get hasRestorationHeight => type == WalletType.monero;
@override @override
WalletCredentials getCredentialsFromRestoredWallet(dynamic options, RestoredWallet restoreWallet) { WalletCredentials getCredentialsFromRestoredWallet(
dynamic options, RestoredWallet restoreWallet) {
final password = generateWalletPassword(); final password = generateWalletPassword();
switch (restoreWallet.restoreMode) { switch (restoreWallet.restoreMode) {
@ -69,6 +69,7 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
throw Exception('Unexpected type: ${restoreWallet.type.toString()}'); throw Exception('Unexpected type: ${restoreWallet.type.toString()}');
} }
case WalletRestoreMode.seed: case WalletRestoreMode.seed:
case WalletRestoreMode.txids:
switch (restoreWallet.type) { switch (restoreWallet.type) {
case WalletType.monero: case WalletType.monero:
return monero!.createMoneroRestoreWalletFromSeedCredentials( return monero!.createMoneroRestoreWalletFromSeedCredentials(
@ -83,30 +84,20 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
default: default:
throw Exception('Unexpected type: ${type.toString()}'); 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: default:
throw Exception('Unexpected type: ${type.toString()}'); throw Exception('Unexpected type: ${type.toString()}');
} }
} }
@override @override
Future<WalletBase> processFromRestoredWallet(WalletCredentials credentials, RestoredWallet restoreWallet) async { Future<WalletBase> processFromRestoredWallet(
WalletCredentials credentials, RestoredWallet restoreWallet) async {
try { try {
switch (restoreWallet.restoreMode) { switch (restoreWallet.restoreMode) {
case WalletRestoreMode.keys: case WalletRestoreMode.keys:
return walletCreationService.restoreFromKeys(credentials); return walletCreationService.restoreFromKeys(credentials);
case WalletRestoreMode.seed: case WalletRestoreMode.seed:
case WalletRestoreMode.txids:
return walletCreationService.restoreFromSeed(credentials); return walletCreationService.restoreFromSeed(credentials);
default: default:
throw Exception('Unexpected restore mode: ${restoreWallet.restoreMode.toString()}'); throw Exception('Unexpected restore mode: ${restoreWallet.restoreMode.toString()}');

View file

@ -53,12 +53,17 @@ class RestoredWallet {
} }
factory RestoredWallet.fromTxIds(Map<String, dynamic> json) { factory RestoredWallet.fromTxIds(Map<String, dynamic> json) {
final mnemonic_seed = json['mnemonic_seed'] as String?;
final seed = json['seed'] as String?;
return RestoredWallet( return RestoredWallet(
restoreMode: json['mode'] as WalletRestoreMode, restoreMode: json['mode'] as WalletRestoreMode,
type: json['type'] as WalletType, type: json['type'] as WalletType,
address: json['address'] as String?, address: json['address'] as String?,
txId: json['tx_payment_id'] as String, txId: json['txid'] as String,
txAmount: json['tx_amount'] 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?, txDescription: json['tx_description'] as String?,
recipientName: json['recipient_name'] as String?, recipientName: json['recipient_name'] as String?,
); );

View file

@ -125,11 +125,11 @@ class WalletRestoreFromQRCode {
static WalletRestoreMode getWalletRestoreMode(Map<String, dynamic> credentials) { static WalletRestoreMode getWalletRestoreMode(Map<String, dynamic> credentials) {
final type = credentials['type'] as WalletType; final type = credentials['type'] as WalletType;
if (credentials.containsKey('tx_payment_id')) { if (credentials.containsKey('txid')) {
final txIdValue = credentials['tx_payment_id'] as String? ?? ''; final txIdValue = credentials['txid'] as String? ?? '';
return txIdValue.isNotEmpty return txIdValue.isNotEmpty
? WalletRestoreMode.txids ? WalletRestoreMode.txids
: throw Exception('Unexpected restore mode: tx_payment_id is invalid'); : throw Exception('Unexpected restore mode: txid is invalid');
} }
if (credentials.containsKey('seed')) { if (credentials.containsKey('seed')) {

View file

@ -1,5 +1,8 @@
import 'package:cake_wallet/core/wallet_creation_service.dart'; import 'package:cake_wallet/core/wallet_creation_service.dart';
import 'package:cake_wallet/view_model/restore/restore_wallet.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:hive/hive.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:cake_wallet/core/execution_state.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:cw_core/wallet_type.dart';
import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/entities/generate_name.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'; part 'wallet_creation_vm.g.dart';
@ -33,20 +39,60 @@ abstract class WalletCreationVMBase with Store {
final Box<WalletInfo> _walletInfoSource; final Box<WalletInfo> _walletInfoSource;
final AppStore _appStore; final AppStore _appStore;
bool nameExists(String name) bool nameExists(String name) => walletCreationService.exists(name);
=> walletCreationService.exists(name);
bool typeExists(WalletType type) bool typeExists(WalletType type) => walletCreationService.typeExists(type);
=> walletCreationService.typeExists(type);
Future<void> create({dynamic options, RestoredWallet? restoreWallet}) async { Future<void> create({dynamic options, RestoredWallet? restoreWallet}) async {
final type = restoreWallet?.type ?? this.type; final type = restoreWallet?.type ?? this.type;
try { try {
//! Create a restoredWallet from the scanned wallet parameters
final restoredWallet =
await createNewWalletWithoutSwitching(options: options, restoreWallet: restoreWallet);
print('Restored Wallet Address ' + restoredWallet.walletAddresses.address);
//TODO Get transactions details to verify 10 confirmations
//! 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);
//! 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());
}
}
Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>>
createNewWalletWithoutSwitching(
{dynamic options, RestoredWallet? restoreWallet, bool regenerateName = false}) async {
state = IsExecutingState(); state = IsExecutingState();
if (name.isEmpty) { if (name.isEmpty) {
name = await generateName(); name = await generateName();
} }
if (regenerateName) {
name = await generateName();
}
walletCreationService.checkIfExists(name); walletCreationService.checkIfExists(name);
final dirPath = await pathForWalletDir(name: name, type: type); final dirPath = await pathForWalletDir(name: name, type: type);
final path = await pathForWallet(name: name, type: type); final path = await pathForWallet(name: name, type: type);
@ -63,34 +109,52 @@ abstract class WalletCreationVMBase with Store {
path: path, path: path,
dirPath: dirPath, dirPath: dirPath,
address: '', address: '',
showIntroCakePayCard: (!walletCreationService.typeExists(type)) && type != WalletType.haven); showIntroCakePayCard:
(!walletCreationService.typeExists(type)) && type != WalletType.haven);
credentials.walletInfo = walletInfo; credentials.walletInfo = walletInfo;
//! Restored
final wallet = restoreWallet != null final wallet = restoreWallet != null
? await processFromRestoredWallet(credentials, restoreWallet) ? await processFromRestoredWallet(credentials, restoreWallet)
: await process(credentials); : await process(credentials);
walletInfo.address = wallet.walletAddresses.address; walletInfo.address = wallet.walletAddresses.address;
await _walletInfoSource.add(walletInfo);
//---- Code to create new
//! Before we switch return wallet;
_appStore.changeCurrentWallet(wallet); }
_appStore.authenticationStore.allowed();
state = ExecutedSuccessfullyState(); Future<Map<String, dynamic>> sweepAllFundsToNewWallet(
} catch (e) { WalletType type, String address, String paymentId) async {
state = FailureState(e.toString()); 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()}');
} }
} }
WalletCredentials getCredentials(dynamic options) =>
Future<WalletBase> process(WalletCredentials credentials) {
walletCreationService.changeWalletType(type: type);
return walletCreationService.create(credentials);
}
WalletCredentials getCredentialsFromRestoredWallet(
dynamic options, RestoredWallet restoreWallet) =>
throw UnimplementedError(); throw UnimplementedError();
Future<WalletBase> process(WalletCredentials credentials) => Future<WalletBase> processFromRestoredWallet(
throw UnimplementedError(); WalletCredentials credentials, RestoredWallet restoreWallet) =>
WalletCredentials getCredentialsFromRestoredWallet(dynamic options, RestoredWallet restoreWallet) =>
throw UnimplementedError();
Future<WalletBase> processFromRestoredWallet(WalletCredentials credentials, RestoredWallet restoreWallet) =>
throw UnimplementedError(); throw UnimplementedError();
} }

View file

@ -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:hive/hive.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/app_store.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
import 'package:cake_wallet/core/wallet_creation_service.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_info.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:cake_wallet/view_model/wallet_creation_vm.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/bitcoin/bitcoin.dart';
import 'package:cake_wallet/haven/haven.dart'; import 'package:cake_wallet/haven/haven.dart';
@ -43,7 +41,7 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
return haven!.createHavenNewWalletCredentials( return haven!.createHavenNewWalletCredentials(
name: name, language: options as String); name: name, language: options as String);
default: default:
throw Exception('Unexpected type: ${type.toString()}');; throw Exception('Unexpected type: ${type.toString()}');
} }
} }