mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-18 16:55:58 +00:00
TMP 0
This commit is contained in:
parent
5eefd6a31b
commit
6aaac93fa8
28 changed files with 364 additions and 143 deletions
|
@ -1,2 +1,4 @@
|
||||||
-
|
-
|
||||||
uri: electrum2.hodlister.co:50002
|
uri: electrum2.hodlister.co:50002
|
||||||
|
-
|
||||||
|
uri: bitcoin.electrumx.multicoin.co:50002
|
|
@ -61,7 +61,7 @@ DEPENDENCIES:
|
||||||
- cw_monero (from `.symlinks/plugins/cw_monero/ios`)
|
- cw_monero (from `.symlinks/plugins/cw_monero/ios`)
|
||||||
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
- devicelocale (from `.symlinks/plugins/devicelocale/ios`)
|
||||||
- esys_flutter_share (from `.symlinks/plugins/esys_flutter_share/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_plugin_android_lifecycle (from `.symlinks/plugins/flutter_plugin_android_lifecycle/ios`)
|
||||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
- local_auth (from `.symlinks/plugins/local_auth/ios`)
|
- local_auth (from `.symlinks/plugins/local_auth/ios`)
|
||||||
|
@ -92,7 +92,7 @@ EXTERNAL SOURCES:
|
||||||
esys_flutter_share:
|
esys_flutter_share:
|
||||||
:path: ".symlinks/plugins/esys_flutter_share/ios"
|
:path: ".symlinks/plugins/esys_flutter_share/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: ".symlinks/flutter/ios"
|
:path: ".symlinks/flutter/ios-release"
|
||||||
flutter_plugin_android_lifecycle:
|
flutter_plugin_android_lifecycle:
|
||||||
:path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios"
|
:path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios"
|
||||||
flutter_secure_storage:
|
flutter_secure_storage:
|
||||||
|
|
|
@ -373,7 +373,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 6;
|
CURRENT_PROJECT_VERSION = 9;
|
||||||
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -509,7 +509,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 6;
|
CURRENT_PROJECT_VERSION = 9;
|
||||||
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
@ -540,7 +540,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 6;
|
CURRENT_PROJECT_VERSION = 9;
|
||||||
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
DEVELOPMENT_TEAM = 32J6BB6VUS;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>Cake Wallet requires access to your phone’s camera.</string>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
|
|
|
@ -200,7 +200,8 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
||||||
Future<void> startSync() async {
|
Future<void> startSync() async {
|
||||||
try {
|
try {
|
||||||
syncStatus = StartingSyncStatus();
|
syncStatus = StartingSyncStatus();
|
||||||
transactionHistory.updateAsync(onFinished: () => print('finished!'));
|
transactionHistory.updateAsync(
|
||||||
|
onFinished: () => print('transactionHistory update finished!'));
|
||||||
_subscribeForUpdates();
|
_subscribeForUpdates();
|
||||||
await _updateBalance();
|
await _updateBalance();
|
||||||
syncStatus = SyncedSyncStatus();
|
syncStatus = SyncedSyncStatus();
|
||||||
|
@ -215,11 +216,7 @@ abstract class BitcoinWalletBase extends WalletBase<BitcoinBalance> with Store {
|
||||||
Future<void> connectToNode({@required Node node}) async {
|
Future<void> connectToNode({@required Node node}) async {
|
||||||
try {
|
try {
|
||||||
syncStatus = ConnectingSyncStatus();
|
syncStatus = ConnectingSyncStatus();
|
||||||
// electrum2.hodlister.co
|
await eclient.connectToUri(node.uri);
|
||||||
// bitcoin.electrumx.multicoin.co:50002
|
|
||||||
// electrum2.taborsky.cz:5002
|
|
||||||
await eclient.connect(
|
|
||||||
host: 'bitcoin.electrumx.multicoin.co', port: 50002);
|
|
||||||
syncStatus = ConnectedSyncStatus();
|
syncStatus = ConnectedSyncStatus();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e.toString());
|
print(e.toString());
|
||||||
|
|
|
@ -49,10 +49,9 @@ class BitcoinWalletService extends WalletService<
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> remove(String wallet) {
|
Future<void> remove(String wallet) async =>
|
||||||
// TODO: implement remove
|
File(await pathForWalletDir(name: wallet, type: WalletType.bitcoin))
|
||||||
throw UnimplementedError();
|
.delete(recursive: true);
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<BitcoinWallet> restoreFromKeys(
|
Future<BitcoinWallet> restoreFromKeys(
|
||||||
|
|
|
@ -37,11 +37,15 @@ class ElectrumClient {
|
||||||
bool _isConnected;
|
bool _isConnected;
|
||||||
Timer _aliveTimer;
|
Timer _aliveTimer;
|
||||||
|
|
||||||
Future<void> connect({@required String host, @required int port}) async {
|
Future<void> connectToUri(String uri) async {
|
||||||
if (socket != null) {
|
final _uri = Uri.parse(uri);
|
||||||
await socket.close();
|
final host = _uri.scheme;
|
||||||
|
final port = int.parse(_uri.path);
|
||||||
|
await connect(host: host, port: port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> connect({@required String host, @required int port}) async {
|
||||||
|
await socket?.close();
|
||||||
final start = DateTime.now();
|
final start = DateTime.now();
|
||||||
|
|
||||||
socket = await SecureSocket.connect(host, port, timeout: connectionTimeout);
|
socket = await SecureSocket.connect(host, port, timeout: connectionTimeout);
|
||||||
|
|
26
lib/di.dart
26
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/subaddress/address_edit_or_create_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/wallet_list/wallet_list_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/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_list_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/contact_list/contact_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';
|
import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
|
||||||
|
@ -74,8 +75,20 @@ NodeListStore setupNodeListStore(Box<Node> nodeSource) {
|
||||||
_nodeListStore = NodeListStore();
|
_nodeListStore = NodeListStore();
|
||||||
_nodeListStore.replaceValues(nodeSource.values);
|
_nodeListStore.replaceValues(nodeSource.values);
|
||||||
_onNodesSourceChange = nodeSource.watch();
|
_onNodesSourceChange = nodeSource.watch();
|
||||||
_onNodesSourceChange
|
_onNodesSourceChange.listen((event) {
|
||||||
.listen((_) => _nodeListStore.replaceValues(nodeSource.values));
|
// 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;
|
return _nodeListStore;
|
||||||
}
|
}
|
||||||
|
@ -274,10 +287,11 @@ Future setup(
|
||||||
getIt.registerFactoryParam<ContactPage, Contact, void>((Contact contact, _) =>
|
getIt.registerFactoryParam<ContactPage, Contact, void>((Contact contact, _) =>
|
||||||
ContactPage(getIt.get<ContactViewModel>(param1: contact)));
|
ContactPage(getIt.get<ContactViewModel>(param1: contact)));
|
||||||
|
|
||||||
getIt.registerFactory(() => NodeListViewModel(
|
getIt.registerFactory(() {
|
||||||
getIt.get<AppStore>().nodeListStore,
|
final appStore = getIt.get<AppStore>();
|
||||||
nodeSource,
|
return NodeListViewModel(appStore.nodeListStore, nodeSource,
|
||||||
getIt.get<AppStore>().wallet));
|
appStore.wallet, appStore.settingsStore);
|
||||||
|
});
|
||||||
|
|
||||||
getIt.registerFactory(() => NodeListPage(getIt.get<NodeListViewModel>()));
|
getIt.registerFactory(() => NodeListPage(getIt.get<NodeListViewModel>()));
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ void main() async {
|
||||||
contactSource: contacts,
|
contactSource: contacts,
|
||||||
tradesSource: trades,
|
tradesSource: trades,
|
||||||
fiatConvertationService: fiatConvertationService,
|
fiatConvertationService: fiatConvertationService,
|
||||||
initialMigrationVersion: 3);
|
initialMigrationVersion: 4);
|
||||||
|
|
||||||
setReactions(
|
setReactions(
|
||||||
settingsStore: settingsStore,
|
settingsStore: settingsStore,
|
||||||
|
@ -169,7 +169,7 @@ Future<void> initialSetup(
|
||||||
@required Box<Contact> contactSource,
|
@required Box<Contact> contactSource,
|
||||||
@required Box<Trade> tradesSource,
|
@required Box<Trade> tradesSource,
|
||||||
@required FiatConvertationService fiatConvertationService,
|
@required FiatConvertationService fiatConvertationService,
|
||||||
int initialMigrationVersion = 3}) async {
|
int initialMigrationVersion = 4}) async {
|
||||||
await defaultSettingsMigration(
|
await defaultSettingsMigration(
|
||||||
version: initialMigrationVersion,
|
version: initialMigrationVersion,
|
||||||
sharedPreferences: sharedPreferences,
|
sharedPreferences: sharedPreferences,
|
||||||
|
|
|
@ -50,7 +50,8 @@ ReactionDisposer _onCurrentWalletChangeReaction;
|
||||||
ReactionDisposer _onWalletSyncStatusChangeReaction;
|
ReactionDisposer _onWalletSyncStatusChangeReaction;
|
||||||
ReactionDisposer _onCurrentFiatCurrencyChangeDisposer;
|
ReactionDisposer _onCurrentFiatCurrencyChangeDisposer;
|
||||||
|
|
||||||
Future<void> bootstrap({FiatConvertationService fiatConvertationService}) async {
|
Future<void> bootstrap(
|
||||||
|
{FiatConvertationService fiatConvertationService}) async {
|
||||||
final authenticationStore = getIt.get<AuthenticationStore>();
|
final authenticationStore = getIt.get<AuthenticationStore>();
|
||||||
final settingsStore = getIt.get<SettingsStore>();
|
final settingsStore = getIt.get<SettingsStore>();
|
||||||
final fiatConvertationStore = getIt.get<FiatConvertationStore>();
|
final fiatConvertationStore = getIt.get<FiatConvertationStore>();
|
||||||
|
@ -72,12 +73,10 @@ Future<void> bootstrap({FiatConvertationService fiatConvertationService}) async
|
||||||
|
|
||||||
_onCurrentWalletChangeReaction ??=
|
_onCurrentWalletChangeReaction ??=
|
||||||
reaction((_) => getIt.get<AppStore>().wallet, (WalletBase wallet) async {
|
reaction((_) => getIt.get<AppStore>().wallet, (WalletBase wallet) async {
|
||||||
print('Wallet name ${wallet.name}');
|
|
||||||
|
|
||||||
_onWalletSyncStatusChangeReaction?.reaction?.dispose();
|
_onWalletSyncStatusChangeReaction?.reaction?.dispose();
|
||||||
_onWalletSyncStatusChangeReaction = when(
|
_onWalletSyncStatusChangeReaction = reaction(
|
||||||
(_) => wallet.syncStatus is ConnectedSyncStatus,
|
(_) => wallet.syncStatus is ConnectedSyncStatus,
|
||||||
() async => await wallet.startSync());
|
(_) async => await wallet.startSync());
|
||||||
|
|
||||||
await getIt
|
await getIt
|
||||||
.get<SharedPreferences>()
|
.get<SharedPreferences>()
|
||||||
|
@ -87,30 +86,24 @@ Future<void> bootstrap({FiatConvertationService fiatConvertationService}) async
|
||||||
.get<SharedPreferences>()
|
.get<SharedPreferences>()
|
||||||
.setInt('current_wallet_type', serializeToInt(wallet.type));
|
.setInt('current_wallet_type', serializeToInt(wallet.type));
|
||||||
|
|
||||||
await wallet.connectToNode(node: null);
|
final node = settingsStore.getCurrentNode(wallet.type);
|
||||||
|
|
||||||
final cryptoCurrency = wallet.currency;
|
final cryptoCurrency = wallet.currency;
|
||||||
final fiatCurrency = settingsStore.fiatCurrency;
|
final fiatCurrency = settingsStore.fiatCurrency;
|
||||||
|
|
||||||
|
await wallet.connectToNode(node: node);
|
||||||
|
|
||||||
final price = await fiatConvertationService.getPrice(
|
final price = await fiatConvertationService.getPrice(
|
||||||
crypto: cryptoCurrency,
|
crypto: cryptoCurrency, fiat: fiatCurrency);
|
||||||
fiat: fiatCurrency
|
|
||||||
);
|
|
||||||
|
|
||||||
fiatConvertationStore.setPrice(price);
|
fiatConvertationStore.setPrice(price);
|
||||||
});
|
});
|
||||||
|
|
||||||
//
|
_onCurrentFiatCurrencyChangeDisposer ??= reaction(
|
||||||
|
(_) => settingsStore.fiatCurrency, (FiatCurrency fiatCurrency) async {
|
||||||
_onCurrentFiatCurrencyChangeDisposer ??=
|
|
||||||
reaction((_) => settingsStore.fiatCurrency,
|
|
||||||
(FiatCurrency fiatCurrency) async {
|
|
||||||
final cryptoCurrency = getIt.get<AppStore>().wallet.currency;
|
final cryptoCurrency = getIt.get<AppStore>().wallet.currency;
|
||||||
|
|
||||||
final price = await fiatConvertationService.getPrice(
|
final price = await fiatConvertationService.getPrice(
|
||||||
crypto: cryptoCurrency,
|
crypto: cryptoCurrency, fiat: fiatCurrency);
|
||||||
fiat: fiatCurrency
|
|
||||||
);
|
|
||||||
|
|
||||||
fiatConvertationStore.setPrice(price);
|
fiatConvertationStore.setPrice(price);
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,15 +29,19 @@ Future defaultSettingsMigration(
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case 1:
|
case 1:
|
||||||
await sharedPreferences.setString(
|
await sharedPreferences.setString(
|
||||||
SettingsStoreBase.currentFiatCurrencyKey, FiatCurrency.usd.toString());
|
SettingsStoreBase.currentFiatCurrencyKey,
|
||||||
|
FiatCurrency.usd.toString());
|
||||||
await sharedPreferences.setInt(
|
await sharedPreferences.setInt(
|
||||||
SettingsStoreBase.currentTransactionPriorityKey, TransactionPriority.standart.raw);
|
SettingsStoreBase.currentTransactionPriorityKey,
|
||||||
|
TransactionPriority.standart.raw);
|
||||||
await sharedPreferences.setInt(
|
await sharedPreferences.setInt(
|
||||||
SettingsStoreBase.currentBalanceDisplayModeKey,
|
SettingsStoreBase.currentBalanceDisplayModeKey,
|
||||||
BalanceDisplayMode.availableBalance.raw);
|
BalanceDisplayMode.availableBalance.raw);
|
||||||
await sharedPreferences.setBool('save_recipient_address', true);
|
await sharedPreferences.setBool('save_recipient_address', true);
|
||||||
await resetToDefault(nodes);
|
await resetToDefault(nodes);
|
||||||
await changeCurrentNodeToDefault(
|
await changeMoneroCurrentNodeToDefault(
|
||||||
|
sharedPreferences: sharedPreferences, nodes: nodes);
|
||||||
|
await changeBitcoinCurrentElectrumServerToDefault(
|
||||||
sharedPreferences: sharedPreferences, nodes: nodes);
|
sharedPreferences: sharedPreferences, nodes: nodes);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -50,6 +54,11 @@ Future defaultSettingsMigration(
|
||||||
case 3:
|
case 3:
|
||||||
await updateNodeTypes(nodes: nodes);
|
await updateNodeTypes(nodes: nodes);
|
||||||
await addBitcoinElectrumServerList(nodes: nodes);
|
await addBitcoinElectrumServerList(nodes: nodes);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
await changeBitcoinCurrentElectrumServerToDefault(
|
||||||
|
sharedPreferences: sharedPreferences, nodes: nodes);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -69,10 +78,11 @@ Future defaultSettingsMigration(
|
||||||
Future<void> replaceNodesMigration({@required Box<Node> nodes}) async {
|
Future<void> replaceNodesMigration({@required Box<Node> nodes}) async {
|
||||||
final replaceNodes = <String, Node>{
|
final replaceNodes = <String, Node>{
|
||||||
'eu-node.cakewallet.io:18081':
|
'eu-node.cakewallet.io:18081':
|
||||||
Node(uri: 'xmr-node-eu.cakewallet.com:18081'),
|
Node(uri: 'xmr-node-eu.cakewallet.com:18081', type: WalletType.monero),
|
||||||
'node.cakewallet.io:18081':
|
'node.cakewallet.io:18081': Node(
|
||||||
Node(uri: 'xmr-node-usa-east.cakewallet.com:18081'),
|
uri: 'xmr-node-usa-east.cakewallet.com:18081', type: WalletType.monero),
|
||||||
'node.xmr.ru:13666': Node(uri: 'node.monero.net:18081')
|
'node.xmr.ru:13666':
|
||||||
|
Node(uri: 'node.monero.net:18081', type: WalletType.monero)
|
||||||
};
|
};
|
||||||
|
|
||||||
nodes.values.forEach((Node node) async {
|
nodes.values.forEach((Node node) async {
|
||||||
|
@ -87,11 +97,27 @@ Future<void> replaceNodesMigration({@required Box<Node> nodes}) async {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> changeCurrentNodeToDefault(
|
Future<void> changeMoneroCurrentNodeToDefault(
|
||||||
{@required SharedPreferences sharedPreferences,
|
{@required SharedPreferences sharedPreferences,
|
||||||
@required Box<Node> nodes}) async {
|
@required Box<Node> 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<Node> 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<Node> nodes}) {
|
||||||
final timeZone = DateTime.now().timeZoneOffset.inHours;
|
final timeZone = DateTime.now().timeZoneOffset.inHours;
|
||||||
String nodeUri = '';
|
var nodeUri = '';
|
||||||
|
|
||||||
if (timeZone >= 1) {
|
if (timeZone >= 1) {
|
||||||
// Eurasia
|
// Eurasia
|
||||||
|
@ -101,11 +127,18 @@ Future<void> changeCurrentNodeToDefault(
|
||||||
nodeUri = 'xmr-node-usa-east.cakewallet.com:18081';
|
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;
|
nodes.values.first;
|
||||||
final nodeId = node != null ? node.key as int : 0; // 0 - England
|
}
|
||||||
|
|
||||||
await sharedPreferences.setInt('current_node_id', nodeId);
|
Future<void> changeBitcoinCurrentElectrumServerToDefault(
|
||||||
|
{@required SharedPreferences sharedPreferences,
|
||||||
|
@required Box<Node> nodes}) async {
|
||||||
|
final server = getBitcoinDefaultElectrumServer(nodes: nodes);
|
||||||
|
final serverId = server?.key as int ?? 0;
|
||||||
|
|
||||||
|
await sharedPreferences.setInt('current_node_id_btc', serverId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> replaceDefaultNode(
|
Future<void> replaceDefaultNode(
|
||||||
|
@ -126,7 +159,7 @@ Future<void> replaceDefaultNode(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await changeCurrentNodeToDefault(
|
await changeMoneroCurrentNodeToDefault(
|
||||||
sharedPreferences: sharedPreferences, nodes: nodes);
|
sharedPreferences: sharedPreferences, nodes: nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,16 @@ part 'node.g.dart';
|
||||||
|
|
||||||
@HiveType(typeId: 1)
|
@HiveType(typeId: 1)
|
||||||
class Node extends HiveObject {
|
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;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node.fromMap(Map map)
|
Node.fromMap(Map map)
|
||||||
: uri = (map['uri'] ?? '') as String,
|
: uri = map['uri'] as String ?? '',
|
||||||
login = map['login'] as String,
|
login = map['login'] as String,
|
||||||
password = map['password'] as String,
|
password = map['password'] as String,
|
||||||
typeRaw = map['typeRaw'] as int;
|
typeRaw = map['typeRaw'] as int;
|
||||||
|
|
|
@ -10,7 +10,10 @@ Future<List<Node>> loadDefaultNodes() async {
|
||||||
|
|
||||||
return nodes.map((dynamic raw) {
|
return nodes.map((dynamic raw) {
|
||||||
if (raw is Map) {
|
if (raw is Map) {
|
||||||
return Node.fromMap(raw);
|
final node = Node.fromMap(raw);
|
||||||
|
node?.type = WalletType.monero;
|
||||||
|
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -38,13 +41,7 @@ Future resetToDefault(Box<Node> nodeSource) async {
|
||||||
final moneroNodes = await loadDefaultNodes();
|
final moneroNodes = await loadDefaultNodes();
|
||||||
final bitcoinElectrumServerList = await loadElectrumServerList();
|
final bitcoinElectrumServerList = await loadElectrumServerList();
|
||||||
final nodes = moneroNodes + bitcoinElectrumServerList;
|
final nodes = moneroNodes + bitcoinElectrumServerList;
|
||||||
final entities = <int, Node>{};
|
|
||||||
|
|
||||||
await nodeSource.clear();
|
await nodeSource.clear();
|
||||||
|
await nodeSource.addAll(nodes);
|
||||||
for (var i = 0; i < nodes.length; i++) {
|
|
||||||
entities[i] = nodes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
await nodeSource.putAll(entities);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,10 +50,7 @@ class DashboardPage extends BasePage {
|
||||||
padding: EdgeInsets.all(0),
|
padding: EdgeInsets.all(0),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await showDialog<void>(
|
await showDialog<void>(
|
||||||
builder: (_) => MenuWidget(
|
builder: (_) => MenuWidget(walletViewModel),
|
||||||
name: walletViewModel.name,
|
|
||||||
subname: walletViewModel.subname,
|
|
||||||
type: walletViewModel.type),
|
|
||||||
context: context);
|
context: context);
|
||||||
},
|
},
|
||||||
child: menuButton
|
child: menuButton
|
||||||
|
|
|
@ -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/screens/auth/auth_page.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||||
|
|
||||||
|
// FIXME: terrible design
|
||||||
|
|
||||||
class WalletMenu {
|
class WalletMenu {
|
||||||
WalletMenu(this.context);
|
WalletMenu(this.context, this.reconnect);
|
||||||
|
|
||||||
final List<String> items = [
|
final List<String> items = [
|
||||||
S.current.reconnect,
|
S.current.reconnect,
|
||||||
|
@ -30,6 +32,7 @@ class WalletMenu {
|
||||||
];
|
];
|
||||||
|
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
|
final Future<void> Function() reconnect;
|
||||||
|
|
||||||
void action(int index) {
|
void action(int index) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
|
@ -70,8 +73,6 @@ class WalletMenu {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _presentReconnectAlert(BuildContext context) async {
|
Future<void> _presentReconnectAlert(BuildContext context) async {
|
||||||
final walletStore = Provider.of<WalletStore>(context);
|
|
||||||
|
|
||||||
await showDialog<void>(
|
await showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
|
@ -80,12 +81,11 @@ class WalletMenu {
|
||||||
alertContent: S.of(context).reconnect_alert_text,
|
alertContent: S.of(context).reconnect_alert_text,
|
||||||
leftButtonText: S.of(context).ok,
|
leftButtonText: S.of(context).ok,
|
||||||
rightButtonText: S.of(context).cancel,
|
rightButtonText: S.of(context).cancel,
|
||||||
actionLeftButton: () {
|
actionLeftButton: () async {
|
||||||
walletStore.reconnect();
|
await reconnect?.call();
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
actionRightButton: () => Navigator.of(context).pop()
|
actionRightButton: () => Navigator.of(context).pop());
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||||
import 'package:cake_wallet/src/screens/dashboard/wallet_menu.dart';
|
import 'package:cake_wallet/src/screens/dashboard/wallet_menu.dart';
|
||||||
|
|
||||||
class MenuWidget extends StatefulWidget {
|
// FIXME: terrible design.
|
||||||
MenuWidget({this.type, this.name, this.subname});
|
|
||||||
|
|
||||||
final WalletType type;
|
class MenuWidget extends StatefulWidget {
|
||||||
final String name;
|
MenuWidget(this.dashboardViewModel);
|
||||||
final String subname;
|
|
||||||
|
final DashboardViewModel dashboardViewModel;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MenuWidgetState createState() => MenuWidgetState();
|
MenuWidgetState createState() => MenuWidgetState();
|
||||||
|
@ -65,8 +66,8 @@ class MenuWidgetState extends State<MenuWidget> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final walletMenu = WalletMenu(context);
|
final walletMenu =
|
||||||
// final walletStore = Provider.of<WalletStore>(context);
|
WalletMenu(context, () async => widget.dashboardViewModel.reconnect());
|
||||||
final itemCount = walletMenu.items.length;
|
final itemCount = walletMenu.items.length;
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
|
@ -118,19 +119,20 @@ class MenuWidgetState extends State<MenuWidget> {
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
_iconFor(type: widget.type),
|
_iconFor(type: widget.dashboardViewModel.type),
|
||||||
SizedBox(width: 16),
|
SizedBox(width: 16),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: widget.subname != null
|
mainAxisAlignment:
|
||||||
|
widget.dashboardViewModel.subname != null
|
||||||
? MainAxisAlignment.spaceBetween
|
? MainAxisAlignment.spaceBetween
|
||||||
: MainAxisAlignment.center,
|
: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
widget.name,
|
widget.dashboardViewModel.name,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.primaryTextTheme
|
.primaryTextTheme
|
||||||
|
@ -141,9 +143,9 @@ class MenuWidgetState extends State<MenuWidget> {
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.bold),
|
fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
if (widget.subname != null)
|
if (widget.dashboardViewModel.subname != null)
|
||||||
Text(
|
Text(
|
||||||
widget.subname,
|
widget.dashboardViewModel.subname,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.primaryTextTheme
|
.primaryTextTheme
|
||||||
|
|
|
@ -74,15 +74,41 @@ class NodeListPage extends BasePage {
|
||||||
}
|
}
|
||||||
|
|
||||||
final node = nodeListViewModel.nodes[index];
|
final node = nodeListViewModel.nodes[index];
|
||||||
final isSelected = index == 1; // FIXME: hardcoded value.
|
|
||||||
final nodeListRow = NodeListRow(
|
final nodeListRow = NodeListRow(
|
||||||
title: node.uri,
|
title: node.value.uri,
|
||||||
isSelected: isSelected,
|
isSelected: node.isSelected,
|
||||||
isAlive: node.requestNode(),
|
isAlive: node.value.requestNode(),
|
||||||
onTap: (_) {});
|
onTap: (_) async {
|
||||||
|
if (node.isSelected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
content: Text(
|
||||||
|
S.of(context).change_current_node(node.value.uri),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
actions: <Widget>[
|
||||||
|
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(
|
final dismissibleRow = Dismissible(
|
||||||
key: Key('${node.key}'),
|
key: Key('${node.value.key}'),
|
||||||
confirmDismiss: (direction) async {
|
confirmDismiss: (direction) async {
|
||||||
return await showDialog(
|
return await showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -99,7 +125,7 @@ class NodeListPage extends BasePage {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onDismissed: (direction) async =>
|
onDismissed: (direction) async =>
|
||||||
nodeListViewModel.delete(node),
|
nodeListViewModel.delete(node.value),
|
||||||
direction: DismissDirection.endToStart,
|
direction: DismissDirection.endToStart,
|
||||||
background: Container(
|
background: Container(
|
||||||
padding: EdgeInsets.only(right: 10.0),
|
padding: EdgeInsets.only(right: 10.0),
|
||||||
|
@ -120,7 +146,7 @@ class NodeListPage extends BasePage {
|
||||||
)),
|
)),
|
||||||
child: nodeListRow);
|
child: nodeListRow);
|
||||||
|
|
||||||
return isSelected ? nodeListRow : dismissibleRow;
|
return node.isSelected ? nodeListRow : dismissibleRow;
|
||||||
},
|
},
|
||||||
itemCounter: (int sectionIndex) {
|
itemCounter: (int sectionIndex) {
|
||||||
if (sectionIndex == 0) {
|
if (sectionIndex == 0) {
|
||||||
|
|
|
@ -63,14 +63,6 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||||
itemBuilder: (__, index) {
|
itemBuilder: (__, index) {
|
||||||
final wallet = widget.walletListViewModel.wallets[index];
|
final wallet = widget.walletListViewModel.wallets[index];
|
||||||
final screenWidth = MediaQuery.of(context).size.width;
|
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 walletMenu = WalletMenu(context, widget.walletListViewModel);
|
||||||
final items =
|
final items =
|
||||||
walletMenu.generateItemsForWalletMenu(wallet.isCurrent);
|
walletMenu.generateItemsForWalletMenu(wallet.isCurrent);
|
||||||
|
|
|
@ -109,7 +109,7 @@ class WalletMenu {
|
||||||
try {
|
try {
|
||||||
auth.changeProcessText(
|
auth.changeProcessText(
|
||||||
S.of(context).wallet_list_removing_wallet(wallet.name));
|
S.of(context).wallet_list_removing_wallet(wallet.name));
|
||||||
// await _walletListStore.remove(wallet);
|
await walletListViewModel.remove(wallet);
|
||||||
auth.close();
|
auth.close();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
auth.changeProcessText(S
|
auth.changeProcessText(S
|
||||||
|
|
|
@ -42,7 +42,7 @@ abstract class SettingsStoreBase with Store {
|
||||||
_sharedPreferences = sharedPreferences;
|
_sharedPreferences = sharedPreferences;
|
||||||
_nodes = nodes;
|
_nodes = nodes;
|
||||||
allowBiometricalAuthentication = initialAllowBiometricalAuthentication;
|
allowBiometricalAuthentication = initialAllowBiometricalAuthentication;
|
||||||
isDarkTheme = initialDarkTheme;
|
isDarkTheme = true;
|
||||||
defaultPinLength = initialPinLength;
|
defaultPinLength = initialPinLength;
|
||||||
languageCode = initialLanguageCode;
|
languageCode = initialLanguageCode;
|
||||||
currentLocale = initialCurrentLocale;
|
currentLocale = initialCurrentLocale;
|
||||||
|
@ -143,7 +143,7 @@ abstract class SettingsStoreBase with Store {
|
||||||
bool allowBiometricalAuthentication;
|
bool allowBiometricalAuthentication;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
bool isDarkTheme;
|
bool isDarkTheme = true;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
int defaultPinLength;
|
int defaultPinLength;
|
||||||
|
@ -285,7 +285,7 @@ abstract class SettingsStoreBase with Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future setCurrentNodeToDefault() async {
|
Future setCurrentNodeToDefault() async {
|
||||||
await changeCurrentNodeToDefault(sharedPreferences: _sharedPreferences, nodes: _nodes);
|
// await changeCurrentNodeToDefault(sharedPreferences: _sharedPreferences, nodes: _nodes);
|
||||||
await loadSettings();
|
await loadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:cake_wallet/di.dart';
|
import 'package:cake_wallet/di.dart';
|
||||||
|
import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
@ -29,8 +30,9 @@ abstract class SettingsStoreBase with Store {
|
||||||
@required int initialPinLength,
|
@required int initialPinLength,
|
||||||
@required String initialLanguageCode,
|
@required String initialLanguageCode,
|
||||||
@required String initialCurrentLocale,
|
@required String initialCurrentLocale,
|
||||||
@required this.node,
|
// @required this.node,
|
||||||
@required this.appVersion,
|
@required this.appVersion,
|
||||||
|
@required Map<WalletType, Node> nodes,
|
||||||
this.actionlistDisplayMode}) {
|
this.actionlistDisplayMode}) {
|
||||||
fiatCurrency = initialFiatCurrency;
|
fiatCurrency = initialFiatCurrency;
|
||||||
transactionPriority = initialTransactionPriority;
|
transactionPriority = initialTransactionPriority;
|
||||||
|
@ -44,9 +46,11 @@ abstract class SettingsStoreBase with Store {
|
||||||
itemHeaders = {};
|
itemHeaders = {};
|
||||||
_sharedPreferences = sharedPreferences;
|
_sharedPreferences = sharedPreferences;
|
||||||
_nodeSource = nodeSource;
|
_nodeSource = nodeSource;
|
||||||
|
_nodes = nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const currentNodeIdKey = 'current_node_id';
|
static const currentNodeIdKey = 'current_node_id';
|
||||||
|
static const currentBitcoinElectrumSererIdKey = 'current_node_id_btc';
|
||||||
static const currentFiatCurrencyKey = 'current_fiat_currency';
|
static const currentFiatCurrencyKey = 'current_fiat_currency';
|
||||||
static const currentTransactionPriorityKey = 'current_fee_priority';
|
static const currentTransactionPriorityKey = 'current_fee_priority';
|
||||||
static const currentBalanceDisplayModeKey = 'current_balance_display_mode';
|
static const currentBalanceDisplayModeKey = 'current_balance_display_mode';
|
||||||
|
@ -58,8 +62,8 @@ abstract class SettingsStoreBase with Store {
|
||||||
static const currentPinLength = 'current_pin_length';
|
static const currentPinLength = 'current_pin_length';
|
||||||
static const currentLanguageCode = 'language_code';
|
static const currentLanguageCode = 'language_code';
|
||||||
|
|
||||||
@observable
|
// @observable
|
||||||
Node node;
|
// Node node;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
FiatCurrency fiatCurrency;
|
FiatCurrency fiatCurrency;
|
||||||
|
@ -97,6 +101,26 @@ abstract class SettingsStoreBase with Store {
|
||||||
SharedPreferences _sharedPreferences;
|
SharedPreferences _sharedPreferences;
|
||||||
Box<Node> _nodeSource;
|
Box<Node> _nodeSource;
|
||||||
|
|
||||||
|
Map<WalletType, Node> _nodes;
|
||||||
|
|
||||||
|
Node getCurrentNode(WalletType walletType) => _nodes[walletType];
|
||||||
|
|
||||||
|
Future<void> 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<SettingsStore> load(
|
static Future<SettingsStore> load(
|
||||||
{@required Box<Node> nodeSource,
|
{@required Box<Node> nodeSource,
|
||||||
FiatCurrency initialFiatCurrency = FiatCurrency.usd,
|
FiatCurrency initialFiatCurrency = FiatCurrency.usd,
|
||||||
|
@ -126,12 +150,18 @@ abstract class SettingsStoreBase with Store {
|
||||||
await Language.localeDetection();
|
await Language.localeDetection();
|
||||||
final initialCurrentLocale = await Devicelocale.currentLocale;
|
final initialCurrentLocale = await Devicelocale.currentLocale;
|
||||||
final nodeId = sharedPreferences.getInt(currentNodeIdKey);
|
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();
|
final packageInfo = await PackageInfo.fromPlatform();
|
||||||
|
|
||||||
return SettingsStore(
|
return SettingsStore(
|
||||||
sharedPreferences: sharedPreferences,
|
sharedPreferences: sharedPreferences,
|
||||||
node: node,
|
nodes: {
|
||||||
|
WalletType.monero: moneroNode,
|
||||||
|
WalletType.bitcoin: bitcoinElectrumServer
|
||||||
|
},
|
||||||
nodeSource: nodeSource,
|
nodeSource: nodeSource,
|
||||||
appVersion: packageInfo.version,
|
appVersion: packageInfo.version,
|
||||||
initialFiatCurrency: currentFiatCurrency,
|
initialFiatCurrency: currentFiatCurrency,
|
||||||
|
|
45
lib/utils/mobx.dart
Normal file
45
lib/utils/mobx.dart
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
||||||
|
Dispose connectDifferent<T, Y>(ObservableList<T> source, ObservableList<Y> dest,
|
||||||
|
Y Function(T) transform, {bool Function(T) filter}) {
|
||||||
|
return source.observe((change) {
|
||||||
|
switch (change.type) {
|
||||||
|
case OperationType.add:
|
||||||
|
final _values = change.added;
|
||||||
|
Iterable<T> 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<T>(ObservableList<T> source, ObservableList<T> 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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -129,6 +129,11 @@ abstract class DashboardViewModelBase with Store {
|
||||||
|
|
||||||
ReactionDisposer _reaction;
|
ReactionDisposer _reaction;
|
||||||
|
|
||||||
|
Future<void> reconnect() async {
|
||||||
|
final node = appStore.settingsStore.getCurrentNode(wallet.type);
|
||||||
|
await wallet.connectToNode(node: node);
|
||||||
|
}
|
||||||
|
|
||||||
void _onWalletChange(WalletBase wallet) {
|
void _onWalletChange(WalletBase wallet) {
|
||||||
name = wallet.name;
|
name = wallet.name;
|
||||||
transactions.clear();
|
transactions.clear();
|
||||||
|
|
|
@ -1,26 +1,92 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:cake_wallet/core/wallet_base.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.dart';
|
||||||
import 'package:cake_wallet/src/domain/common/node_list.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/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';
|
part 'node_list_view_model.g.dart';
|
||||||
|
|
||||||
class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
|
class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
|
||||||
|
|
||||||
abstract class NodeListViewModelBase with Store {
|
class ItemCell<Item> {
|
||||||
NodeListViewModelBase(this._nodeListStore, this._nodeSource, this._wallet);
|
ItemCell(this.value, {@required this.isSelected});
|
||||||
|
|
||||||
@computed
|
final Item value;
|
||||||
ObservableList<Node> get nodes => ObservableList<Node>.of(
|
final bool isSelected;
|
||||||
_nodeListStore.nodes.where((node) => node.type == _wallet.type));
|
}
|
||||||
|
|
||||||
|
abstract class NodeListViewModelBase with Store {
|
||||||
|
NodeListViewModelBase(
|
||||||
|
this._nodeListStore, this._nodeSource, this._wallet, this._settingsStore)
|
||||||
|
: nodes = ObservableList<ItemCell<Node>>() {
|
||||||
|
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<Node>(val, isSelected: val.key == currentNode.key)));
|
||||||
|
connectDifferent(
|
||||||
|
_nodeListStore.nodes,
|
||||||
|
nodes,
|
||||||
|
(Node val) =>
|
||||||
|
ItemCell<Node>(val, isSelected: val.key == currentNode.key),
|
||||||
|
filter: (Node val) {
|
||||||
|
return val.type == _wallet.type;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ObservableList<ItemCell<Node>> nodes;
|
||||||
|
|
||||||
final WalletBase _wallet;
|
final WalletBase _wallet;
|
||||||
final Box<Node> _nodeSource;
|
final Box<Node> _nodeSource;
|
||||||
final NodeListStore _nodeListStore;
|
final NodeListStore _nodeListStore;
|
||||||
|
final SettingsStore _settingsStore;
|
||||||
|
|
||||||
Future<void> reset() async => await resetToDefault(_nodeSource);
|
Future<void> reset() async {
|
||||||
|
await resetToDefault(_nodeSource);
|
||||||
|
|
||||||
Future<void> 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<void> delete(Node node) async => _nodeSource.delete(node.key);
|
||||||
|
|
||||||
|
Future<void> 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<Node>(item.value, isSelected: isSelected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ abstract class SendViewModelBase with Store {
|
||||||
this._wallet, this._settingsStore, this._fiatConversationStore)
|
this._wallet, this._settingsStore, this._fiatConversationStore)
|
||||||
: state = InitialSendViewModelState(),
|
: state = InitialSendViewModelState(),
|
||||||
_cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12,
|
_cryptoNumberFormat = NumberFormat()..maximumFractionDigits = 12,
|
||||||
|
// FIXME: need to be based on wallet type.
|
||||||
all = false;
|
all = false;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
|
@ -79,7 +80,7 @@ abstract class SendViewModelBase with Store {
|
||||||
final WalletBase _wallet;
|
final WalletBase _wallet;
|
||||||
final SettingsStore _settingsStore;
|
final SettingsStore _settingsStore;
|
||||||
final FiatConvertationStore _fiatConversationStore;
|
final FiatConvertationStore _fiatConversationStore;
|
||||||
NumberFormat _cryptoNumberFormat;
|
final NumberFormat _cryptoNumberFormat;
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void setAll() => all = true;
|
void setAll() => all = true;
|
||||||
|
@ -129,7 +130,8 @@ abstract class SendViewModelBase with Store {
|
||||||
void _updateFiatAmount() {
|
void _updateFiatAmount() {
|
||||||
try {
|
try {
|
||||||
final fiat = calculateFiatAmount(
|
final fiat = calculateFiatAmount(
|
||||||
price: _fiatConversationStore.price, cryptoAmount: cryptoAmount);
|
price: _fiatConversationStore.price,
|
||||||
|
cryptoAmount: cryptoAmount.replaceAll(',', '.'));
|
||||||
if (fiatAmount != fiat) {
|
if (fiatAmount != fiat) {
|
||||||
fiatAmount = fiat;
|
fiatAmount = fiat;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +143,8 @@ abstract class SendViewModelBase with Store {
|
||||||
@action
|
@action
|
||||||
void _updateCryptoAmount() {
|
void _updateCryptoAmount() {
|
||||||
try {
|
try {
|
||||||
final crypto = double.parse(fiatAmount) / _fiatConversationStore.price;
|
final crypto = double.parse(fiatAmount.replaceAll(',', '.')) /
|
||||||
|
_fiatConversationStore.price;
|
||||||
final cryptoAmountTmp = _cryptoNumberFormat.format(crypto);
|
final cryptoAmountTmp = _cryptoNumberFormat.format(crypto);
|
||||||
|
|
||||||
if (cryptoAmount != cryptoAmountTmp) {
|
if (cryptoAmount != cryptoAmountTmp) {
|
||||||
|
|
|
@ -23,7 +23,8 @@ class SettingsViewModel = SettingsViewModelBase with _$SettingsViewModel;
|
||||||
|
|
||||||
abstract class SettingsViewModelBase with Store {
|
abstract class SettingsViewModelBase with Store {
|
||||||
SettingsViewModelBase(this._settingsStore, WalletBase wallet)
|
SettingsViewModelBase(this._settingsStore, WalletBase wallet)
|
||||||
: itemHeaders = {} {
|
: itemHeaders = {},
|
||||||
|
_walletType = wallet.type {
|
||||||
sections = [
|
sections = [
|
||||||
[
|
[
|
||||||
PickerListItem(
|
PickerListItem(
|
||||||
|
@ -117,7 +118,7 @@ abstract class SettingsViewModelBase with Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
Node get node => _settingsStore.node;
|
Node get node => _settingsStore.getCurrentNode(_walletType);
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency;
|
FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency;
|
||||||
|
@ -150,13 +151,10 @@ abstract class SettingsViewModelBase with Store {
|
||||||
set allowBiometricalAuthentication(bool value) =>
|
set allowBiometricalAuthentication(bool value) =>
|
||||||
_settingsStore.allowBiometricalAuthentication = value;
|
_settingsStore.allowBiometricalAuthentication = value;
|
||||||
|
|
||||||
// @observable
|
|
||||||
|
|
||||||
// @observable
|
|
||||||
|
|
||||||
final Map<String, String> itemHeaders;
|
final Map<String, String> itemHeaders;
|
||||||
List<List<SettingsListItem>> sections;
|
|
||||||
final SettingsStore _settingsStore;
|
final SettingsStore _settingsStore;
|
||||||
|
final WalletType _walletType;
|
||||||
|
List<List<SettingsListItem>> sections;
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void toggleTransactionsDisplay() =>
|
void toggleTransactionsDisplay() =>
|
||||||
|
|
|
@ -3,9 +3,10 @@ import 'package:cake_wallet/src/domain/common/wallet_type.dart';
|
||||||
|
|
||||||
class WalletListItem {
|
class WalletListItem {
|
||||||
const 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 String name;
|
||||||
final WalletType type;
|
final WalletType type;
|
||||||
final bool isCurrent;
|
final bool isCurrent;
|
||||||
|
final dynamic key;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,7 @@ abstract class WalletListViewModelBase with Store {
|
||||||
WalletListViewModelBase(
|
WalletListViewModelBase(
|
||||||
this._walletInfoSource, this._appStore, this._keyService) {
|
this._walletInfoSource, this._appStore, this._keyService) {
|
||||||
wallets = ObservableList<WalletListItem>();
|
wallets = ObservableList<WalletListItem>();
|
||||||
wallets.addAll(_walletInfoSource.values.map((info) => WalletListItem(
|
_updateList();
|
||||||
name: info.name,
|
|
||||||
type: info.type,
|
|
||||||
isCurrent: info.name == _appStore.wallet.name &&
|
|
||||||
info.type == _appStore.wallet.type)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
|
@ -40,7 +36,12 @@ abstract class WalletListViewModelBase with Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
Future<void> remove(WalletListItem wallet) async {}
|
Future<void> remove(WalletListItem wallet) async {
|
||||||
|
final walletService = _getWalletService(wallet.type);
|
||||||
|
await walletService.remove(wallet.name);
|
||||||
|
await _walletInfoSource.delete(wallet.key);
|
||||||
|
_updateList();
|
||||||
|
}
|
||||||
|
|
||||||
WalletService _getWalletService(WalletType type) {
|
WalletService _getWalletService(WalletType type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -52,4 +53,14 @@ abstract class WalletListViewModelBase with Store {
|
||||||
return null;
|
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)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue