Merge redesign part 7.

This commit is contained in:
M 2020-09-15 23:35:49 +03:00
parent d67ab4934d
commit 95917b2cdb
31 changed files with 373 additions and 267 deletions

View file

@ -1,5 +1,3 @@
include: package:pedantic/analysis_options.yaml
analyzer:
strong-mode:
implicit-casts: false

View file

@ -180,7 +180,7 @@ extern "C"
void change_current_wallet(Monero::Wallet *wallet)
{
m_wallet = wallet;
// m_listener = nullptr;
m_listener = nullptr;
if (wallet != nullptr)
@ -553,7 +553,7 @@ extern "C"
if (m_listener != nullptr)
{
free(m_listener);
// free(m_listener);
}
m_listener = new MoneroWalletListener();

View file

@ -254,12 +254,12 @@ class SyncListner {
onNewBlock(syncHeight, left, ptc);
}
if (newTransactionExist && onNewTransaction != null) {
onNewTransaction();
if (newTransactionExist) {
onNewTransaction?.call();
}
if (needToRefresh && onNeedToRefresh != null) {
onNeedToRefresh();
if (needToRefresh) {
onNeedToRefresh?.call();
}
});
}

View file

@ -3,6 +3,13 @@ PODS:
- Flutter
- MTBBarcodeScanner
- SwiftProtobuf
- connectivity (0.0.1):
- Flutter
- Reachability
- connectivity_for_web (0.1.0):
- Flutter
- connectivity_macos (0.0.1):
- Flutter
- cw_monero (0.0.2):
- cw_monero/Boost (= 0.0.2)
- cw_monero/lmdb (= 0.0.2)
@ -40,6 +47,7 @@ PODS:
- Flutter
- path_provider_macos (0.0.1):
- Flutter
- Reachability (3.2)
- share (0.0.1):
- Flutter
- shared_preferences (0.0.1):
@ -62,6 +70,9 @@ PODS:
DEPENDENCIES:
- barcode_scan (from `.symlinks/plugins/barcode_scan/ios`)
- connectivity (from `.symlinks/plugins/connectivity/ios`)
- connectivity_for_web (from `.symlinks/plugins/connectivity_for_web/ios`)
- connectivity_macos (from `.symlinks/plugins/connectivity_macos/ios`)
- cw_monero (from `.symlinks/plugins/cw_monero/ios`)
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
- esys_flutter_share (from `.symlinks/plugins/esys_flutter_share/ios`)
@ -86,11 +97,18 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- MTBBarcodeScanner
- Reachability
- SwiftProtobuf
EXTERNAL SOURCES:
barcode_scan:
:path: ".symlinks/plugins/barcode_scan/ios"
connectivity:
:path: ".symlinks/plugins/connectivity/ios"
connectivity_for_web:
:path: ".symlinks/plugins/connectivity_for_web/ios"
connectivity_macos:
:path: ".symlinks/plugins/connectivity_macos/ios"
cw_monero:
:path: ".symlinks/plugins/cw_monero/ios"
devicelocale:
@ -134,6 +152,9 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
barcode_scan: a5c27959edfafaa0c771905bad0b29d6d39e4479
connectivity: c4130b2985d4ef6fd26f9702e886bd5260681467
connectivity_for_web: 2b8584556930d4bd490d82b836bcf45067ce345b
connectivity_macos: e2e9731b6b22dda39eb1b128f6969d574460e191
cw_monero: 2e1f79929880cc2293b5bc1b25e28152e4d84649
devicelocale: feebbe5e7a30adb8c4f83185de1b50ff19b44f00
esys_flutter_share: 403498dab005b36ce1f8d7aff377e81f0621b0b4
@ -146,6 +167,7 @@ SPEC CHECKSUMS:
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
path_provider_linux: 4d630dc393e1f20364f3e3b4a2ff41d9674a84e4
path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
share: 0b2c3e82132f5888bccca3351c504d0003b3b410
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
shared_preferences_linux: afefbfe8d921e207f01ede8b60373d9e3b566b78

View file

@ -275,8 +275,10 @@
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${PODS_ROOT}/../Flutter/Flutter.framework",
"${BUILT_PRODUCTS_DIR}/MTBBarcodeScanner/MTBBarcodeScanner.framework",
"${BUILT_PRODUCTS_DIR}/Reachability/Reachability.framework",
"${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework",
"${BUILT_PRODUCTS_DIR}/barcode_scan/barcode_scan.framework",
"${BUILT_PRODUCTS_DIR}/connectivity/connectivity.framework",
"${BUILT_PRODUCTS_DIR}/cw_monero/cw_monero.framework",
"${BUILT_PRODUCTS_DIR}/devicelocale/devicelocale.framework",
"${BUILT_PRODUCTS_DIR}/esys_flutter_share/esys_flutter_share.framework",
@ -293,8 +295,10 @@
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MTBBarcodeScanner.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reachability.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/barcode_scan.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cw_monero.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/devicelocale.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/esys_flutter_share.framework",

View file

@ -9,8 +9,6 @@ import 'package:cake_wallet/bitcoin/electrum.dart';
part 'bitcoin_transaction_history.g.dart';
// TODO: Think about another transaction store for bitcoin transaction history..
const _transactionsHistoryFileName = 'transactions.json';
class BitcoinTransactionHistory = BitcoinTransactionHistoryBase

View file

@ -1,39 +1,29 @@
import 'dart:async';
import 'dart:typed_data';
import 'dart:convert';
import 'package:mobx/mobx.dart';
import 'package:bip39/bip39.dart' as bip39;
import 'package:flutter/foundation.dart';
import 'package:rxdart/rxdart.dart';
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
import 'package:cake_wallet/bitcoin/bitcoin_transaction_credentials.dart';
import 'package:cake_wallet/bitcoin/bitcoin_transaction_info.dart';
import 'package:cake_wallet/bitcoin/bitcoin_transaction_no_inputs_exception.dart';
import 'package:cake_wallet/bitcoin/bitcoin_transaction_wrong_balance_exception.dart';
import 'package:cake_wallet/bitcoin/bitcoin_unspent.dart';
import 'package:cake_wallet/bitcoin/bitcoin_wallet_keys.dart';
import 'package:cake_wallet/bitcoin/electrum.dart';
import 'package:cake_wallet/bitcoin/pending_bitcoin_transaction.dart';
import 'package:cake_wallet/bitcoin/script_hash.dart';
import 'package:cake_wallet/bitcoin/utils.dart';
import 'package:cake_wallet/src/domain/bitcoin/bitcoin_amount_format.dart';
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
import 'package:cake_wallet/src/domain/common/sync_status.dart';
import 'package:cake_wallet/src/domain/common/transaction_direction.dart';
import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
import 'package:cw_monero/transaction_history.dart';
import 'package:flutter/cupertino.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/src/domain/common/wallet_type.dart';
import 'package:cake_wallet/src/domain/common/wallet_info.dart';
import 'package:cake_wallet/bitcoin/bitcoin_transaction_history.dart';
import 'package:cake_wallet/bitcoin/bitcoin_address_record.dart';
import 'package:cake_wallet/bitcoin/file.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 'package:cake_wallet/core/wallet_base.dart';
import 'package:rxdart/rxdart.dart';
import 'package:hex/hex.dart';
import 'package:cake_wallet/di.dart';
import 'package:shared_preferences/shared_preferences.dart';
part 'bitcoin_wallet.g.dart';
@ -44,8 +34,8 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
{@required this.eclient,
@required this.path,
@required String password,
@required this.name,
List<BitcoinAddressRecord> initialAddresses,
@required WalletInfo walletInfo,
@required List<BitcoinAddressRecord> initialAddresses,
int accountIndex = 0,
this.transactionHistory,
this.mnemonic,
@ -60,9 +50,7 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
syncStatus = NotConnectedSyncStatus(),
_password = password,
_accountIndex = accountIndex,
_addressesKeys = {} {
type = WalletType.bitcoin;
currency = CryptoCurrency.btc;
super(walletInfo) {
_scripthashesUpdateSubject = {};
}
@ -114,7 +102,6 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
return BitcoinWallet._internal(
eclient: eclient,
path: walletPath,
name: name,
mnemonic: mnemonic,
password: password,
accountIndex: accountIndex,
@ -130,9 +117,6 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
final ElectrumClient eclient;
final String mnemonic;
@override
String name;
@override
@observable
String address;
@ -147,8 +131,6 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
ObservableList<BitcoinAddressRecord> addresses;
Map<String, bitcoin.ECPair> _addressesKeys;
List<String> get scriptHashes =>
addresses.map((addr) => scriptHash(addr.address)).toList();
@ -161,8 +143,8 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
BitcoinWalletKeys get keys => BitcoinWalletKeys(
wif: hd.wif, privateKey: hd.privKey, publicKey: hd.pubKey);
final String _password;
int _accountIndex;
String _password;
Map<String, BehaviorSubject<Object>> _scripthashesUpdateSubject;
Future<void> init() async {

View file

@ -1,5 +1,4 @@
import 'dart:io';
import 'dart:convert';
import 'package:cake_wallet/bitcoin/key.dart';
import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:flutter/foundation.dart';
@ -28,8 +27,7 @@ Future<void> writeData(
f.writeAsStringSync(encrypted);
}
Future<String> read(
{@required String path, @required String password}) async {
Future<String> read({@required String path, @required String password}) async {
final file = File(path);
if (!file.existsSync()) {

View file

@ -1,4 +1,3 @@
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';

View file

@ -1,4 +1,5 @@
import 'package:flutter/foundation.dart';
import 'package:cake_wallet/src/domain/common/wallet_info.dart';
import 'package:cake_wallet/core/pending_transaction.dart';
import 'package:cake_wallet/core/transaction_history.dart';
import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
@ -7,18 +8,43 @@ import 'package:cake_wallet/src/domain/common/sync_status.dart';
import 'package:cake_wallet/src/domain/common/node.dart';
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
// FIXME: Move me.
CryptoCurrency currencyForWalletType(WalletType type) {
switch (type) {
case WalletType.bitcoin:
return CryptoCurrency.btc;
case WalletType.monero:
return CryptoCurrency.xmr;
default:
return null;
}
}
abstract class WalletBase<BalaceType> {
WalletType type;
WalletBase(this.walletInfo);
CryptoCurrency currency;
static String idFor(String name, WalletType type) =>
walletTypeToString(type).toLowerCase() + '_' + name;
String get name;
WalletInfo walletInfo;
String address;
WalletType get type => walletInfo.type;
BalaceType balance;
CryptoCurrency get currency => currencyForWalletType(type);
SyncStatus syncStatus;
String get id => walletInfo.id;
String get name => walletInfo.name;
String get address;
set address(String address);
BalaceType get balance;
SyncStatus get syncStatus;
set syncStatus(SyncStatus status);
String get seed;
@ -26,8 +52,6 @@ abstract class WalletBase<BalaceType> {
TransactionHistoryBase transactionHistory;
String get id => walletTypeToString(type).toLowerCase() + '_' + name;
Future<void> connectToNode({@required Node node});
Future<void> startSync();

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/di.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:shared_preferences/shared_preferences.dart';
@ -32,17 +33,7 @@ class WalletCreationService {
void changeWalletType({@required WalletType type}) {
this.type = type;
switch (type) {
case WalletType.monero:
_service = MoneroWalletService();
break;
case WalletType.bitcoin:
_service = BitcoinWalletService();
break;
default:
break;
}
_service = getIt.get<WalletService>(param1: type);
}
Future<void> create(WalletCredentials credentials) async {

View file

@ -1,6 +1,10 @@
import 'package:cake_wallet/src/domain/common/wallet_info.dart';
abstract class WalletCredentials {
WalletCredentials({this.name, this.password});
WalletCredentials({this.name, this.password, this.height});
final String name;
final int height;
String password;
WalletInfo walletInfo;
}

View file

@ -1,7 +1,11 @@
import 'package:cake_wallet/bitcoin/bitcoin_wallet_service.dart';
import 'package:cake_wallet/core/contact_service.dart';
import 'package:cake_wallet/core/wallet_service.dart';
import 'package:cake_wallet/monero/monero_wallet_service.dart';
import 'package:cake_wallet/src/domain/common/contact.dart';
import 'package:cake_wallet/src/domain/common/node.dart';
import 'package:cake_wallet/src/domain/exchange/trade.dart';
// import 'package:cake_wallet/src/domain/services/wallet_service.dart';
import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
import 'package:cake_wallet/src/screens/contact/contact_page.dart';
import 'package:cake_wallet/src/screens/exchange_trade/exchange_confirm_page.dart';
@ -367,6 +371,22 @@ Future setup(
getIt.registerFactory(
() => ExchangeTemplatePage(getIt.get<ExchangeViewModel>()));
getIt.registerFactory(() => MoneroWalletService(walletInfoSource));
getIt.registerFactory(() => BitcoinWalletService());
getIt.registerFactoryParam<WalletService, WalletType, void>(
(WalletType param1, __) {
switch (param1) {
case WalletType.monero:
return getIt.get<MoneroWalletService>();
case WalletType.bitcoin:
return getIt.get<BitcoinWalletService>();
default:
return null;
}
});
}
void setupThemeChangerStore(ThemeChanger themeChanger) {

View file

@ -251,6 +251,17 @@ class MaterialAppWithTheme extends StatelessWidget {
_settingsStore.isDarkTheme ? Brightness.light : Brightness.dark;
final statusBarIconBrightness =
_settingsStore.isDarkTheme ? Brightness.light : Brightness.dark;
final authenticationStore = getIt.get<AuthenticationStore>();
String initialRoute;
switch (authenticationStore.state) {
case AuthenticationState.denied:
initialRoute = Routes.welcome;
break;
default:
initialRoute = Routes.login;
break;
}
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: statusBarColor,
@ -258,7 +269,7 @@ class MaterialAppWithTheme extends StatelessWidget {
statusBarIconBrightness: statusBarIconBrightness));
return Root(
authenticationStore: getIt.get<AuthenticationStore>(),
authenticationStore: authenticationStore,
child: MaterialApp(
navigatorKey: navigatorKey,
debugShowCheckedModeBanner: false,
@ -286,8 +297,7 @@ class MaterialAppWithTheme extends StatelessWidget {
nodes: nodes,
trades: trades,
transactionDescriptions: transactionDescriptions),
initialRoute: Routes.login, // FIXME: get initial route!
// home: Container(color: Colors.blue),
initialRoute: initialRoute,
));
}
}

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/src/domain/common/wallet_info.dart';
import 'package:cake_wallet/src/domain/monero/monero_transaction_creation_credentials.dart';
import 'package:flutter/foundation.dart';
import 'package:mobx/mobx.dart';
@ -9,36 +10,29 @@ import 'package:cake_wallet/monero/monero_transaction_history.dart';
import 'package:cake_wallet/monero/monero_subaddress_list.dart';
import 'package:cake_wallet/monero/monero_account_list.dart';
import 'package:cake_wallet/core/wallet_base.dart';
import 'package:cake_wallet/core/transaction_history.dart';
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
import 'package:cake_wallet/src/domain/common/wallet_type.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/common/node.dart';
import 'package:cake_wallet/core/pending_transaction.dart';
import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
import 'package:cake_wallet/src/domain/common/calculate_fiat_amount.dart'
as cfa;
part 'monero_wallet.g.dart';
const moneroBlockSize = 1000;
class MoneroWallet = MoneroWalletBase with _$MoneroWallet;
abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
MoneroWalletBase({String filename, this.isRecovery = false})
MoneroWalletBase({String filename, WalletInfo walletInfo})
: transactionHistory = MoneroTransactionHistory(),
accountList = MoneroAccountList(),
subaddressList = MoneroSubaddressList() {
subaddressList = MoneroSubaddressList(),
super(walletInfo) {
_filename = filename;
balance = MoneroBalance(
fullBalance: monero_wallet.getFullBalance(accountIndex: 0),
unlockedBalance: monero_wallet.getFullBalance(accountIndex: 0));
currency = CryptoCurrency.xmr;
type = WalletType.monero;
_rct = reaction(
(_) => syncStatus, (SyncStatus status) => print(status.toString()));
_onAccountChangeReaction = reaction((_) => account, (Account account) {
subaddressList.update(accountIndex: account.id);
subaddress = subaddressList.subaddresses.first;
@ -46,8 +40,6 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
});
}
ReactionDisposer _rct;
@override
final MoneroTransactionHistory transactionHistory;
@ -57,15 +49,17 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
@observable
Subaddress subaddress;
@override
@observable
SyncStatus syncStatus;
@override
String get name => _filename.split('/').last;
@observable
String address;
@override
@observable
String address;
MoneroBalance balance;
@override
String get seed => monero_wallet.getSeed();
@ -81,8 +75,6 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
final MoneroAccountList accountList;
bool isRecovery;
String _filename;
SyncListner _listener;
ReactionDisposer _onAccountChangeReaction;
@ -107,8 +99,6 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
@override
Future<void> connectToNode({@required Node node}) async {
final node = Node(uri: 'xmr-node-uk.cakewallet.com:18081');
try {
syncStatus = ConnectingSyncStatus();
await monero_wallet.setupNode(
@ -127,6 +117,10 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
@override
Future<void> startSync() async {
try {
_setInitialHeight();
} catch (_) {}
try {
syncStatus = StartingSyncStatus();
monero_wallet.startRefresh();
@ -180,25 +174,18 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
@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();
Future<void> setAsRecovered() async {
walletInfo.isRecovery = false;
await walletInfo.save();
}
void _setListeners() {
_listener?.stop();
_listener = monero_wallet.setListeners(
@ -206,6 +193,41 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
_listener.start();
}
void _setInitialHeight() {
if (walletInfo.isRecovery) {
return;
}
final currentHeight = getCurrentHeight();
print('currentHeight $currentHeight');
if (currentHeight <= 1) {
final height = _getHeightByDate(walletInfo.date);
monero_wallet.setRecoveringFromSeed(isRecovery: true);
monero_wallet.setRefreshFromBlockHeight(height: height);
}
}
int _getHeightDistance(DateTime date) {
final distance =
DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch;
final daysTmp = (distance / 86400).round();
final days = daysTmp < 1 ? 1 : daysTmp;
return days * 1000;
}
int _getHeightByDate(DateTime date) {
final nodeHeight = monero_wallet.getNodeHeightSync();
final heightDistance = _getHeightDistance(date);
if (nodeHeight <= 0) {
return 0;
}
return nodeHeight - heightDistance;
}
void _askForUpdateBalance() {
final fullBalance = _getFullBalance();
final unlockedBalance = _getUnlockedBalance();
@ -236,13 +258,17 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance> with Store {
syncStatus = SyncedSyncStatus();
if (isRecovery) {
if (walletInfo.isRecovery) {
_askForUpdateTransactionHistory();
}
// if (isRecovery && (nodeHeight - currentHeight < moneroBlockSize)) {
// await setAsRecovered();
// }
final currentHeight = getCurrentHeight();
final nodeHeight = monero_wallet.getNodeHeightSync();
if (walletInfo.isRecovery &&
(nodeHeight - currentHeight < moneroBlockSize)) {
await setAsRecovered();
}
await save();
}

View file

@ -1,12 +1,14 @@
import 'dart:io';
import 'package:cake_wallet/core/wallet_base.dart';
import 'package:hive/hive.dart';
import 'package:cw_monero/wallet_manager.dart' as monero_wallet_manager;
import 'package:cw_monero/wallet.dart' as monero_wallet;
import 'package:cake_wallet/monero/monero_wallet.dart';
import 'package:cake_wallet/core/wallet_credentials.dart';
import 'package:cake_wallet/core/wallet_service.dart';
import 'package:cake_wallet/src/domain/common/pathForWallet.dart';
import 'package:cake_wallet/src/domain/common/wallet_info.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 {
MoneroNewWalletCredentials({String name, String password, this.language})
@ -17,11 +19,10 @@ class MoneroNewWalletCredentials extends WalletCredentials {
class MoneroRestoreWalletFromSeedCredentials extends WalletCredentials {
MoneroRestoreWalletFromSeedCredentials(
{String name, String password, this.mnemonic, this.height})
: super(name: name, password: password);
{String name, String password, int height, this.mnemonic})
: super(name: name, password: password, height: height);
final String mnemonic;
final int height;
}
class MoneroRestoreWalletFromKeysCredentials extends WalletCredentials {
@ -32,32 +33,35 @@ class MoneroRestoreWalletFromKeysCredentials extends WalletCredentials {
this.address,
this.viewKey,
this.spendKey,
this.height})
: super(name: name, password: password);
int height})
: super(name: name, password: password, height: height);
final String language;
final String address;
final String viewKey;
final String spendKey;
final int height;
}
class MoneroWalletService extends WalletService<
MoneroNewWalletCredentials,
MoneroRestoreWalletFromSeedCredentials,
MoneroRestoreWalletFromKeysCredentials> {
MoneroWalletService(this.walletInfoSource);
final Box<WalletInfo> walletInfoSource;
@override
Future<MoneroWallet> 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);
final wallet = MoneroWallet(filename: monero_wallet.getFilename());
final wallet = MoneroWallet(
filename: monero_wallet.getFilename(),
walletInfo: credentials.walletInfo);
await wallet.init();
return wallet;
@ -84,8 +88,16 @@ class MoneroWalletService extends WalletService<
Future<MoneroWallet> openWallet(String name, String password) async {
try {
final path = await pathForWallet(name: name, type: WalletType.monero);
final file = File(path);
final stat = await file.stat();
print(stat.changed);
print(stat.modified);
print(stat.accessed);
monero_wallet_manager.openWallet(path: path, password: password);
final wallet = MoneroWallet(filename: monero_wallet.getFilename());
final walletInfo = walletInfoSource.values.firstWhere(
(info) => info.id == WalletBase.idFor(name, WalletType.monero));
final wallet = MoneroWallet(
filename: monero_wallet.getFilename(), walletInfo: walletInfo);
await wallet.init();
return wallet;
@ -107,7 +119,6 @@ class MoneroWalletService extends WalletService<
try {
final path =
await pathForWallet(name: credentials.name, type: WalletType.monero);
await monero_wallet_manager.restoreFromKeys(
path: path,
password: credentials.password,
@ -116,8 +127,9 @@ class MoneroWalletService extends WalletService<
address: credentials.address,
viewKey: credentials.viewKey,
spendKey: credentials.spendKey);
final wallet = MoneroWallet(filename: monero_wallet.getFilename());
final wallet = MoneroWallet(
filename: monero_wallet.getFilename(),
walletInfo: credentials.walletInfo);
await wallet.init();
return wallet;
@ -134,14 +146,14 @@ class MoneroWalletService extends WalletService<
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);
final wallet = MoneroWallet(filename: monero_wallet.getFilename());
final wallet = MoneroWallet(
filename: monero_wallet.getFilename(),
walletInfo: credentials.walletInfo);
await wallet.init();
return wallet;

View file

@ -1,28 +1,20 @@
import 'dart:async';
import 'package:cake_wallet/core/key_service.dart';
import 'package:cake_wallet/router.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/domain/common/sync_status.dart';
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
import 'package:cake_wallet/src/screens/dashboard/dashboard_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/di.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:cake_wallet/bitcoin/bitcoin_wallet_service.dart';
import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
import 'package:cake_wallet/monero/monero_wallet_service.dart';
import 'package:connectivity/connectivity.dart';
import 'package:cake_wallet/core/key_service.dart';
import 'package:cake_wallet/router.dart';
import 'package:cake_wallet/src/domain/common/sync_status.dart';
import 'package:cake_wallet/core/wallet_base.dart';
import 'package:cake_wallet/core/wallet_service.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/store/authentication_store.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';
import 'package:cake_wallet/src/domain/services/fiat_convertation_service.dart';
import 'package:cake_wallet/src/domain/common/fiat_currency.dart';
import 'package:cake_wallet/store/dashboard/fiat_convertation_store.dart';
@ -36,19 +28,7 @@ Future<void> loadCurrentWallet() async {
final type = deserializeFromInt(typeRaw);
final password =
await getIt.get<KeyService>().getWalletPassword(walletName: name);
WalletService _service;
switch (type) {
case WalletType.monero:
_service = MoneroWalletService();
break;
case WalletType.bitcoin:
_service = BitcoinWalletService();
break;
default:
break;
}
final _service = getIt.get<WalletService>(param1: type);
final wallet = await _service.openWallet(name, password);
appStore.wallet = wallet;
}
@ -79,9 +59,6 @@ Future<void> bootstrap(
if (state == AuthenticationState.installed) {
await loadCurrentWallet();
}
if (state == AuthenticationState.installed) {
await navigatorKey.currentState
.pushAndRemoveUntil(createLoginRoute(), (_) => false);
}
@ -101,16 +78,31 @@ Future<void> bootstrap(
reaction((_) => getIt.get<AppStore>().wallet, (WalletBase wallet) async {
_onWalletSyncStatusChangeReaction?.reaction?.dispose();
_reconnectionTimer?.cancel();
_onWalletSyncStatusChangeReaction = reaction(
(_) => wallet.syncStatus is ConnectedSyncStatus,
(Object _) async => await wallet.startSync());
_onWalletSyncStatusChangeReaction =
reaction((_) => wallet.syncStatus, (SyncStatus status) async {
if (status is ConnectedSyncStatus) {
await wallet.startSync();
}
});
_reconnectionTimer = Timer.periodic(Duration(seconds: 5), (_) async {
final connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.none) {
wallet.syncStatus = FailedSyncStatus();
return;
}
if (wallet.syncStatus is LostConnectionSyncStatus ||
wallet.syncStatus is FailedSyncStatus) {
try {
final alive =
await settingsStore.getCurrentNode(wallet.type).requestNode();
if (alive) {
await wallet.connectToNode(
node: settingsStore.getCurrentNode(wallet.type));
}
} catch (_) {}
}
});

View file

@ -82,28 +82,28 @@ Future<void> migrate_wallets({Directory appDocDir}) async {
Future<void> migrate_ios_wallet_info(
{@required Directory appDocDir,
@required Box<WalletInfo> walletsInfo}) async {
final walletsDir = Directory('${appDocDir.path}/wallets');
final moneroWalletsDir = Directory('${walletsDir.path}/monero');
// final walletsDir = Directory('${appDocDir.path}/wallets');
// final moneroWalletsDir = Directory('${walletsDir.path}/monero');
moneroWalletsDir.listSync().forEach((item) async {
try {
if (item is Directory) {
final name = item.path.split('/').last;
final configFile = File('${item.path}/$name.json');
final config =
json.decode(configFile.readAsStringSync()) as Map<String, dynamic>;
final isRecovery = config["isRecovery"] as bool ?? false;
final id =
walletTypeToString(WalletType.monero).toLowerCase() + '_' + name;
final walletInfo =
WalletInfo(id: id, name: name, isRecovery: isRecovery);
// moneroWalletsDir.listSync().forEach((item) async {
// try {
// if (item is Directory) {
// final name = item.path.split('/').last;
// final configFile = File('${item.path}/$name.json');
// final config =
// json.decode(configFile.readAsStringSync()) as Map<String, dynamic>;
// final isRecovery = config["isRecovery"] as bool ?? false;
// final id =
// walletTypeToString(WalletType.monero).toLowerCase() + '_' + name;
// final walletInfo =
// WalletInfo(id: id, name: name, isRecovery: isRecovery);
await walletsInfo.add(walletInfo);
}
} catch (e) {
print(e.toString());
}
});
// await walletsInfo.add(walletInfo);
// }
// } catch (e) {
// print(e.toString());
// }
// });
}
Future<void> migrate_ios_trades_list(

View file

@ -1,12 +1,26 @@
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
part 'wallet_info.g.dart';
@HiveType(typeId: 4)
class WalletInfo extends HiveObject {
WalletInfo(
{this.id, this.name, this.type, this.isRecovery, this.restoreHeight});
WalletInfo(this.id, this.name, this.type, this.isRecovery, this.restoreHeight,
this.timestamp, this.dirPath, this.path);
factory WalletInfo.external(
{@required String id,
@required String name,
@required WalletType type,
@required bool isRecovery,
@required int restoreHeight,
@required DateTime date,
@required String dirPath,
@required String path}) {
return WalletInfo(id, name, type, isRecovery, restoreHeight,
date.millisecondsSinceEpoch ?? 0, dirPath, path);
}
static const boxName = 'WalletInfo';
@ -24,4 +38,15 @@ class WalletInfo extends HiveObject {
@HiveField(4)
int restoreHeight;
@HiveField(5)
int timestamp;
@HiveField(6)
String dirPath;
@HiveField(7)
String path;
DateTime get date => DateTime.fromMillisecondsSinceEpoch(timestamp);
}

View file

@ -47,18 +47,19 @@ class MoneroWallet extends Wallet {
String name,
bool isRecovery = false,
int restoreHeight = 0}) async {
const type = WalletType.monero;
final id = walletTypeToString(type).toLowerCase() + '_' + name;
final walletInfo = WalletInfo(
id: id,
name: name,
type: type,
isRecovery: isRecovery,
restoreHeight: restoreHeight);
await walletInfoSource.add(walletInfo);
// const type = WalletType.monero;
// final id = walletTypeToString(type).toLowerCase() + '_' + name;
// final walletInfo = WalletInfo(
// id: id,
// name: name,
// type: type,
// isRecovery: isRecovery,
// restoreHeight: restoreHeight);
// await walletInfoSource.add(walletInfo);
return await configured(
walletInfo: walletInfo, walletInfoSource: walletInfoSource);
// return await configured(
// walletInfo: walletInfo, walletInfoSource: walletInfoSource);
return null;
}
static Future<MoneroWallet> load(

View file

@ -12,8 +12,6 @@ import 'package:cake_wallet/src/domain/common/wallet.dart';
import 'package:cake_wallet/src/domain/monero/monero_wallet.dart';
import 'package:cake_wallet/src/domain/common/wallet_description.dart';
class MoneroWalletsManager extends WalletsManager {
MoneroWalletsManager({@required this.walletInfoSource});
@ -27,7 +25,8 @@ class MoneroWalletsManager extends WalletsManager {
const isRecovery = false;
final path = await pathForWallet(name: name, type: WalletType.monero);
await monero_wallet_manager.createWallet(path: path, password: password, language: language);
await monero_wallet_manager.createWallet(
path: path, password: password, language: language);
final wallet = await MoneroWallet.createdWallet(
walletInfoSource: walletInfoSource,

View file

@ -65,18 +65,18 @@ void onSyncStatusChange(
{SyncStore syncStore,
WalletStore walletStore,
SettingsStore settingsStore}) {
_onSyncStatusChangeDisposer?.call();
// _onSyncStatusChangeDisposer?.call();
reaction((_) => syncStore.status, (SyncStatus status) async {
if (status is ConnectedSyncStatus) {
await walletStore.startSync();
}
// reaction((_) => syncStore.status, (SyncStatus status) async {
// if (status is ConnectedSyncStatus) {
// await walletStore.startSync();
// }
// Reconnect to the node if the app is not started sync after 30 seconds
if (status is StartingSyncStatus) {
startReconnectionObserver(syncStore: syncStore, walletStore: walletStore);
}
});
// // Reconnect to the node if the app is not started sync after 30 seconds
// if (status is StartingSyncStatus) {
// startReconnectionObserver(syncStore: syncStore, walletStore: walletStore);
// }
// });
}
void startReconnectionObserver({SyncStore syncStore, WalletStore walletStore}) {

View file

@ -14,7 +14,8 @@ import 'package:cake_wallet/generated/i18n.dart';
part 'exchange_trade_view_model.g.dart';
class ExchangeTradeViewModel = ExchangeTradeViewModelBase with _$ExchangeTradeViewModel;
class ExchangeTradeViewModel = ExchangeTradeViewModelBase
with _$ExchangeTradeViewModel;
abstract class ExchangeTradeViewModelBase with Store {
ExchangeTradeViewModelBase({this.wallet, this.trades, this.tradesStore}) {
@ -38,17 +39,11 @@ abstract class ExchangeTradeViewModelBase with Store {
items = ObservableList<ExchangeTradeItem>();
items.addAll([
ExchangeTradeItem(
title: S.current.id,
data: '${trade.id}',
isCopied: true),
title: S.current.id, data: '${trade.id}', isCopied: true),
ExchangeTradeItem(
title: S.current.amount,
data: '${trade.amount}',
isCopied: false),
title: S.current.amount, data: '${trade.amount}', isCopied: false),
ExchangeTradeItem(
title: S.current.status,
data: '${trade.state}',
isCopied: false),
title: S.current.status, data: '${trade.state}', isCopied: false),
ExchangeTradeItem(
title: S.current.widgets_address + ':',
data: trade.inputAddress,

View file

@ -1,5 +1,3 @@
import 'package:cake_wallet/utils/item_cell.dart';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/core/wallet_base.dart';
@ -10,6 +8,7 @@ import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/src/domain/common/default_settings_migration.dart';
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
import 'package:cake_wallet/utils/mobx.dart';
import 'package:cake_wallet/utils/item_cell.dart';
part 'node_list_view_model.g.dart';

View file

@ -1,3 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:intl/intl.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/core/address_validator.dart';
import 'package:cake_wallet/core/amount_validator.dart';
import 'package:cake_wallet/core/template_validator.dart';
@ -5,7 +8,6 @@ import 'package:cake_wallet/core/validator.dart';
import 'package:cake_wallet/core/wallet_base.dart';
import 'package:cake_wallet/bitcoin/bitcoin_wallet.dart';
import 'package:cake_wallet/monero/monero_wallet.dart';
import 'package:cake_wallet/src/domain/common/balance.dart';
import 'package:cake_wallet/src/domain/common/balance_display_mode.dart';
import 'package:cake_wallet/src/domain/common/calculate_estimated_fee.dart';
import 'package:cake_wallet/src/domain/common/crypto_currency.dart';
@ -14,15 +16,6 @@ import 'package:cake_wallet/src/domain/common/sync_status.dart';
import 'package:cake_wallet/src/domain/common/transaction_priority.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/store/templates/send_template_store.dart';
import 'package:flutter/foundation.dart';
import 'package:intl/intl.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/monero/monero_wallet_service.dart';
import 'package:cake_wallet/bitcoin/bitcoin_wallet_creation_credentials.dart';
import 'package:cake_wallet/core/wallet_creation_service.dart';
import 'package:cake_wallet/core/wallet_credentials.dart';
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/domain/common/openalias_record.dart';
import 'package:cake_wallet/store/dashboard/fiat_convertation_store.dart';
@ -51,12 +44,8 @@ class SendingFailed extends SendViewModelState {
class SendViewModel = SendViewModelBase with _$SendViewModel;
abstract class SendViewModelBase with Store {
SendViewModelBase(
this._wallet,
this._settingsStore,
this._fiatConvertationStore,
this.sendTemplateStore) {
SendViewModelBase(this._wallet, this._settingsStore,
this._fiatConvertationStore, this.sendTemplateStore) {
state = InitialSendViewModelState();
_cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12;
@ -116,9 +105,10 @@ abstract class SendViewModelBase with Store {
double get price => _fiatConvertationStore.price;
@computed
ObservableList<Template> get templates => ObservableList.of(
sendTemplateStore.templates.where((item)
=> item.cryptoCurrency == _wallet.currency.title).toList());
ObservableList<Template> get templates =>
ObservableList.of(sendTemplateStore.templates
.where((item) => item.cryptoCurrency == _wallet.currency.title)
.toList());
@computed
String get balance {
@ -211,8 +201,8 @@ abstract class SendViewModelBase with Store {
String recordAddress;
Future<bool> isOpenaliasRecord(String name) async {
final _openaliasRecord = await OpenaliasRecord
.fetchAddressAndName(OpenaliasRecord.formatDomainName(name));
final _openaliasRecord = await OpenaliasRecord.fetchAddressAndName(
OpenaliasRecord.formatDomainName(name));
recordAddress = _openaliasRecord.address;
recordName = _openaliasRecord.name;

View file

@ -24,15 +24,14 @@ class AddressEditOrCreateStateFailure extends AddressEditOrCreateState {
}
abstract class WalletAddressEditOrCreateViewModelBase with Store {
WalletAddressEditOrCreateViewModelBase({@required WalletBase wallet, dynamic item})
WalletAddressEditOrCreateViewModelBase(
{@required WalletBase wallet, dynamic item})
: isEdit = item != null,
state = AddressEditOrCreateStateInitial(),
label = item?.name as String,
_item = item,
_wallet = wallet;
dynamic _item;
@observable
AddressEditOrCreateState state;
@ -41,11 +40,10 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store {
bool isEdit;
final dynamic _item;
final WalletBase _wallet;
Future<void> save() async {
final wallet = _wallet;
try {
state = AddressIsSaving();

View file

@ -109,8 +109,8 @@ abstract class WalletAddressListViewModelBase with Store {
return addressList;
}
set address(WalletAddressListItem address) =>
_wallet.address = address.address;
set address(WalletAddressListItem address) => null;
// _wallet.address = address.address;
bool hasAccounts;

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/core/wallet_base.dart';
import 'package:cake_wallet/src/domain/common/wallet_info.dart';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
@ -32,14 +33,16 @@ abstract class WalletCreationVMBase with Store {
Future<void> create({dynamic options}) async {
try {
state = WalletCreating();
await process(getCredentials(options));
final id = walletTypeToString(type).toLowerCase() + '_' + name;
final walletInfo = WalletInfo(
id: id,
final credentials = getCredentials(options);
final walletInfo = WalletInfo.external(
id: WalletBase.idFor(name, type),
name: name,
type: type,
isRecovery: isRecovery,
restoreHeight: 0);
restoreHeight: credentials.height ?? 0,
date: DateTime.now());
credentials.walletInfo = walletInfo;
await process(credentials);
await _walletInfoSource.add(walletInfo);
state = WalletCreatedSuccessfully();
} catch (e) {

View file

@ -1,12 +1,10 @@
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/core/key_service.dart';
import 'package:cake_wallet/core/wallet_service.dart';
import 'package:cake_wallet/bitcoin/bitcoin_wallet_service.dart';
import 'package:cake_wallet/monero/monero_wallet_service.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
import 'package:cake_wallet/src/domain/common/wallet_info.dart';
part 'wallet_list_view_model.g.dart';
@ -31,29 +29,18 @@ abstract class WalletListViewModelBase with Store {
Future<void> loadWallet(WalletListItem wallet) async {
final password =
await _keyService.getWalletPassword(walletName: wallet.name);
final walletService = _getWalletService(wallet.type);
final walletService = getIt.get<WalletService>();
_appStore.wallet = await walletService.openWallet(wallet.name, password);
}
@action
Future<void> remove(WalletListItem wallet) async {
final walletService = _getWalletService(wallet.type);
final walletService = getIt.get<WalletService>();
await walletService.remove(wallet.name);
await _walletInfoSource.delete(wallet.key);
_updateList();
}
WalletService _getWalletService(WalletType type) {
switch (type) {
case WalletType.monero:
return MoneroWalletService();
case WalletType.bitcoin:
return BitcoinWalletService();
default:
return null;
}
}
void _updateList() {
wallets.clear();
wallets.addAll(_walletInfoSource.values.map((info) => WalletListItem(

View file

@ -211,6 +211,34 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.14.13"
connectivity:
dependency: "direct main"
description:
name: connectivity
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.9+2"
connectivity_for_web:
dependency: transitive
description:
name: connectivity_for_web
url: "https://pub.dartlang.org"
source: hosted
version: "0.3.1+2"
connectivity_macos:
dependency: transitive
description:
name: connectivity_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.0+4"
connectivity_platform_interface:
dependency: transitive
description:
name: connectivity_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.6"
convert:
dependency: transitive
description:

View file

@ -60,6 +60,7 @@ dependencies:
basic_utils: ^1.0.8
bitcoin_flutter: ^2.0.0
get_it: ^4.0.2
connectivity: ^0.4.9+2
dev_dependencies:
flutter_test: