mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-25 21:19:37 +00:00
Finished setup and initiated initial testing WIP [skip ci]
This commit is contained in:
parent
8c609f09a1
commit
b7d9bf8746
14 changed files with 215 additions and 176 deletions
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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');
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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()}');
|
||||||
|
|
|
@ -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?,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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')) {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue