diff --git a/assets/electrum_server_list.yml b/assets/electrum_server_list.yml
index 4baf56aec..0331f42ea 100644
--- a/assets/electrum_server_list.yml
+++ b/assets/electrum_server_list.yml
@@ -1,2 +1,4 @@
-
- uri: electrum2.hodlister.co:50002
\ No newline at end of file
+ uri: electrum2.hodlister.co:50002
+-
+ uri: bitcoin.electrumx.multicoin.co:50002
\ No newline at end of file
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 959c597e1..641750308 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -61,7 +61,7 @@ DEPENDENCIES:
- cw_monero (from `.symlinks/plugins/cw_monero/ios`)
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
- esys_flutter_share (from `.symlinks/plugins/esys_flutter_share/ios`)
- - Flutter (from `.symlinks/flutter/ios`)
+ - Flutter (from `.symlinks/flutter/ios-release`)
- flutter_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- local_auth (from `.symlinks/plugins/local_auth/ios`)
@@ -92,7 +92,7 @@ EXTERNAL SOURCES:
esys_flutter_share:
:path: ".symlinks/plugins/esys_flutter_share/ios"
Flutter:
- :path: ".symlinks/flutter/ios"
+ :path: ".symlinks/flutter/ios-release"
flutter_plugin_android_lifecycle:
:path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios"
flutter_secure_storage:
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 34c4e48a4..987e086fc 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -373,7 +373,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 9;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -509,7 +509,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 9;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
@@ -540,7 +540,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = 6;
+ CURRENT_PROJECT_VERSION = 9;
DEVELOPMENT_TEAM = 32J6BB6VUS;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 0b40211a4..65000c894 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -22,6 +22,8 @@
$(CURRENT_PROJECT_VERSION)
LSRequiresIPhoneOS
+ NSCameraUsageDescription
+ Cake Wallet requires access to your phone’s camera.
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
diff --git a/lib/bitcoin/bitcoin_wallet.dart b/lib/bitcoin/bitcoin_wallet.dart
index b83e95ef1..4f67fa59f 100644
--- a/lib/bitcoin/bitcoin_wallet.dart
+++ b/lib/bitcoin/bitcoin_wallet.dart
@@ -200,7 +200,8 @@ abstract class BitcoinWalletBase extends WalletBase with Store {
Future startSync() async {
try {
syncStatus = StartingSyncStatus();
- transactionHistory.updateAsync(onFinished: () => print('finished!'));
+ transactionHistory.updateAsync(
+ onFinished: () => print('transactionHistory update finished!'));
_subscribeForUpdates();
await _updateBalance();
syncStatus = SyncedSyncStatus();
@@ -215,11 +216,7 @@ abstract class BitcoinWalletBase extends WalletBase with Store {
Future connectToNode({@required Node node}) async {
try {
syncStatus = ConnectingSyncStatus();
- // electrum2.hodlister.co
- // bitcoin.electrumx.multicoin.co:50002
- // electrum2.taborsky.cz:5002
- await eclient.connect(
- host: 'bitcoin.electrumx.multicoin.co', port: 50002);
+ await eclient.connectToUri(node.uri);
syncStatus = ConnectedSyncStatus();
} catch (e) {
print(e.toString());
diff --git a/lib/bitcoin/bitcoin_wallet_service.dart b/lib/bitcoin/bitcoin_wallet_service.dart
index d5827df18..e18692968 100644
--- a/lib/bitcoin/bitcoin_wallet_service.dart
+++ b/lib/bitcoin/bitcoin_wallet_service.dart
@@ -49,10 +49,9 @@ class BitcoinWalletService extends WalletService<
}
@override
- Future remove(String wallet) {
- // TODO: implement remove
- throw UnimplementedError();
- }
+ Future remove(String wallet) async =>
+ File(await pathForWalletDir(name: wallet, type: WalletType.bitcoin))
+ .delete(recursive: true);
@override
Future restoreFromKeys(
diff --git a/lib/bitcoin/electrum.dart b/lib/bitcoin/electrum.dart
index f24f6611f..d92c69405 100644
--- a/lib/bitcoin/electrum.dart
+++ b/lib/bitcoin/electrum.dart
@@ -37,11 +37,15 @@ class ElectrumClient {
bool _isConnected;
Timer _aliveTimer;
- Future connect({@required String host, @required int port}) async {
- if (socket != null) {
- await socket.close();
- }
+ Future connectToUri(String uri) async {
+ final _uri = Uri.parse(uri);
+ final host = _uri.scheme;
+ final port = int.parse(_uri.path);
+ await connect(host: host, port: port);
+ }
+ Future connect({@required String host, @required int port}) async {
+ await socket?.close();
final start = DateTime.now();
socket = await SecureSocket.connect(host, port, timeout: connectionTimeout);
diff --git a/lib/di.dart b/lib/di.dart
index 4c4c038a7..d7f425edf 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -25,6 +25,7 @@ import 'package:cake_wallet/src/screens/send/send_page.dart';
import 'package:cake_wallet/src/screens/subaddress/address_edit_or_create_page.dart';
import 'package:cake_wallet/src/screens/wallet_list/wallet_list_page.dart';
import 'package:cake_wallet/store/wallet_list_store.dart';
+import 'package:cake_wallet/utils/mobx.dart';
import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
import 'package:cake_wallet/view_model/contact_list/contact_view_model.dart';
import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
@@ -74,8 +75,20 @@ NodeListStore setupNodeListStore(Box nodeSource) {
_nodeListStore = NodeListStore();
_nodeListStore.replaceValues(nodeSource.values);
_onNodesSourceChange = nodeSource.watch();
- _onNodesSourceChange
- .listen((_) => _nodeListStore.replaceValues(nodeSource.values));
+ _onNodesSourceChange.listen((event) {
+// print(event);
+
+ if (event.deleted) {
+ _nodeListStore.nodes.removeWhere((n) {
+ return n.key != null ? n.key == event.key : true;
+ });
+ }
+
+ if (event.value is Node) {
+ final val = event.value as Node;
+ _nodeListStore.nodes.add(val);
+ }
+ });
return _nodeListStore;
}
@@ -274,10 +287,11 @@ Future setup(
getIt.registerFactoryParam((Contact contact, _) =>
ContactPage(getIt.get(param1: contact)));
- getIt.registerFactory(() => NodeListViewModel(
- getIt.get().nodeListStore,
- nodeSource,
- getIt.get().wallet));
+ getIt.registerFactory(() {
+ final appStore = getIt.get();
+ return NodeListViewModel(appStore.nodeListStore, nodeSource,
+ appStore.wallet, appStore.settingsStore);
+ });
getIt.registerFactory(() => NodeListPage(getIt.get()));
diff --git a/lib/main.dart b/lib/main.dart
index d1be6866d..6e69f4410 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -127,7 +127,7 @@ void main() async {
contactSource: contacts,
tradesSource: trades,
fiatConvertationService: fiatConvertationService,
- initialMigrationVersion: 3);
+ initialMigrationVersion: 4);
setReactions(
settingsStore: settingsStore,
@@ -169,7 +169,7 @@ Future initialSetup(
@required Box contactSource,
@required Box tradesSource,
@required FiatConvertationService fiatConvertationService,
- int initialMigrationVersion = 3}) async {
+ int initialMigrationVersion = 4}) async {
await defaultSettingsMigration(
version: initialMigrationVersion,
sharedPreferences: sharedPreferences,
diff --git a/lib/reactions/bootstrap.dart b/lib/reactions/bootstrap.dart
index b190697c5..76990eb55 100644
--- a/lib/reactions/bootstrap.dart
+++ b/lib/reactions/bootstrap.dart
@@ -50,7 +50,8 @@ ReactionDisposer _onCurrentWalletChangeReaction;
ReactionDisposer _onWalletSyncStatusChangeReaction;
ReactionDisposer _onCurrentFiatCurrencyChangeDisposer;
-Future bootstrap({FiatConvertationService fiatConvertationService}) async {
+Future bootstrap(
+ {FiatConvertationService fiatConvertationService}) async {
final authenticationStore = getIt.get();
final settingsStore = getIt.get();
final fiatConvertationStore = getIt.get();
@@ -72,12 +73,10 @@ Future bootstrap({FiatConvertationService fiatConvertationService}) async
_onCurrentWalletChangeReaction ??=
reaction((_) => getIt.get().wallet, (WalletBase wallet) async {
- print('Wallet name ${wallet.name}');
-
_onWalletSyncStatusChangeReaction?.reaction?.dispose();
- _onWalletSyncStatusChangeReaction = when(
+ _onWalletSyncStatusChangeReaction = reaction(
(_) => wallet.syncStatus is ConnectedSyncStatus,
- () async => await wallet.startSync());
+ (_) async => await wallet.startSync());
await getIt
.get()
@@ -87,30 +86,24 @@ Future bootstrap({FiatConvertationService fiatConvertationService}) async
.get()
.setInt('current_wallet_type', serializeToInt(wallet.type));
- await wallet.connectToNode(node: null);
-
+ final node = settingsStore.getCurrentNode(wallet.type);
final cryptoCurrency = wallet.currency;
final fiatCurrency = settingsStore.fiatCurrency;
+ await wallet.connectToNode(node: node);
+
final price = await fiatConvertationService.getPrice(
- crypto: cryptoCurrency,
- fiat: fiatCurrency
- );
+ crypto: cryptoCurrency, fiat: fiatCurrency);
fiatConvertationStore.setPrice(price);
});
- //
-
- _onCurrentFiatCurrencyChangeDisposer ??=
- reaction((_) => settingsStore.fiatCurrency,
- (FiatCurrency fiatCurrency) async {
+ _onCurrentFiatCurrencyChangeDisposer ??= reaction(
+ (_) => settingsStore.fiatCurrency, (FiatCurrency fiatCurrency) async {
final cryptoCurrency = getIt.get().wallet.currency;
final price = await fiatConvertationService.getPrice(
- crypto: cryptoCurrency,
- fiat: fiatCurrency
- );
+ crypto: cryptoCurrency, fiat: fiatCurrency);
fiatConvertationStore.setPrice(price);
});
diff --git a/lib/src/domain/common/default_settings_migration.dart b/lib/src/domain/common/default_settings_migration.dart
index d89223a4d..4ad41dff2 100644
--- a/lib/src/domain/common/default_settings_migration.dart
+++ b/lib/src/domain/common/default_settings_migration.dart
@@ -29,15 +29,19 @@ Future defaultSettingsMigration(
switch (version) {
case 1:
await sharedPreferences.setString(
- SettingsStoreBase.currentFiatCurrencyKey, FiatCurrency.usd.toString());
+ SettingsStoreBase.currentFiatCurrencyKey,
+ FiatCurrency.usd.toString());
await sharedPreferences.setInt(
- SettingsStoreBase.currentTransactionPriorityKey, TransactionPriority.standart.raw);
+ SettingsStoreBase.currentTransactionPriorityKey,
+ TransactionPriority.standart.raw);
await sharedPreferences.setInt(
SettingsStoreBase.currentBalanceDisplayModeKey,
BalanceDisplayMode.availableBalance.raw);
await sharedPreferences.setBool('save_recipient_address', true);
await resetToDefault(nodes);
- await changeCurrentNodeToDefault(
+ await changeMoneroCurrentNodeToDefault(
+ sharedPreferences: sharedPreferences, nodes: nodes);
+ await changeBitcoinCurrentElectrumServerToDefault(
sharedPreferences: sharedPreferences, nodes: nodes);
break;
@@ -50,6 +54,11 @@ Future defaultSettingsMigration(
case 3:
await updateNodeTypes(nodes: nodes);
await addBitcoinElectrumServerList(nodes: nodes);
+
+ break;
+ case 4:
+ await changeBitcoinCurrentElectrumServerToDefault(
+ sharedPreferences: sharedPreferences, nodes: nodes);
break;
default:
break;
@@ -69,10 +78,11 @@ Future defaultSettingsMigration(
Future replaceNodesMigration({@required Box nodes}) async {
final replaceNodes = {
'eu-node.cakewallet.io:18081':
- Node(uri: 'xmr-node-eu.cakewallet.com:18081'),
- 'node.cakewallet.io:18081':
- Node(uri: 'xmr-node-usa-east.cakewallet.com:18081'),
- 'node.xmr.ru:13666': Node(uri: 'node.monero.net:18081')
+ Node(uri: 'xmr-node-eu.cakewallet.com:18081', type: WalletType.monero),
+ 'node.cakewallet.io:18081': Node(
+ uri: 'xmr-node-usa-east.cakewallet.com:18081', type: WalletType.monero),
+ 'node.xmr.ru:13666':
+ Node(uri: 'node.monero.net:18081', type: WalletType.monero)
};
nodes.values.forEach((Node node) async {
@@ -87,11 +97,27 @@ Future replaceNodesMigration({@required Box nodes}) async {
});
}
-Future changeCurrentNodeToDefault(
+Future changeMoneroCurrentNodeToDefault(
{@required SharedPreferences sharedPreferences,
@required Box nodes}) async {
+ final node = getMoneroDefaultNode(nodes: nodes);
+ final nodeId = node?.key as int ?? 0; // 0 - England
+
+ await sharedPreferences.setInt('current_node_id', nodeId);
+}
+
+Node getBitcoinDefaultElectrumServer({@required Box nodes}) {
+ final uri = 'bitcoin.electrumx.multicoin.co:50002';
+
+ return nodes.values
+ .firstWhere((Node node) => node.uri == uri, orElse: () => null) ??
+ nodes.values.firstWhere((node) => node.type == WalletType.bitcoin,
+ orElse: () => null);
+}
+
+Node getMoneroDefaultNode({@required Box nodes}) {
final timeZone = DateTime.now().timeZoneOffset.inHours;
- String nodeUri = '';
+ var nodeUri = '';
if (timeZone >= 1) {
// Eurasia
@@ -101,11 +127,18 @@ Future changeCurrentNodeToDefault(
nodeUri = 'xmr-node-usa-east.cakewallet.com:18081';
}
- final node = nodes.values.firstWhere((Node node) => node.uri == nodeUri) ??
+ return nodes.values
+ .firstWhere((Node node) => node.uri == nodeUri, orElse: () => null) ??
nodes.values.first;
- final nodeId = node != null ? node.key as int : 0; // 0 - England
+}
- await sharedPreferences.setInt('current_node_id', nodeId);
+Future changeBitcoinCurrentElectrumServerToDefault(
+ {@required SharedPreferences sharedPreferences,
+ @required Box nodes}) async {
+ final server = getBitcoinDefaultElectrumServer(nodes: nodes);
+ final serverId = server?.key as int ?? 0;
+
+ await sharedPreferences.setInt('current_node_id_btc', serverId);
}
Future replaceDefaultNode(
@@ -126,7 +159,7 @@ Future replaceDefaultNode(
return;
}
- await changeCurrentNodeToDefault(
+ await changeMoneroCurrentNodeToDefault(
sharedPreferences: sharedPreferences, nodes: nodes);
}
diff --git a/lib/src/domain/common/node.dart b/lib/src/domain/common/node.dart
index f5b91547d..b47f002e9 100644
--- a/lib/src/domain/common/node.dart
+++ b/lib/src/domain/common/node.dart
@@ -9,12 +9,16 @@ part 'node.g.dart';
@HiveType(typeId: 1)
class Node extends HiveObject {
- Node({@required this.uri, @required WalletType type, this.login, this.password}) {
+ Node(
+ {@required this.uri,
+ @required WalletType type,
+ this.login,
+ this.password}) {
this.type = type;
}
Node.fromMap(Map map)
- : uri = (map['uri'] ?? '') as String,
+ : uri = map['uri'] as String ?? '',
login = map['login'] as String,
password = map['password'] as String,
typeRaw = map['typeRaw'] as int;
diff --git a/lib/src/domain/common/node_list.dart b/lib/src/domain/common/node_list.dart
index ad5db8a5d..67bfe6eac 100644
--- a/lib/src/domain/common/node_list.dart
+++ b/lib/src/domain/common/node_list.dart
@@ -10,7 +10,10 @@ Future> loadDefaultNodes() async {
return nodes.map((dynamic raw) {
if (raw is Map) {
- return Node.fromMap(raw);
+ final node = Node.fromMap(raw);
+ node?.type = WalletType.monero;
+
+ return node;
}
return null;
@@ -38,13 +41,7 @@ Future resetToDefault(Box nodeSource) async {
final moneroNodes = await loadDefaultNodes();
final bitcoinElectrumServerList = await loadElectrumServerList();
final nodes = moneroNodes + bitcoinElectrumServerList;
- final entities = {};
await nodeSource.clear();
-
- for (var i = 0; i < nodes.length; i++) {
- entities[i] = nodes[i];
- }
-
- await nodeSource.putAll(entities);
+ await nodeSource.addAll(nodes);
}
diff --git a/lib/src/screens/dashboard/dashboard_page.dart b/lib/src/screens/dashboard/dashboard_page.dart
index 1d5eab711..7a81d66cc 100644
--- a/lib/src/screens/dashboard/dashboard_page.dart
+++ b/lib/src/screens/dashboard/dashboard_page.dart
@@ -50,10 +50,7 @@ class DashboardPage extends BasePage {
padding: EdgeInsets.all(0),
onPressed: () async {
await showDialog(
- builder: (_) => MenuWidget(
- name: walletViewModel.name,
- subname: walletViewModel.subname,
- type: walletViewModel.type),
+ builder: (_) => MenuWidget(walletViewModel),
context: context);
},
child: menuButton
diff --git a/lib/src/screens/dashboard/wallet_menu.dart b/lib/src/screens/dashboard/wallet_menu.dart
index 2190a8d34..2de702bb9 100644
--- a/lib/src/screens/dashboard/wallet_menu.dart
+++ b/lib/src/screens/dashboard/wallet_menu.dart
@@ -6,8 +6,10 @@ import 'package:cake_wallet/src/stores/wallet/wallet_store.dart';
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
+// FIXME: terrible design
+
class WalletMenu {
- WalletMenu(this.context);
+ WalletMenu(this.context, this.reconnect);
final List items = [
S.current.reconnect,
@@ -30,6 +32,7 @@ class WalletMenu {
];
final BuildContext context;
+ final Future Function() reconnect;
void action(int index) {
switch (index) {
@@ -70,8 +73,6 @@ class WalletMenu {
}
Future _presentReconnectAlert(BuildContext context) async {
- final walletStore = Provider.of(context);
-
await showDialog(
context: context,
builder: (BuildContext context) {
@@ -80,12 +81,11 @@ class WalletMenu {
alertContent: S.of(context).reconnect_alert_text,
leftButtonText: S.of(context).ok,
rightButtonText: S.of(context).cancel,
- actionLeftButton: () {
- walletStore.reconnect();
+ actionLeftButton: () async {
+ await reconnect?.call();
Navigator.of(context).pop();
},
- actionRightButton: () => Navigator.of(context).pop()
- );
+ actionRightButton: () => Navigator.of(context).pop());
});
}
}
diff --git a/lib/src/screens/dashboard/widgets/menu_widget.dart b/lib/src/screens/dashboard/widgets/menu_widget.dart
index fdd9a704c..fab768773 100644
--- a/lib/src/screens/dashboard/widgets/menu_widget.dart
+++ b/lib/src/screens/dashboard/widgets/menu_widget.dart
@@ -1,14 +1,15 @@
import 'dart:ui';
+import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
import 'package:cake_wallet/src/screens/dashboard/wallet_menu.dart';
-class MenuWidget extends StatefulWidget {
- MenuWidget({this.type, this.name, this.subname});
+// FIXME: terrible design.
- final WalletType type;
- final String name;
- final String subname;
+class MenuWidget extends StatefulWidget {
+ MenuWidget(this.dashboardViewModel);
+
+ final DashboardViewModel dashboardViewModel;
@override
MenuWidgetState createState() => MenuWidgetState();
@@ -65,8 +66,8 @@ class MenuWidgetState extends State {
@override
Widget build(BuildContext context) {
- final walletMenu = WalletMenu(context);
-// final walletStore = Provider.of(context);
+ final walletMenu =
+ WalletMenu(context, () async => widget.dashboardViewModel.reconnect());
final itemCount = walletMenu.items.length;
return Row(
@@ -118,19 +119,20 @@ class MenuWidgetState extends State {
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
- _iconFor(type: widget.type),
+ _iconFor(type: widget.dashboardViewModel.type),
SizedBox(width: 16),
Expanded(
child: Container(
height: 40,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: widget.subname != null
- ? MainAxisAlignment.spaceBetween
- : MainAxisAlignment.center,
+ mainAxisAlignment:
+ widget.dashboardViewModel.subname != null
+ ? MainAxisAlignment.spaceBetween
+ : MainAxisAlignment.center,
children: [
Text(
- widget.name,
+ widget.dashboardViewModel.name,
style: TextStyle(
color: Theme.of(context)
.primaryTextTheme
@@ -141,9 +143,9 @@ class MenuWidgetState extends State {
fontSize: 20,
fontWeight: FontWeight.bold),
),
- if (widget.subname != null)
+ if (widget.dashboardViewModel.subname != null)
Text(
- widget.subname,
+ widget.dashboardViewModel.subname,
style: TextStyle(
color: Theme.of(context)
.primaryTextTheme
diff --git a/lib/src/screens/nodes/nodes_list_page.dart b/lib/src/screens/nodes/nodes_list_page.dart
index 2777e25b7..2182c38e7 100644
--- a/lib/src/screens/nodes/nodes_list_page.dart
+++ b/lib/src/screens/nodes/nodes_list_page.dart
@@ -74,15 +74,41 @@ class NodeListPage extends BasePage {
}
final node = nodeListViewModel.nodes[index];
- final isSelected = index == 1; // FIXME: hardcoded value.
final nodeListRow = NodeListRow(
- title: node.uri,
- isSelected: isSelected,
- isAlive: node.requestNode(),
- onTap: (_) {});
+ title: node.value.uri,
+ isSelected: node.isSelected,
+ isAlive: node.value.requestNode(),
+ onTap: (_) async {
+ if (node.isSelected) {
+ return;
+ }
+
+ await showDialog(
+ context: context,
+ builder: (BuildContext context) {
+ return AlertDialog(
+ content: Text(
+ S.of(context).change_current_node(node.value.uri),
+ textAlign: TextAlign.center,
+ ),
+ actions: [
+ FlatButton(
+ onPressed: () => Navigator.pop(context),
+ child: Text(S.of(context).cancel)),
+ FlatButton(
+ onPressed: () async {
+ Navigator.of(context).pop();
+ await nodeListViewModel
+ .setAsCurrent(node.value);
+ },
+ child: Text(S.of(context).change)),
+ ],
+ );
+ });
+ });
final dismissibleRow = Dismissible(
- key: Key('${node.key}'),
+ key: Key('${node.value.key}'),
confirmDismiss: (direction) async {
return await showDialog(
context: context,
@@ -99,7 +125,7 @@ class NodeListPage extends BasePage {
});
},
onDismissed: (direction) async =>
- nodeListViewModel.delete(node),
+ nodeListViewModel.delete(node.value),
direction: DismissDirection.endToStart,
background: Container(
padding: EdgeInsets.only(right: 10.0),
@@ -120,7 +146,7 @@ class NodeListPage extends BasePage {
)),
child: nodeListRow);
- return isSelected ? nodeListRow : dismissibleRow;
+ return node.isSelected ? nodeListRow : dismissibleRow;
},
itemCounter: (int sectionIndex) {
if (sectionIndex == 0) {
diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart
index 6b8e047cf..a500b2d20 100644
--- a/lib/src/screens/wallet_list/wallet_list_page.dart
+++ b/lib/src/screens/wallet_list/wallet_list_page.dart
@@ -63,14 +63,6 @@ class WalletListBodyState extends State {
itemBuilder: (__, index) {
final wallet = widget.walletListViewModel.wallets[index];
final screenWidth = MediaQuery.of(context).size.width;
-// String shortAddress = '';
-
-// if (wallet.isCurrent) {
-// shortAddress = wallet.address;
-// shortAddress = shortAddress.replaceRange(
-// 4, shortAddress.length - 4, '...');
-// }
-
final walletMenu = WalletMenu(context, widget.walletListViewModel);
final items =
walletMenu.generateItemsForWalletMenu(wallet.isCurrent);
diff --git a/lib/src/screens/wallet_list/wallet_menu.dart b/lib/src/screens/wallet_list/wallet_menu.dart
index b6654d0e8..a52eb8f8e 100644
--- a/lib/src/screens/wallet_list/wallet_menu.dart
+++ b/lib/src/screens/wallet_list/wallet_menu.dart
@@ -109,7 +109,7 @@ class WalletMenu {
try {
auth.changeProcessText(
S.of(context).wallet_list_removing_wallet(wallet.name));
-// await _walletListStore.remove(wallet);
+ await walletListViewModel.remove(wallet);
auth.close();
} catch (e) {
auth.changeProcessText(S
diff --git a/lib/src/stores/settings/settings_store.dart b/lib/src/stores/settings/settings_store.dart
index b3fe22e5a..21b56a967 100644
--- a/lib/src/stores/settings/settings_store.dart
+++ b/lib/src/stores/settings/settings_store.dart
@@ -42,7 +42,7 @@ abstract class SettingsStoreBase with Store {
_sharedPreferences = sharedPreferences;
_nodes = nodes;
allowBiometricalAuthentication = initialAllowBiometricalAuthentication;
- isDarkTheme = initialDarkTheme;
+ isDarkTheme = true;
defaultPinLength = initialPinLength;
languageCode = initialLanguageCode;
currentLocale = initialCurrentLocale;
@@ -143,7 +143,7 @@ abstract class SettingsStoreBase with Store {
bool allowBiometricalAuthentication;
@observable
- bool isDarkTheme;
+ bool isDarkTheme = true;
@observable
int defaultPinLength;
@@ -285,7 +285,7 @@ abstract class SettingsStoreBase with Store {
}
Future setCurrentNodeToDefault() async {
- await changeCurrentNodeToDefault(sharedPreferences: _sharedPreferences, nodes: _nodes);
+// await changeCurrentNodeToDefault(sharedPreferences: _sharedPreferences, nodes: _nodes);
await loadSettings();
}
diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart
index 7db75d309..0251fbce8 100644
--- a/lib/store/settings_store.dart
+++ b/lib/store/settings_store.dart
@@ -1,4 +1,5 @@
import 'package:cake_wallet/di.dart';
+import 'package:cake_wallet/src/domain/common/wallet_type.dart';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
@@ -29,8 +30,9 @@ abstract class SettingsStoreBase with Store {
@required int initialPinLength,
@required String initialLanguageCode,
@required String initialCurrentLocale,
- @required this.node,
+// @required this.node,
@required this.appVersion,
+ @required Map nodes,
this.actionlistDisplayMode}) {
fiatCurrency = initialFiatCurrency;
transactionPriority = initialTransactionPriority;
@@ -44,9 +46,11 @@ abstract class SettingsStoreBase with Store {
itemHeaders = {};
_sharedPreferences = sharedPreferences;
_nodeSource = nodeSource;
+ _nodes = nodes;
}
static const currentNodeIdKey = 'current_node_id';
+ static const currentBitcoinElectrumSererIdKey = 'current_node_id_btc';
static const currentFiatCurrencyKey = 'current_fiat_currency';
static const currentTransactionPriorityKey = 'current_fee_priority';
static const currentBalanceDisplayModeKey = 'current_balance_display_mode';
@@ -58,8 +62,8 @@ abstract class SettingsStoreBase with Store {
static const currentPinLength = 'current_pin_length';
static const currentLanguageCode = 'language_code';
- @observable
- Node node;
+// @observable
+// Node node;
@observable
FiatCurrency fiatCurrency;
@@ -97,6 +101,26 @@ abstract class SettingsStoreBase with Store {
SharedPreferences _sharedPreferences;
Box _nodeSource;
+ Map _nodes;
+
+ Node getCurrentNode(WalletType walletType) => _nodes[walletType];
+
+ Future setCurrentNode(Node node, WalletType walletType) async {
+ switch (walletType) {
+ case WalletType.bitcoin:
+ await _sharedPreferences.setInt(
+ currentBitcoinElectrumSererIdKey, node.key as int);
+ break;
+ case WalletType.monero:
+ await _sharedPreferences.setInt(currentNodeIdKey, node.key as int);
+ break;
+ default:
+ break;
+ }
+
+ _nodes[walletType] = node;
+ }
+
static Future load(
{@required Box nodeSource,
FiatCurrency initialFiatCurrency = FiatCurrency.usd,
@@ -126,12 +150,18 @@ abstract class SettingsStoreBase with Store {
await Language.localeDetection();
final initialCurrentLocale = await Devicelocale.currentLocale;
final nodeId = sharedPreferences.getInt(currentNodeIdKey);
- final node = nodeSource.get(nodeId);
+ final bitcoinElectrumServerId =
+ sharedPreferences.getInt(currentBitcoinElectrumSererIdKey);
+ final moneroNode = nodeSource.get(nodeId);
+ final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId);
final packageInfo = await PackageInfo.fromPlatform();
return SettingsStore(
sharedPreferences: sharedPreferences,
- node: node,
+ nodes: {
+ WalletType.monero: moneroNode,
+ WalletType.bitcoin: bitcoinElectrumServer
+ },
nodeSource: nodeSource,
appVersion: packageInfo.version,
initialFiatCurrency: currentFiatCurrency,
diff --git a/lib/utils/mobx.dart b/lib/utils/mobx.dart
new file mode 100644
index 000000000..4dd9b4100
--- /dev/null
+++ b/lib/utils/mobx.dart
@@ -0,0 +1,45 @@
+import 'package:mobx/mobx.dart';
+
+Dispose connectDifferent(ObservableList source, ObservableList dest,
+ Y Function(T) transform, {bool Function(T) filter}) {
+ return source.observe((change) {
+ switch (change.type) {
+ case OperationType.add:
+ final _values = change.added;
+ Iterable values;
+
+ if (filter != null) {
+ values = _values.where(filter);
+ }
+
+ dest.addAll(values.map((e) => transform(e)));
+ break;
+ case OperationType.remove:
+ print(change.index);
+ print(change.removed);
+ change.removed.forEach((element) { dest.remove(element); });
+
+// dest.removeAt(change.index);
+ break;
+ case OperationType.update:
+// change.index
+ break;
+ }
+ });
+}
+
+Dispose connect(ObservableList source, ObservableList dest) {
+ return source.observe((change) {
+ switch (change.type) {
+ case OperationType.add:
+ dest.addAll(change.added);
+ break;
+ case OperationType.remove:
+ dest.removeAt(change.index);
+ break;
+ case OperationType.update:
+// change.index
+ break;
+ }
+ });
+}
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index 7b79a772c..acb0d3d0a 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -129,6 +129,11 @@ abstract class DashboardViewModelBase with Store {
ReactionDisposer _reaction;
+ Future reconnect() async {
+ final node = appStore.settingsStore.getCurrentNode(wallet.type);
+ await wallet.connectToNode(node: node);
+ }
+
void _onWalletChange(WalletBase wallet) {
name = wallet.name;
transactions.clear();
diff --git a/lib/view_model/node_list/node_list_view_model.dart b/lib/view_model/node_list/node_list_view_model.dart
index 6821ae574..73f2b934e 100644
--- a/lib/view_model/node_list/node_list_view_model.dart
+++ b/lib/view_model/node_list/node_list_view_model.dart
@@ -1,26 +1,92 @@
+import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/core/wallet_base.dart';
import 'package:cake_wallet/src/domain/common/node.dart';
import 'package:cake_wallet/src/domain/common/node_list.dart';
import 'package:cake_wallet/store/node_list_store.dart';
+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';
part 'node_list_view_model.g.dart';
class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
-abstract class NodeListViewModelBase with Store {
- NodeListViewModelBase(this._nodeListStore, this._nodeSource, this._wallet);
+class ItemCell- {
+ ItemCell(this.value, {@required this.isSelected});
- @computed
- ObservableList get nodes => ObservableList.of(
- _nodeListStore.nodes.where((node) => node.type == _wallet.type));
+ final Item value;
+ final bool isSelected;
+}
+
+abstract class NodeListViewModelBase with Store {
+ NodeListViewModelBase(
+ this._nodeListStore, this._nodeSource, this._wallet, this._settingsStore)
+ : nodes = ObservableList>() {
+ final currentNode = _settingsStore.getCurrentNode(_wallet.type);
+ final values = _nodeListStore.nodes;
+ nodes.clear();
+ nodes.addAll(values.where((Node node) => node.type == _wallet.type).map(
+ (Node val) =>
+ ItemCell(val, isSelected: val.key == currentNode.key)));
+ connectDifferent(
+ _nodeListStore.nodes,
+ nodes,
+ (Node val) =>
+ ItemCell(val, isSelected: val.key == currentNode.key),
+ filter: (Node val) {
+ return val.type == _wallet.type;
+ });
+ }
+
+ ObservableList> nodes;
final WalletBase _wallet;
final Box _nodeSource;
final NodeListStore _nodeListStore;
+ final SettingsStore _settingsStore;
- Future reset() async => await resetToDefault(_nodeSource);
+ Future reset() async {
+ await resetToDefault(_nodeSource);
- Future delete(Node node) async => node.delete();
+ Node node;
+
+ switch (_wallet.type) {
+ case WalletType.bitcoin:
+ node = getBitcoinDefaultElectrumServer(nodes: _nodeSource);
+ break;
+ case WalletType.monero:
+ node = getMoneroDefaultNode(
+ nodes: _nodeSource,
+ );
+ break;
+ default:
+ break;
+ }
+
+ await _wallet.connectToNode(node: node);
+ }
+
+ Future delete(Node node) async => _nodeSource.delete(node.key);
+
+ Future setAsCurrent(Node node) async {
+ await _wallet.connectToNode(node: node);
+ await _settingsStore.setCurrentNode(node, _wallet.type);
+ _updateCurrentNode();
+ }
+
+ void _updateCurrentNode() {
+ final currentNode = _settingsStore.getCurrentNode(_wallet.type);
+
+ for (var i = 0; i < nodes.length; i++) {
+ final item = nodes[i];
+ final isSelected = item.value.key == currentNode.key;
+
+ if (item.isSelected != isSelected) {
+ nodes[i] = ItemCell(item.value, isSelected: isSelected);
+ }
+ }
+ }
}
diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index 0a128dc0a..75926a0b2 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -27,6 +27,7 @@ abstract class SendViewModelBase with Store {
this._wallet, this._settingsStore, this._fiatConversationStore)
: state = InitialSendViewModelState(),
_cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12,
+ // FIXME: need to be based on wallet type.
all = false;
@observable
@@ -79,7 +80,7 @@ abstract class SendViewModelBase with Store {
final WalletBase _wallet;
final SettingsStore _settingsStore;
final FiatConvertationStore _fiatConversationStore;
- NumberFormat _cryptoNumberFormat;
+ final NumberFormat _cryptoNumberFormat;
@action
void setAll() => all = true;
@@ -129,7 +130,8 @@ abstract class SendViewModelBase with Store {
void _updateFiatAmount() {
try {
final fiat = calculateFiatAmount(
- price: _fiatConversationStore.price, cryptoAmount: cryptoAmount);
+ price: _fiatConversationStore.price,
+ cryptoAmount: cryptoAmount.replaceAll(',', '.'));
if (fiatAmount != fiat) {
fiatAmount = fiat;
}
@@ -141,7 +143,8 @@ abstract class SendViewModelBase with Store {
@action
void _updateCryptoAmount() {
try {
- final crypto = double.parse(fiatAmount) / _fiatConversationStore.price;
+ final crypto = double.parse(fiatAmount.replaceAll(',', '.')) /
+ _fiatConversationStore.price;
final cryptoAmountTmp = _cryptoNumberFormat.format(crypto);
if (cryptoAmount != cryptoAmountTmp) {
diff --git a/lib/view_model/settings/settings_view_model.dart b/lib/view_model/settings/settings_view_model.dart
index dbca8ef66..4eb68286f 100644
--- a/lib/view_model/settings/settings_view_model.dart
+++ b/lib/view_model/settings/settings_view_model.dart
@@ -23,7 +23,8 @@ class SettingsViewModel = SettingsViewModelBase with _$SettingsViewModel;
abstract class SettingsViewModelBase with Store {
SettingsViewModelBase(this._settingsStore, WalletBase wallet)
- : itemHeaders = {} {
+ : itemHeaders = {},
+ _walletType = wallet.type {
sections = [
[
PickerListItem(
@@ -117,7 +118,7 @@ abstract class SettingsViewModelBase with Store {
}
@computed
- Node get node => _settingsStore.node;
+ Node get node => _settingsStore.getCurrentNode(_walletType);
@computed
FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency;
@@ -150,13 +151,10 @@ abstract class SettingsViewModelBase with Store {
set allowBiometricalAuthentication(bool value) =>
_settingsStore.allowBiometricalAuthentication = value;
-// @observable
-
-// @observable
-
final Map itemHeaders;
- List
> sections;
final SettingsStore _settingsStore;
+ final WalletType _walletType;
+ List> sections;
@action
void toggleTransactionsDisplay() =>
diff --git a/lib/view_model/wallet_list/wallet_list_item.dart b/lib/view_model/wallet_list/wallet_list_item.dart
index 669a2be79..5e2210c7a 100644
--- a/lib/view_model/wallet_list/wallet_list_item.dart
+++ b/lib/view_model/wallet_list/wallet_list_item.dart
@@ -3,9 +3,10 @@ import 'package:cake_wallet/src/domain/common/wallet_type.dart';
class WalletListItem {
const WalletListItem(
- {@required this.name, @required this.type, this.isCurrent = false});
+ {@required this.name, @required this.type, @required this.key, this.isCurrent = false});
final String name;
final WalletType type;
final bool isCurrent;
+ final dynamic key;
}
diff --git a/lib/view_model/wallet_list/wallet_list_view_model.dart b/lib/view_model/wallet_list/wallet_list_view_model.dart
index e84959e91..15683d1f1 100644
--- a/lib/view_model/wallet_list/wallet_list_view_model.dart
+++ b/lib/view_model/wallet_list/wallet_list_view_model.dart
@@ -17,11 +17,7 @@ abstract class WalletListViewModelBase with Store {
WalletListViewModelBase(
this._walletInfoSource, this._appStore, this._keyService) {
wallets = ObservableList();
- wallets.addAll(_walletInfoSource.values.map((info) => WalletListItem(
- name: info.name,
- type: info.type,
- isCurrent: info.name == _appStore.wallet.name &&
- info.type == _appStore.wallet.type)));
+ _updateList();
}
@observable
@@ -40,7 +36,12 @@ abstract class WalletListViewModelBase with Store {
}
@action
- Future remove(WalletListItem wallet) async {}
+ Future remove(WalletListItem wallet) async {
+ final walletService = _getWalletService(wallet.type);
+ await walletService.remove(wallet.name);
+ await _walletInfoSource.delete(wallet.key);
+ _updateList();
+ }
WalletService _getWalletService(WalletType type) {
switch (type) {
@@ -52,4 +53,14 @@ abstract class WalletListViewModelBase with Store {
return null;
}
}
+
+ void _updateList() {
+ wallets.clear();
+ wallets.addAll(_walletInfoSource.values.map((info) => WalletListItem(
+ name: info.name,
+ type: info.type,
+ key: info.key,
+ isCurrent: info.name == _appStore.wallet.name &&
+ info.type == _appStore.wallet.type)));
+ }
}