mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-30 06:48:49 +01:00
TMP 4
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
|
||||
class AddressLabelValidator extends TextValidator {
|
||||
AddressLabelValidator({WalletType type})
|
||||
: super(
|
||||
errorMessage: S.current.error_text_subaddress_name,
|
||||
pattern: '''^[^`,'"]{1,20}\$''',
|
||||
minLength: 1,
|
||||
maxLength: 20);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
|
||||
class AmountValidator extends TextValidator {
|
||||
AmountValidator({WalletType type})
|
||||
: super(
|
||||
errorMessage: S.current.error_text_amount,
|
||||
pattern: _pattern(type),
|
||||
minLength: 0,
|
||||
maxLength: 0);
|
||||
|
||||
static String _pattern(WalletType type) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$';
|
||||
case WalletType.bitcoin:
|
||||
// FIXME: Incorrect pattern for bitcoin
|
||||
return '^([0-9]+([.][0-9]{0,12})?|[.][0-9]{1,12})\$';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/core/auth_service.dart';
|
||||
import 'package:cake_wallet/core/wallet_base.dart';
|
||||
import 'package:cake_wallet/core/wallet_creation_service.dart';
|
||||
|
||||
part 'app_service.g.dart';
|
||||
|
||||
class AppService = AppServiceBase with _$AppService;
|
||||
|
||||
abstract class AppServiceBase with Store {
|
||||
AppServiceBase({this.walletCreationService, this.authService, this.wallet});
|
||||
|
||||
WalletCreationService walletCreationService;
|
||||
AuthService authService;
|
||||
WalletBase wallet;
|
||||
}
|
||||
+33
-13
@@ -1,21 +1,41 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/core/setup_pin_code_state.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:cake_wallet/src/domain/common/secret_store_key.dart';
|
||||
import 'package:cake_wallet/src/domain/common/encrypt.dart';
|
||||
|
||||
part 'auth_service.g.dart';
|
||||
class AuthService with Store {
|
||||
AuthService({this.secureStorage, this.sharedPreferences});
|
||||
|
||||
class AuthService = AuthServiceBase with _$AuthService;
|
||||
final FlutterSecureStorage secureStorage;
|
||||
final SharedPreferences sharedPreferences;
|
||||
|
||||
abstract class AuthServiceBase with Store {
|
||||
@observable
|
||||
SetupPinCodeState setupPinCodeState;
|
||||
|
||||
Future<void> setupPinCode({@required String pin}) async {}
|
||||
|
||||
Future<bool> authenticate({@required String pin}) async {
|
||||
return false;
|
||||
Future setPassword(String password) async {
|
||||
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||
final encodedPassword = encodedPinCode(pin: password);
|
||||
await secureStorage.write(key: key, value: encodedPassword);
|
||||
}
|
||||
|
||||
void resetSetupPinCodeState() =>
|
||||
setupPinCodeState = InitialSetupPinCodeState();
|
||||
Future<bool> canAuthenticate() async {
|
||||
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||
final walletName = sharedPreferences.getString('current_wallet_name') ?? '';
|
||||
var password = '';
|
||||
|
||||
try {
|
||||
password = await secureStorage.read(key: key);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
|
||||
return walletName.isNotEmpty && password.isNotEmpty;
|
||||
}
|
||||
|
||||
Future<bool> authenticate(String pin) async {
|
||||
final key = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
|
||||
final encodedPin = await secureStorage.read(key: key);
|
||||
final decodedPin = decodedPinCode(pin: encodedPin);
|
||||
|
||||
return decodedPin == pin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
abstract class AuthState {}
|
||||
|
||||
class AuthenticationStateInitial extends AuthState {}
|
||||
|
||||
class AuthenticationInProgress extends AuthState {}
|
||||
|
||||
class AuthenticatedSuccessfully extends AuthState {}
|
||||
|
||||
class AuthenticationFailure extends AuthState {
|
||||
AuthenticationFailure({this.error});
|
||||
|
||||
final String error;
|
||||
}
|
||||
|
||||
class AuthenticationBanned extends AuthState {
|
||||
AuthenticationBanned({this.error});
|
||||
|
||||
final String error;
|
||||
}
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/core/transaction_history.dart';
|
||||
import 'package:cake_wallet/core/bitcoin_wallet.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart';
|
||||
import 'package:cake_wallet/bitcoin/electrum.dart';
|
||||
import 'package:cake_wallet/src/domain/common/transaction_info.dart';
|
||||
import 'package:cake_wallet/bitcoin/file.dart';
|
||||
|
||||
part 'bitcoin_transaction_history.g.dart';
|
||||
|
||||
// TODO: Think about another transaction store for bitcoin transaction history..
|
||||
|
||||
const _transactionsHistoryFileName = 'transactions.json';
|
||||
|
||||
class BitcoinTransactionHistory = BitcoinTransactionHistoryBase
|
||||
with _$BitcoinTransactionHistory;
|
||||
|
||||
abstract class BitcoinTransactionHistoryBase
|
||||
extends TranasctionHistoryBase<BitcoinTransactionInfo> with Store {
|
||||
BitcoinTransactionHistoryBase(
|
||||
{this.eclient, String dirPath, @required String password})
|
||||
: path = '$dirPath/$_transactionsHistoryFileName',
|
||||
_password = password,
|
||||
_height = 0;
|
||||
|
||||
BitcoinWallet wallet;
|
||||
final ElectrumClient eclient;
|
||||
final String path;
|
||||
final String _password;
|
||||
int _height;
|
||||
|
||||
Future<void> init() async {
|
||||
// TODO: throw exeption if wallet is null;
|
||||
final info = await _read();
|
||||
_height = (info['height'] as int) ?? _height;
|
||||
transactions = info['transactions'] as List<BitcoinTransactionInfo>;
|
||||
}
|
||||
|
||||
@override
|
||||
Future update() async {
|
||||
await super.update();
|
||||
_updateHeight();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<BitcoinTransactionInfo>> fetchTransactions() async {
|
||||
final addresses = wallet.getAddresses();
|
||||
final histories =
|
||||
addresses.map((address) => eclient.getHistory(address: address));
|
||||
final _historiesWithDetails = await Future.wait(histories)
|
||||
.then((histories) => histories
|
||||
.map((h) => h.where((tx) => (tx['height'] as int) > _height))
|
||||
.expand((i) => i)
|
||||
.toList())
|
||||
.then((histories) => histories.map((tx) => fetchTransactionInfo(
|
||||
hash: tx['tx_hash'] as String, height: tx['height'] as int)));
|
||||
final historiesWithDetails = await Future.wait(_historiesWithDetails);
|
||||
|
||||
return historiesWithDetails
|
||||
.map((info) => BitcoinTransactionInfo.fromHexAndHeader(
|
||||
info['raw'] as String, info['header'] as Map<String, Object>,
|
||||
addresses: addresses))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<Map<String, Object>> fetchTransactionInfo(
|
||||
{@required String hash, @required int height}) async {
|
||||
final rawFetching = eclient.getTransactionRaw(hash: hash);
|
||||
final headerFetching = eclient.getHeader(height: height);
|
||||
final result = await Future.wait([rawFetching, headerFetching]);
|
||||
final raw = result.first as String;
|
||||
final header = result[1] as Map<String, Object>;
|
||||
|
||||
return {'raw': raw, 'header': header};
|
||||
}
|
||||
|
||||
Future<void> add(List<BitcoinTransactionInfo> transactions) async {
|
||||
this.transactions.addAll(transactions);
|
||||
await save();
|
||||
}
|
||||
|
||||
Future<void> addOne(BitcoinTransactionInfo tx) async {
|
||||
transactions.add(tx);
|
||||
await save();
|
||||
}
|
||||
|
||||
Future<void> save() async => writeData(
|
||||
path: path,
|
||||
password: _password,
|
||||
data: json.encode({'height': _height, 'transactions': transactions}));
|
||||
|
||||
Future<Map<String, Object>> _read() async {
|
||||
try {
|
||||
final content = await read(path: path, password: _password);
|
||||
final jsoned = json.decode(content) as Map<String, Object>;
|
||||
final height = jsoned['height'] as int;
|
||||
final transactions = (jsoned['transactions'] as List<dynamic>)
|
||||
.map((dynamic row) {
|
||||
if (row is Map<String, Object>) {
|
||||
return BitcoinTransactionInfo.fromJson(row);
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.where((el) => el != null)
|
||||
.toList();
|
||||
|
||||
return {'transactions': transactions, 'height': height};
|
||||
} catch (_) {
|
||||
return {'transactions': <TransactionInfo>[], 'height': 0};
|
||||
}
|
||||
}
|
||||
|
||||
void _updateHeight() {
|
||||
final newHeight = transactions.fold(
|
||||
0, (int acc, val) => val.height > acc ? val.height : acc);
|
||||
_height = newHeight > _height ? newHeight : _height;
|
||||
}
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'package:cake_wallet/core/bitcoin_transaction_history.dart';
|
||||
import 'package:cake_wallet/core/transaction_history.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData;
|
||||
import 'package:cake_wallet/bitcoin/file.dart';
|
||||
import 'package:cake_wallet/src/domain/common/pathForWallet.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:cake_wallet/bitcoin/electrum.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_balance.dart';
|
||||
import 'package:cake_wallet/src/domain/common/node.dart';
|
||||
import 'wallet_base.dart';
|
||||
|
||||
part 'bitcoin_wallet.g.dart';
|
||||
|
||||
/* TODO: Save balance to a wallet file.
|
||||
Load balance from the wallet file in `init` method.
|
||||
*/
|
||||
|
||||
class BitcoinWallet = BitcoinWalletBase with _$BitcoinWallet;
|
||||
|
||||
abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
||||
static Future<BitcoinWalletBase> load(
|
||||
{@required String name, @required String password}) async {
|
||||
final walletDirPath =
|
||||
await pathForWalletDir(name: name, type: WalletType.bitcoin);
|
||||
final walletPath = '$walletDirPath/$name';
|
||||
final walletJSONRaw = await read(path: walletPath, password: password);
|
||||
final jsoned = json.decode(walletJSONRaw) as Map<String, Object>;
|
||||
final mnemonic = jsoned['mnemonic'] as String;
|
||||
final accountIndex =
|
||||
(jsoned['account_index'] == "null" || jsoned['account_index'] == null)
|
||||
? 0
|
||||
: int.parse(jsoned['account_index'] as String);
|
||||
|
||||
return BitcoinWalletBase.build(
|
||||
mnemonic: mnemonic,
|
||||
password: password,
|
||||
name: name,
|
||||
accountIndex: accountIndex);
|
||||
}
|
||||
|
||||
factory BitcoinWalletBase.build(
|
||||
{@required String mnemonic,
|
||||
@required String password,
|
||||
@required String name,
|
||||
@required String dirPath,
|
||||
int accountIndex = 0}) {
|
||||
final walletPath = '$dirPath/$name';
|
||||
final eclient = ElectrumClient();
|
||||
final history = BitcoinTransactionHistory(
|
||||
eclient: eclient, dirPath: dirPath, password: password);
|
||||
|
||||
return BitcoinWallet._internal(
|
||||
eclient: eclient,
|
||||
path: walletPath,
|
||||
mnemonic: mnemonic,
|
||||
password: password,
|
||||
accountIndex: accountIndex,
|
||||
transactionHistory: history);
|
||||
}
|
||||
|
||||
BitcoinWalletBase._internal(
|
||||
{@required this.eclient,
|
||||
@required this.path,
|
||||
@required String password,
|
||||
int accountIndex = 0,
|
||||
this.transactionHistory,
|
||||
this.mnemonic}) {
|
||||
hd = bitcoin.HDWallet.fromSeed(bip39.mnemonicToSeed(mnemonic),
|
||||
network: bitcoin.bitcoin);
|
||||
_password = password;
|
||||
_accountIndex = accountIndex;
|
||||
}
|
||||
|
||||
final BitcoinTransactionHistory transactionHistory;
|
||||
final String path;
|
||||
bitcoin.HDWallet hd;
|
||||
final ElectrumClient eclient;
|
||||
final String mnemonic;
|
||||
int _accountIndex;
|
||||
String _password;
|
||||
|
||||
@override
|
||||
String get name => path.split('/').last ?? '';
|
||||
|
||||
@override
|
||||
String get filename => hd.address;
|
||||
|
||||
String get xpub => hd.base58;
|
||||
|
||||
List<String> getAddresses() => _accountIndex == 0
|
||||
? [address]
|
||||
: List<String>.generate(
|
||||
_accountIndex, (i) => _getAddress(hd: hd, index: i));
|
||||
|
||||
Future<void> init() async {
|
||||
await transactionHistory.init();
|
||||
}
|
||||
|
||||
Future<String> newAddress() async {
|
||||
_accountIndex += 1;
|
||||
final address = _getAddress(hd: hd, index: _accountIndex);
|
||||
await save();
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startSync() async {}
|
||||
|
||||
@override
|
||||
Future<void> connectToNode({@required Node node}) async {}
|
||||
|
||||
@override
|
||||
Future<void> createTransaction(Object credentials) async {}
|
||||
|
||||
@override
|
||||
Future<void> save() async => await write(
|
||||
path: path,
|
||||
password: _password,
|
||||
obj: {'mnemonic': mnemonic, 'account_index': _accountIndex.toString()});
|
||||
|
||||
String _getAddress({bitcoin.HDWallet hd, int index}) => bitcoin
|
||||
.P2PKH(
|
||||
data: PaymentData(
|
||||
pubkey: Uint8List.fromList(hd.derive(index).pubKey.codeUnits)))
|
||||
.data
|
||||
.address;
|
||||
|
||||
Future<Map<String, int>> _fetchBalances() async {
|
||||
final balances = await Future.wait(
|
||||
getAddresses().map((address) => eclient.getBalance(address: address)));
|
||||
final balance = balances.fold(<String, int>{}, (Map<String, int> acc, val) {
|
||||
acc['confirmed'] =
|
||||
(val['confirmed'] as int ?? 0) + (acc['confirmed'] ?? 0);
|
||||
acc['unconfirmed'] =
|
||||
(val['unconfirmed'] as int ?? 0) + (acc['unconfirmed'] ?? 0);
|
||||
|
||||
return acc;
|
||||
});
|
||||
|
||||
return balance;
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
import 'dart:io';
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
|
||||
import 'package:cake_wallet/core/wallet_credentials.dart';
|
||||
import 'package:cake_wallet/core/wallet_list_service.dart';
|
||||
import 'package:cake_wallet/core/bitcoin_wallet.dart';
|
||||
import 'package:cake_wallet/src/domain/common/pathForWallet.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_description.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallets_manager.dart';
|
||||
/*
|
||||
*
|
||||
* BitcoinRestoreWalletFromSeedCredentials
|
||||
*
|
||||
* */
|
||||
|
||||
class BitcoinNewWalletCredentials extends WalletCredentials {}
|
||||
|
||||
/*
|
||||
*
|
||||
* BitcoinRestoreWalletFromSeedCredentials
|
||||
*
|
||||
* */
|
||||
|
||||
class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||
const BitcoinRestoreWalletFromSeedCredentials(
|
||||
{String name, String password, this.mnemonic})
|
||||
: super(name: name, password: password);
|
||||
|
||||
final String mnemonic;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* BitcoinRestoreWalletFromWIFCredentials
|
||||
*
|
||||
* */
|
||||
|
||||
class BitcoinRestoreWalletFromWIFCredentials extends WalletCredentials {
|
||||
const BitcoinRestoreWalletFromWIFCredentials(
|
||||
{String name, String password, this.wif})
|
||||
: super(name: name, password: password);
|
||||
|
||||
final String wif;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* BitcoinWalletListService
|
||||
*
|
||||
* */
|
||||
|
||||
class BitcoinWalletListService extends WalletListService<
|
||||
BitcoinNewWalletCredentials,
|
||||
BitcoinRestoreWalletFromSeedCredentials,
|
||||
BitcoinRestoreWalletFromWIFCredentials> {
|
||||
@override
|
||||
Future<void> create(BitcoinNewWalletCredentials credentials) async {
|
||||
final wallet = await BitcoinWalletBase.build(
|
||||
mnemonic: bip39.generateMnemonic(),
|
||||
password: credentials.password,
|
||||
name: credentials.name);
|
||||
await wallet.save();
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isWalletExit(String name) async =>
|
||||
File(await pathForWallet(name: name, type: WalletType.bitcoin))
|
||||
.existsSync();
|
||||
|
||||
@override
|
||||
Future<void> openWallet(String name, String password) async {
|
||||
// TODO: implement openWallet
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
Future<void> remove(String wallet) {
|
||||
// TODO: implement remove
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> restoreFromKeys(
|
||||
BitcoinRestoreWalletFromWIFCredentials credentials) async {
|
||||
// TODO: implement restoreFromKeys
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> restoreFromSeed(
|
||||
BitcoinRestoreWalletFromSeedCredentials credentials) async {
|
||||
final wallet = await BitcoinWalletBase.build(
|
||||
name: credentials.name,
|
||||
password: credentials.password,
|
||||
mnemonic: credentials.mnemonic);
|
||||
await wallet.save();
|
||||
|
||||
return wallet;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'package:cake_wallet/bitcoin/key.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
|
||||
String generateWalletPassword(WalletType type) {
|
||||
switch (type) {
|
||||
case WalletType.bitcoin:
|
||||
return generateKey();
|
||||
default:
|
||||
return Uuid().v4();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
|
||||
const bitcoinMnemonicLength = 12;
|
||||
const moneroMnemonicLength = 25;
|
||||
|
||||
int mnemonicLength(WalletType type) {
|
||||
// TODO: need to have only one place for get(set) mnemonic string lenth;
|
||||
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
return moneroMnemonicLength;
|
||||
case WalletType.bitcoin:
|
||||
return bitcoinMnemonicLength;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/monero_amount_format.dart';
|
||||
|
||||
class MoneroBalance {
|
||||
MoneroBalance({@required this.fullBalance, @required this.unlockedBalance})
|
||||
: formattedFullBalance = moneroAmountToString(amount: fullBalance),
|
||||
formattedUnlockedBalance =
|
||||
moneroAmountToString(amount: unlockedBalance);
|
||||
|
||||
MoneroBalance.fromString(
|
||||
{@required this.formattedFullBalance,
|
||||
@required this.formattedUnlockedBalance})
|
||||
: fullBalance = moneroParseAmount(amount: formattedFullBalance),
|
||||
unlockedBalance = moneroParseAmount(amount: formattedUnlockedBalance);
|
||||
|
||||
final int fullBalance;
|
||||
final int unlockedBalance;
|
||||
final String formattedFullBalance;
|
||||
final String formattedUnlockedBalance;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import 'dart:core';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_monero/transaction_history.dart'
|
||||
as monero_transaction_history;
|
||||
import 'package:cake_wallet/core/transaction_history.dart';
|
||||
import 'package:cake_wallet/src/domain/common/transaction_info.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/monero_transaction_info.dart';
|
||||
|
||||
part 'monero_transaction_history.g.dart';
|
||||
|
||||
List<TransactionInfo> _getAllTransactions(dynamic _) =>
|
||||
monero_transaction_history
|
||||
.getAllTransations()
|
||||
.map((row) => MoneroTransactionInfo.fromRow(row))
|
||||
.toList();
|
||||
|
||||
class MoneroTransactionHistory = MoneroTransactionHistoryBase
|
||||
with _$MoneroTransactionHistory;
|
||||
|
||||
abstract class MoneroTransactionHistoryBase
|
||||
extends TranasctionHistoryBase<TransactionInfo> with Store {
|
||||
@override
|
||||
Future<List<TransactionInfo>> fetchTransactions() async {
|
||||
monero_transaction_history.refreshTransactions();
|
||||
return _getAllTransactions(null);
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
import 'package:cake_wallet/core/monero_balance.dart';
|
||||
import 'package:cake_wallet/core/monero_transaction_history.dart';
|
||||
import 'package:cake_wallet/src/domain/common/sync_status.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/account.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/account_list.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/subaddress.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/subaddress_list.dart';
|
||||
import 'package:cw_monero/wallet.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/src/domain/common/node.dart';
|
||||
import 'package:cw_monero/wallet.dart' as monero_wallet;
|
||||
import 'wallet_base.dart';
|
||||
|
||||
part 'monero_wallet.g.dart';
|
||||
|
||||
class MoneroWallet = MoneroWalletBase with _$MoneroWallet;
|
||||
|
||||
abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
|
||||
MoneroWalletBase({String filename, this.isRecovery = false}) {
|
||||
transactionHistory = MoneroTransactionHistory();
|
||||
_filename = filename;
|
||||
accountList = AccountList();
|
||||
subaddressList = SubaddressList();
|
||||
balance = MoneroBalance(
|
||||
fullBalance: monero_wallet.getFullBalance(accountIndex: 0),
|
||||
unlockedBalance: monero_wallet.getFullBalance(accountIndex: 0));
|
||||
}
|
||||
|
||||
MoneroTransactionHistory transactionHistory;
|
||||
SubaddressList subaddressList;
|
||||
AccountList accountList;
|
||||
|
||||
@observable
|
||||
Account account;
|
||||
|
||||
@observable
|
||||
Subaddress subaddress;
|
||||
|
||||
@observable
|
||||
SyncStatus syncStatus;
|
||||
|
||||
@override
|
||||
String get name => filename.split('/').last;
|
||||
|
||||
@override
|
||||
String get filename => _filename;
|
||||
|
||||
String _filename;
|
||||
|
||||
bool isRecovery;
|
||||
|
||||
SyncListner _listner;
|
||||
|
||||
void init() {
|
||||
account = accountList.getAll().first;
|
||||
subaddressList.refresh(accountIndex: account.id ?? 0);
|
||||
subaddress = subaddressList.getAll().first;
|
||||
balance = MoneroBalance(
|
||||
fullBalance: monero_wallet.getFullBalance(accountIndex: account.id),
|
||||
unlockedBalance:
|
||||
monero_wallet.getFullBalance(accountIndex: account.id));
|
||||
_setListeners();
|
||||
}
|
||||
|
||||
void close() {
|
||||
_listner?.stop();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connectToNode({@required Node node}) async {
|
||||
try {
|
||||
syncStatus = ConnectingSyncStatus();
|
||||
await monero_wallet.setupNode(
|
||||
address: node.uri,
|
||||
login: node.login,
|
||||
password: node.password,
|
||||
useSSL: false,
|
||||
// FIXME: hardcoded value
|
||||
isLightWallet: false); // FIXME: hardcoded value
|
||||
syncStatus = ConnectedSyncStatus();
|
||||
} catch (e) {
|
||||
syncStatus = FailedSyncStatus();
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> startSync() async {
|
||||
try {
|
||||
syncStatus = StartingSyncStatus();
|
||||
monero_wallet.startRefresh();
|
||||
} catch (e) {
|
||||
syncStatus = FailedSyncStatus();
|
||||
print(e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> createTransaction(Object credentials) async {
|
||||
// final _credentials = credentials as MoneroTransactionCreationCredentials;
|
||||
// final transactionDescription = await transaction_history.createTransaction(
|
||||
// address: _credentials.address,
|
||||
// paymentId: _credentials.paymentId,
|
||||
// amount: _credentials.amount,
|
||||
// priorityRaw: _credentials.priority.serialize(),
|
||||
// accountIndex: _account.value.id);
|
||||
//
|
||||
// return PendingTransaction.fromTransactionDescription(
|
||||
// transactionDescription);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> save() async {
|
||||
// if (_isSaving) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
try {
|
||||
// _isSaving = true;
|
||||
await monero_wallet.store();
|
||||
// _isSaving = false;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
// _isSaving = false;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> getNodeHeight() async => monero_wallet.getNodeHeight();
|
||||
|
||||
Future<bool> isConnected() async => monero_wallet.isConnected();
|
||||
|
||||
void _setListeners() {
|
||||
_listner?.stop();
|
||||
_listner = monero_wallet.setListeners(
|
||||
_onNewBlock, _onNeedToRefresh, _onNewTransaction);
|
||||
}
|
||||
|
||||
void _askForUpdateBalance() {
|
||||
final fullBalance = _getFullBalance();
|
||||
final unlockedBalance = _getUnlockedBalance();
|
||||
|
||||
if (balance.fullBalance != fullBalance ||
|
||||
balance.unlockedBalance != unlockedBalance) {
|
||||
balance = MoneroBalance(
|
||||
fullBalance: fullBalance, unlockedBalance: unlockedBalance);
|
||||
}
|
||||
}
|
||||
|
||||
void _askForUpdateTransactionHistory() =>
|
||||
null; // await getHistory().update();
|
||||
|
||||
int _getFullBalance() =>
|
||||
monero_wallet.getFullBalance(accountIndex: account.id);
|
||||
|
||||
int _getUnlockedBalance() =>
|
||||
monero_wallet.getUnlockedBalance(accountIndex: account.id);
|
||||
|
||||
void _onNewBlock(int height, int blocksLeft, double ptc) =>
|
||||
syncStatus = SyncingSyncStatus(blocksLeft, ptc);
|
||||
|
||||
Future _onNeedToRefresh() async {
|
||||
if (syncStatus is FailedSyncStatus) {
|
||||
return;
|
||||
}
|
||||
|
||||
syncStatus = SyncedSyncStatus();
|
||||
|
||||
if (isRecovery) {
|
||||
_askForUpdateTransactionHistory();
|
||||
}
|
||||
|
||||
// if (isRecovery && (nodeHeight - currentHeight < moneroBlockSize)) {
|
||||
// await setAsRecovered();
|
||||
// }
|
||||
|
||||
await save();
|
||||
}
|
||||
|
||||
void _onNewTransaction() {
|
||||
_askForUpdateBalance();
|
||||
_askForUpdateTransactionHistory();
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
import 'package:cake_wallet/core/monero_wallet.dart';
|
||||
import 'package:cake_wallet/core/wallet_credentials.dart';
|
||||
import 'package:cake_wallet/core/wallet_list_service.dart';
|
||||
import 'package:cake_wallet/src/domain/common/pathForWallet.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:cw_monero/wallet_manager.dart' as monero_wallet_manager;
|
||||
import 'package:cw_monero/wallet.dart' as monero_wallet;
|
||||
|
||||
class MoneroNewWalletCredentials extends WalletCredentials {
|
||||
const MoneroNewWalletCredentials(
|
||||
{String name, String password, this.language})
|
||||
: super(name: name, password: password);
|
||||
|
||||
final String language;
|
||||
}
|
||||
|
||||
class MoneroRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||
const MoneroRestoreWalletFromSeedCredentials(
|
||||
{String name, String password, this.mnemonic, this.height})
|
||||
: super(name: name, password: password);
|
||||
|
||||
final String mnemonic;
|
||||
final int height;
|
||||
}
|
||||
|
||||
class MoneroRestoreWalletFromKeysCredentials extends WalletCredentials {
|
||||
const MoneroRestoreWalletFromKeysCredentials(
|
||||
{String name,
|
||||
String password,
|
||||
this.language,
|
||||
this.address,
|
||||
this.viewKey,
|
||||
this.spendKey,
|
||||
this.height})
|
||||
: super(name: name, password: password);
|
||||
|
||||
final String language;
|
||||
final String address;
|
||||
final String viewKey;
|
||||
final String spendKey;
|
||||
final int height;
|
||||
}
|
||||
|
||||
class MoneroWalletListService extends WalletListService<
|
||||
MoneroNewWalletCredentials,
|
||||
MoneroRestoreWalletFromSeedCredentials,
|
||||
MoneroRestoreWalletFromKeysCredentials> {
|
||||
@override
|
||||
Future<void> create(MoneroNewWalletCredentials credentials) async {
|
||||
try {
|
||||
final path =
|
||||
await pathForWallet(name: credentials.name, type: WalletType.monero);
|
||||
|
||||
await monero_wallet_manager.createWallet(
|
||||
path: path,
|
||||
password: credentials.password,
|
||||
language: credentials.language);
|
||||
|
||||
return MoneroWallet(filename: monero_wallet.getFilename())..init();
|
||||
} catch (e) {
|
||||
// TODO: Implement Exception fop wallet list service.
|
||||
print('MoneroWalletsManager Error: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isWalletExit(String name) async {
|
||||
try {
|
||||
final path = await pathForWallet(name: name, type: WalletType.monero);
|
||||
return monero_wallet_manager.isWalletExist(path: path);
|
||||
} catch (e) {
|
||||
// TODO: Implement Exception fop wallet list service.
|
||||
print('MoneroWalletsManager Error: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> openWallet(String name, String password) async {
|
||||
try {
|
||||
final path = await pathForWallet(name: name, type: WalletType.monero);
|
||||
monero_wallet_manager.openWallet(path: path, password: password);
|
||||
|
||||
// final id = walletTypeToString(WalletType.monero).toLowerCase() + '_' + name;
|
||||
// final walletInfo = walletInfoSource.values
|
||||
// .firstWhere((info) => info.id == id, orElse: () => null);
|
||||
|
||||
return MoneroWallet(filename: monero_wallet.getFilename())..init();
|
||||
} catch (e) {
|
||||
// TODO: Implement Exception fop wallet list service.
|
||||
print('MoneroWalletsManager Error: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> remove(String wallet) async {
|
||||
// TODO: implement remove
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> restoreFromKeys(
|
||||
MoneroRestoreWalletFromKeysCredentials credentials) async {
|
||||
try {
|
||||
final path =
|
||||
await pathForWallet(name: credentials.name, type: WalletType.monero);
|
||||
|
||||
await monero_wallet_manager.restoreFromKeys(
|
||||
path: path,
|
||||
password: credentials.password,
|
||||
language: credentials.language,
|
||||
restoreHeight: credentials.height,
|
||||
address: credentials.address,
|
||||
viewKey: credentials.viewKey,
|
||||
spendKey: credentials.spendKey);
|
||||
|
||||
return MoneroWallet(filename: monero_wallet.getFilename())..init();
|
||||
} catch (e) {
|
||||
// TODO: Implement Exception fop wallet list service.
|
||||
print('MoneroWalletsManager Error: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> restoreFromSeed(
|
||||
MoneroRestoreWalletFromSeedCredentials credentials) async {
|
||||
try {
|
||||
final path =
|
||||
await pathForWallet(name: credentials.name, type: WalletType.monero);
|
||||
|
||||
await monero_wallet_manager.restoreFromSeed(
|
||||
path: path,
|
||||
password: credentials.password,
|
||||
seed: credentials.mnemonic,
|
||||
restoreHeight: credentials.height);
|
||||
|
||||
return MoneroWallet(filename: monero_wallet.getFilename())..init();
|
||||
} catch (e) {
|
||||
// TODO: Implement Exception fop wallet list service.
|
||||
print('MoneroWalletsManager Error: $e');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import 'package:bip39/src/wordlists/english.dart' as bitcoin_english;
|
||||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/src/domain/common/mnemonic_item.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/chinese_simplified.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/dutch.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/english.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/german.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/japanese.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/portuguese.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/russian.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/mnemonics/spanish.dart';
|
||||
|
||||
class SeedValidator extends Validator<MnemonicItem> {
|
||||
SeedValidator({this.type, this.language})
|
||||
: _words = getWordList(type: type, language: language);
|
||||
|
||||
final WalletType type;
|
||||
final String language;
|
||||
final List<String> _words;
|
||||
|
||||
static List<String> getWordList({WalletType type, String language}) {
|
||||
switch (type) {
|
||||
case WalletType.bitcoin:
|
||||
return getBitcoinWordList(language);
|
||||
case WalletType.monero:
|
||||
return getMoneroWordList(language);
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
static List<String> getMoneroWordList(String language) {
|
||||
// FIXME: Unnamed constants; Need to be sure that string are in same case;
|
||||
|
||||
switch (language) {
|
||||
case 'English':
|
||||
return EnglishMnemonics.words;
|
||||
break;
|
||||
case 'Chinese (simplified)':
|
||||
return ChineseSimplifiedMnemonics.words;
|
||||
break;
|
||||
case 'Dutch':
|
||||
return DutchMnemonics.words;
|
||||
break;
|
||||
case 'German':
|
||||
return GermanMnemonics.words;
|
||||
break;
|
||||
case 'Japanese':
|
||||
return JapaneseMnemonics.words;
|
||||
break;
|
||||
case 'Portuguese':
|
||||
return PortugueseMnemonics.words;
|
||||
break;
|
||||
case 'Russian':
|
||||
return RussianMnemonics.words;
|
||||
break;
|
||||
case 'Spanish':
|
||||
return SpanishMnemonics.words;
|
||||
break;
|
||||
default:
|
||||
return EnglishMnemonics.words;
|
||||
}
|
||||
}
|
||||
|
||||
static List<String> getBitcoinWordList(String language) {
|
||||
assert(language.toLowerCase() == 'english');
|
||||
return bitcoin_english.WORDLIST;
|
||||
}
|
||||
|
||||
@override
|
||||
bool isValid(MnemonicItem value) => _words.contains(value.text);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
abstract class SetupPinCodeState {}
|
||||
|
||||
class InitialSetupPinCodeState extends SetupPinCodeState {}
|
||||
|
||||
class SetupPinCodeInProgress extends SetupPinCodeState {}
|
||||
|
||||
class SetupPinCodeFinishedSuccessfully extends SetupPinCodeState {}
|
||||
|
||||
class SetupPinCodeFinishedFailure extends SetupPinCodeState {
|
||||
SetupPinCodeFinishedFailure({@required this.error});
|
||||
|
||||
final String error;
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/src/domain/common/transaction_info.dart';
|
||||
|
||||
abstract class TranasctionHistoryBase<TransactionType> {
|
||||
TranasctionHistoryBase() : _isUpdating = false;
|
||||
abstract class TransactionHistoryBase<TransactionType extends TransactionInfo> {
|
||||
TransactionHistoryBase() : _isUpdating = false;
|
||||
|
||||
@observable
|
||||
List<TransactionType> transactions;
|
||||
ObservableList<TransactionType> transactions;
|
||||
|
||||
bool _isUpdating;
|
||||
|
||||
@@ -15,7 +16,7 @@ abstract class TranasctionHistoryBase<TransactionType> {
|
||||
|
||||
try {
|
||||
_isUpdating = false;
|
||||
transactions = await fetchTransactions();
|
||||
transactions.addAll(await fetchTransactions());
|
||||
_isUpdating = true;
|
||||
} catch (e) {
|
||||
_isUpdating = false;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
abstract class Validator<T> {
|
||||
Validator({@required this.errorMessage});
|
||||
|
||||
final String errorMessage;
|
||||
|
||||
bool isValid(T value);
|
||||
|
||||
String call(T value) => !isValid(value) ? errorMessage : null;
|
||||
}
|
||||
|
||||
class TextValidator extends Validator<String> {
|
||||
TextValidator(
|
||||
{this.minLength, this.maxLength, this.pattern, String errorMessage})
|
||||
: super(errorMessage: errorMessage);
|
||||
|
||||
final int minLength;
|
||||
final int maxLength;
|
||||
String pattern;
|
||||
|
||||
@override
|
||||
bool isValid(String value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return value.length > minLength &&
|
||||
(maxLength > 0 ? (value.length <= maxLength) : true) &&
|
||||
(pattern != null ? match(value) : true);
|
||||
}
|
||||
|
||||
bool match(String value) => RegExp(pattern).hasMatch(value);
|
||||
}
|
||||
|
||||
class WalletNameValidator extends TextValidator {
|
||||
WalletNameValidator()
|
||||
: super(minLength: 1, maxLength: 15, pattern: '^[a-zA-Z0-9_]\$');
|
||||
}
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/core/transaction_history.dart';
|
||||
import 'package:cake_wallet/src/domain/common/node.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
|
||||
abstract class WalletBase<BalaceType> {
|
||||
WalletType type;
|
||||
|
||||
String get name;
|
||||
|
||||
String get filename;
|
||||
|
||||
@observable
|
||||
String address;
|
||||
|
||||
@observable
|
||||
BalaceType balance;
|
||||
|
||||
TransactionHistoryBase transactionHistory;
|
||||
|
||||
Future<void> connectToNode({@required Node node});
|
||||
|
||||
Future<void> startSync();
|
||||
|
||||
Future<void> createTransaction(Object credentials);
|
||||
|
||||
Future<void> save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,47 @@
|
||||
import 'package:cake_wallet/core/wallet_creation_state.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:cake_wallet/core/generate_wallet_password.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/core/wallet_credentials.dart';
|
||||
import 'package:cake_wallet/core/bitcoin_wallet_list_service.dart';
|
||||
import 'package:cake_wallet/core/monero_wallet_list_service.dart';
|
||||
import 'package:cake_wallet/core/wallet_list_service.dart';
|
||||
import 'package:cake_wallet/bitcoin/bitcoin_wallet_service.dart';
|
||||
import 'package:cake_wallet/monero/monero_wallet_service.dart';
|
||||
import 'package:cake_wallet/core/wallet_service.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:cake_wallet/src/domain/common/secret_store_key.dart';
|
||||
import 'package:cake_wallet/src/domain/common/encrypt.dart';
|
||||
|
||||
part 'wallet_creation_service.g.dart';
|
||||
|
||||
class WalletCreationService = WalletCreationServiceBase
|
||||
with _$WalletCreationService;
|
||||
|
||||
abstract class WalletCreationServiceBase with Store {
|
||||
@observable
|
||||
WalletCreationState state;
|
||||
class WalletCreationService {
|
||||
WalletCreationService(
|
||||
{WalletType initialType,
|
||||
this.appStore,
|
||||
this.secureStorage,
|
||||
this.sharedPreferences})
|
||||
: type = initialType {
|
||||
if (type != null) {
|
||||
changeWalletType(type: type);
|
||||
}
|
||||
}
|
||||
|
||||
WalletType type;
|
||||
final AppStore appStore;
|
||||
final FlutterSecureStorage secureStorage;
|
||||
final SharedPreferences sharedPreferences;
|
||||
|
||||
WalletListService _service;
|
||||
// final WalletService walletService;
|
||||
// final Box<WalletInfo> walletInfoSource;
|
||||
|
||||
WalletService _service;
|
||||
|
||||
void changeWalletType({@required WalletType type}) {
|
||||
this.type = type;
|
||||
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
_service = MoneroWalletListService();
|
||||
_service = MoneroWalletService();
|
||||
break;
|
||||
case WalletType.bitcoin:
|
||||
_service = BitcoinWalletListService();
|
||||
_service = BitcoinWalletService();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -36,32 +49,45 @@ abstract class WalletCreationServiceBase with Store {
|
||||
}
|
||||
|
||||
Future<void> create(WalletCredentials credentials) async {
|
||||
try {
|
||||
state = WalletCreating();
|
||||
await _service.create(credentials);
|
||||
state = WalletCreatedSuccessfully();
|
||||
} catch (e) {
|
||||
state = WalletCreationFailure(error: e.toString());
|
||||
}
|
||||
final password = generateWalletPassword(type);
|
||||
credentials.password = password;
|
||||
await saveWalletPassword(password: password, walletName: credentials.name);
|
||||
final wallet = await _service.create(credentials);
|
||||
appStore.wallet = wallet;
|
||||
appStore.authenticationStore.allowed();
|
||||
}
|
||||
|
||||
Future<void> restoreFromKeys(WalletCredentials credentials) async {
|
||||
try {
|
||||
state = WalletCreating();
|
||||
await _service.restoreFromKeys(credentials);
|
||||
state = WalletCreatedSuccessfully();
|
||||
} catch (e) {
|
||||
state = WalletCreationFailure(error: e.toString());
|
||||
}
|
||||
final password = generateWalletPassword(type);
|
||||
credentials.password = password;
|
||||
await saveWalletPassword(password: password, walletName: credentials.name);
|
||||
final wallet = await _service.restoreFromKeys(credentials);
|
||||
appStore.wallet = wallet;
|
||||
appStore.authenticationStore.allowed();
|
||||
}
|
||||
|
||||
Future<void> restoreFromSeed(WalletCredentials credentials) async {
|
||||
try {
|
||||
state = WalletCreating();
|
||||
await _service.restoreFromSeed(credentials);
|
||||
state = WalletCreatedSuccessfully();
|
||||
} catch (e) {
|
||||
state = WalletCreationFailure(error: e.toString());
|
||||
}
|
||||
final password = generateWalletPassword(type);
|
||||
credentials.password = password;
|
||||
await saveWalletPassword(password: password, walletName: credentials.name);
|
||||
final wallet = await _service.restoreFromSeed(credentials);
|
||||
appStore.wallet = wallet;
|
||||
appStore.authenticationStore.allowed();
|
||||
}
|
||||
|
||||
Future<String> getWalletPassword({String walletName}) async {
|
||||
final key = generateStoreKeyFor(
|
||||
key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
|
||||
final encodedPassword = await secureStorage.read(key: key);
|
||||
|
||||
return decodeWalletPassword(password: encodedPassword);
|
||||
}
|
||||
|
||||
Future<void> saveWalletPassword({String walletName, String password}) async {
|
||||
final key = generateStoreKeyFor(
|
||||
key: SecretStoreKey.moneroWalletPassword, walletName: walletName);
|
||||
final encodedPassword = encodeWalletPassword(password: password);
|
||||
|
||||
await secureStorage.write(key: key, value: encodedPassword);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
abstract class WalletCredentials {
|
||||
const WalletCredentials({this.name, this.password});
|
||||
WalletCredentials({this.name, this.password});
|
||||
|
||||
final String name;
|
||||
final String password;
|
||||
String password;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import 'package:cake_wallet/core/wallet_credentials.dart';
|
||||
|
||||
abstract class WalletListService<N extends WalletCredentials,
|
||||
RFS extends WalletCredentials, RFK extends WalletCredentials> {
|
||||
Future<void> create(N credentials);
|
||||
|
||||
Future<void> restoreFromSeed(RFS credentials);
|
||||
|
||||
Future<void> restoreFromKeys(RFK credentials);
|
||||
|
||||
Future<void> openWallet(String name, String password);
|
||||
|
||||
Future<bool> isWalletExit(String name);
|
||||
|
||||
Future<void> remove(String wallet);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:cake_wallet/core/wallet_base.dart';
|
||||
import 'package:cake_wallet/core/wallet_credentials.dart';
|
||||
|
||||
abstract class WalletService<N extends WalletCredentials,
|
||||
RFS extends WalletCredentials, RFK extends WalletCredentials> {
|
||||
Future<WalletBase> create(N credentials);
|
||||
|
||||
Future<WalletBase> restoreFromSeed(RFS credentials);
|
||||
|
||||
Future<WalletBase> restoreFromKeys(RFK credentials);
|
||||
|
||||
Future<WalletBase> openWallet(String name, String password);
|
||||
|
||||
Future<bool> isWalletExit(String name);
|
||||
|
||||
Future<void> remove(String wallet);
|
||||
}
|
||||
Reference in New Issue
Block a user