parent
b605a98811
commit
957ca8cd58
@ -0,0 +1,21 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/core/setup_pin_code_state.dart';
|
||||
|
||||
part 'auth_service.g.dart';
|
||||
|
||||
class AuthService = AuthServiceBase with _$AuthService;
|
||||
|
||||
abstract class AuthServiceBase with Store {
|
||||
@observable
|
||||
SetupPinCodeState setupPinCodeState;
|
||||
|
||||
Future<void> setupPinCode({@required String pin}) async {}
|
||||
|
||||
Future<bool> authenticate({@required String pin}) async {
|
||||
return false;
|
||||
}
|
||||
|
||||
void resetSetupPinCodeState() =>
|
||||
setupPinCodeState = InitialSetupPinCodeState();
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
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;
|
||||
}
|
||||
}
|
@ -0,0 +1,149 @@
|
||||
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<BitcoinWallet> 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 BitcoinWallet.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;
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
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,20 @@
|
||||
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;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
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);
|
||||
}
|
||||
}
|
@ -0,0 +1,186 @@
|
||||
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();
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'package:cake_wallet/src/domain/common/node.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/account.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/monero_wallet.dart';
|
||||
import 'package:cake_wallet/src/domain/monero/subaddress.dart';
|
||||
import 'package:cake_wallet/src/domain/services/wallet_service.dart';
|
||||
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
|
||||
import 'package:cake_wallet/src/stores/settings/settings_store.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
part 'monero_wallet_store.g.dart';
|
||||
|
||||
class MoneroWalletStore = MoneroWalletStoreBase with _$MoneroWalletStore;
|
||||
|
||||
abstract class MoneroWalletStoreBase with Store {
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
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,12 +0,0 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||
|
||||
part 'sign_up_store.g.dart';
|
||||
|
||||
class SignUpStore = SignUpStoreBase with _$SignUpStore;
|
||||
|
||||
|
||||
abstract class SignUpStoreBase with Store {
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
abstract class TranasctionHistoryBase<TransactionType> {
|
||||
TranasctionHistoryBase() : _isUpdating = false;
|
||||
|
||||
@observable
|
||||
List<TransactionType> transactions;
|
||||
|
||||
bool _isUpdating;
|
||||
|
||||
Future<void> update() async {
|
||||
if (_isUpdating) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_isUpdating = false;
|
||||
transactions = await fetchTransactions();
|
||||
_isUpdating = true;
|
||||
} catch (e) {
|
||||
_isUpdating = false;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<TransactionType>> fetchTransactions();
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/src/domain/common/node.dart';
|
||||
|
||||
abstract class WalletBase<BalaceType> {
|
||||
String get name;
|
||||
|
||||
String get filename;
|
||||
|
||||
@observable
|
||||
String address;
|
||||
|
||||
@observable
|
||||
BalaceType balance;
|
||||
|
||||
Future<void> connectToNode({@required Node node});
|
||||
Future<void> startSync();
|
||||
Future<void> createTransaction(Object credentials);
|
||||
Future<void> save();
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
import 'package:cake_wallet/core/wallet_creation_state.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:mobx/mobx.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/src/domain/common/wallet_type.dart';
|
||||
|
||||
part 'wallet_creation_service.g.dart';
|
||||
|
||||
class WalletCreationService = WalletCreationServiceBase
|
||||
with _$WalletCreationService;
|
||||
|
||||
abstract class WalletCreationServiceBase with Store {
|
||||
@observable
|
||||
WalletCreationState state;
|
||||
|
||||
WalletListService _service;
|
||||
|
||||
void changeWalletType({@required WalletType type}) {
|
||||
switch (type) {
|
||||
case WalletType.monero:
|
||||
_service = MoneroWalletListService();
|
||||
break;
|
||||
case WalletType.bitcoin:
|
||||
_service = BitcoinWalletListService();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> create(WalletCredentials credentials) async {
|
||||
try {
|
||||
state = WalletCreating();
|
||||
await _service.create(credentials);
|
||||
state = WalletCreatedSuccessfully();
|
||||
} catch (e) {
|
||||
state = WalletCreationFailure(error: e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> restoreFromKeys(WalletCredentials credentials) async {
|
||||
try {
|
||||
state = WalletCreating();
|
||||
await _service.restoreFromKeys(credentials);
|
||||
state = WalletCreatedSuccessfully();
|
||||
} catch (e) {
|
||||
state = WalletCreationFailure(error: e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> restoreFromSeed(WalletCredentials credentials) async {
|
||||
try {
|
||||
state = WalletCreating();
|
||||
await _service.restoreFromSeed(credentials);
|
||||
state = WalletCreatedSuccessfully();
|
||||
} catch (e) {
|
||||
state = WalletCreationFailure(error: e.toString());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
abstract class WalletCreationState {}
|
||||
|
||||
class WalletCreating extends WalletCreationState {}
|
||||
|
||||
class WalletCreatedSuccessfully extends WalletCreationState {}
|
||||
|
||||
class WalletCreationFailure extends WalletCreationState {
|
||||
WalletCreationFailure({@required this.error});
|
||||
|
||||
final String error;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
abstract class WalletCredentials {
|
||||
const WalletCredentials({this.name, this.password});
|
||||
|
||||
final String name;
|
||||
final String password;
|
||||
}
|
Loading…
Reference in new issue