mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-03-22 23:28:53 +00:00
pow node changes
This commit is contained in:
parent
32554b4cc8
commit
d3c76b6d55
14 changed files with 632 additions and 170 deletions
|
@ -22,6 +22,7 @@ class NanoClient {
|
||||||
|
|
||||||
StreamSubscription<Transfer>? subscription;
|
StreamSubscription<Transfer>? subscription;
|
||||||
Node? _node;
|
Node? _node;
|
||||||
|
Node? _powNode;
|
||||||
|
|
||||||
bool connect(Node node) {
|
bool connect(Node node) {
|
||||||
try {
|
try {
|
||||||
|
@ -32,6 +33,15 @@ class NanoClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool connectPow(Node node) {
|
||||||
|
try {
|
||||||
|
_powNode = node;
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<NanoBalance> getBalance(String address) async {
|
Future<NanoBalance> getBalance(String address) async {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
_node!.uri,
|
_node!.uri,
|
||||||
|
@ -117,7 +127,7 @@ class NanoClient {
|
||||||
Future<String> requestWork(String hash) async {
|
Future<String> requestWork(String hash) async {
|
||||||
return http
|
return http
|
||||||
.post(
|
.post(
|
||||||
Uri.parse("https://rpc.nano.to"), // TODO: make a setting
|
_powNode!.uri,
|
||||||
headers: {'Content-type': 'application/json'},
|
headers: {'Content-type': 'application/json'},
|
||||||
body: json.encode(
|
body: json.encode(
|
||||||
{
|
{
|
||||||
|
|
|
@ -134,6 +134,11 @@ abstract class NanoWalletBase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> connectToPowNode({required Node node}) async {
|
||||||
|
_client.connectPow(node);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||||
credentials = credentials as NanoTransactionCredentials;
|
credentials = credentials as NanoTransactionCredentials;
|
||||||
|
@ -237,9 +242,7 @@ abstract class NanoWalletBase
|
||||||
id: transactionModel.hash,
|
id: transactionModel.hash,
|
||||||
amountRaw: transactionModel.amount,
|
amountRaw: transactionModel.amount,
|
||||||
height: transactionModel.height,
|
height: transactionModel.height,
|
||||||
direction: transactionModel.account == address
|
direction: transactionModel.type == "send" ? TransactionDirection.outgoing : TransactionDirection.incoming,
|
||||||
? TransactionDirection.outgoing
|
|
||||||
: TransactionDirection.incoming,
|
|
||||||
confirmed: transactionModel.confirmed,
|
confirmed: transactionModel.confirmed,
|
||||||
date: transactionModel.date ?? DateTime.now(),
|
date: transactionModel.date ?? DateTime.now(),
|
||||||
confirmations: transactionModel.confirmed ? 1 : 0,
|
confirmations: transactionModel.confirmed ? 1 : 0,
|
||||||
|
|
18
lib/di.dart
18
lib/di.dart
|
@ -27,6 +27,7 @@ import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart';
|
import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/display_settings_page.dart';
|
import 'package:cake_wallet/src/screens/settings/display_settings_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart';
|
import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/settings/manage_pow_nodes_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/other_settings_page.dart';
|
import 'package:cake_wallet/src/screens/settings/other_settings_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/privacy_page.dart';
|
import 'package:cake_wallet/src/screens/settings/privacy_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/security_backup_page.dart';
|
import 'package:cake_wallet/src/screens/settings/security_backup_page.dart';
|
||||||
|
@ -68,6 +69,8 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart';
|
||||||
import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart';
|
import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart';
|
import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart';
|
import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart';
|
||||||
|
import 'package:cake_wallet/view_model/node_list/pow_node_create_or_edit_view_model.dart';
|
||||||
|
import 'package:cake_wallet/view_model/node_list/pow_node_list_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart';
|
import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart';
|
||||||
import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
|
import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
|
import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
|
||||||
|
@ -212,7 +215,6 @@ final getIt = GetIt.instance;
|
||||||
var _isSetupFinished = false;
|
var _isSetupFinished = false;
|
||||||
late Box<WalletInfo> _walletInfoSource;
|
late Box<WalletInfo> _walletInfoSource;
|
||||||
late Box<Node> _nodeSource;
|
late Box<Node> _nodeSource;
|
||||||
late Box<Node> _powNodeSource;
|
|
||||||
late Box<Contact> _contactSource;
|
late Box<Contact> _contactSource;
|
||||||
late Box<Trade> _tradesSource;
|
late Box<Trade> _tradesSource;
|
||||||
late Box<Template> _templates;
|
late Box<Template> _templates;
|
||||||
|
@ -259,6 +261,7 @@ Future setup({
|
||||||
|
|
||||||
final settingsStore = await SettingsStoreBase.load(
|
final settingsStore = await SettingsStoreBase.load(
|
||||||
nodeSource: _nodeSource,
|
nodeSource: _nodeSource,
|
||||||
|
powNodeSource: _nodeSource,
|
||||||
isBitcoinBuyEnabled: isBitcoinBuyEnabled,
|
isBitcoinBuyEnabled: isBitcoinBuyEnabled,
|
||||||
// Enforce darkTheme on platforms other than mobile till the design for other themes is completed
|
// Enforce darkTheme on platforms other than mobile till the design for other themes is completed
|
||||||
initialTheme: ResponsiveLayoutUtil.instance.isMobile && DeviceInfo.instance.isMobile
|
initialTheme: ResponsiveLayoutUtil.instance.isMobile && DeviceInfo.instance.isMobile
|
||||||
|
@ -687,7 +690,12 @@ Future setup({
|
||||||
|
|
||||||
getIt.registerFactory(() {
|
getIt.registerFactory(() {
|
||||||
final appStore = getIt.get<AppStore>();
|
final appStore = getIt.get<AppStore>();
|
||||||
return NodeListViewModel(_nodeSource, _powNodeSource, appStore);
|
return NodeListViewModel(_nodeSource, appStore);
|
||||||
|
});
|
||||||
|
|
||||||
|
getIt.registerFactory(() {
|
||||||
|
final appStore = getIt.get<AppStore>();
|
||||||
|
return PowNodeListViewModel(_nodeSource, appStore);
|
||||||
});
|
});
|
||||||
|
|
||||||
getIt.registerFactory(() => ConnectionSyncPage(getIt.get<DashboardViewModel>()));
|
getIt.registerFactory(() => ConnectionSyncPage(getIt.get<DashboardViewModel>()));
|
||||||
|
@ -707,6 +715,10 @@ Future setup({
|
||||||
NodeCreateOrEditViewModel(
|
NodeCreateOrEditViewModel(
|
||||||
_nodeSource, type ?? getIt.get<AppStore>().wallet!.type, getIt.get<SettingsStore>()));
|
_nodeSource, type ?? getIt.get<AppStore>().wallet!.type, getIt.get<SettingsStore>()));
|
||||||
|
|
||||||
|
getIt.registerFactoryParam<PowNodeCreateOrEditViewModel, WalletType?, void>(
|
||||||
|
(WalletType? type, _) => PowNodeCreateOrEditViewModel(
|
||||||
|
_nodeSource, type ?? getIt.get<AppStore>().wallet!.type, getIt.get<SettingsStore>()));
|
||||||
|
|
||||||
getIt.registerFactoryParam<NodeCreateOrEditPage, Node?, bool?>(
|
getIt.registerFactoryParam<NodeCreateOrEditPage, Node?, bool?>(
|
||||||
(Node? editingNode, bool? isSelected) => NodeCreateOrEditPage(
|
(Node? editingNode, bool? isSelected) => NodeCreateOrEditPage(
|
||||||
nodeCreateOrEditViewModel: getIt.get<NodeCreateOrEditViewModel>(),
|
nodeCreateOrEditViewModel: getIt.get<NodeCreateOrEditViewModel>(),
|
||||||
|
@ -1068,6 +1080,8 @@ Future setup({
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactory<ManageNodesPage>(() => ManageNodesPage(getIt.get<NodeListViewModel>()));
|
getIt.registerFactory<ManageNodesPage>(() => ManageNodesPage(getIt.get<NodeListViewModel>()));
|
||||||
|
getIt.registerFactory<ManagePowNodesPage>(
|
||||||
|
() => ManagePowNodesPage(getIt.get<PowNodeListViewModel>()));
|
||||||
|
|
||||||
_isSetupFinished = true;
|
_isSetupFinished = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,4 +13,11 @@ void startOnCurrentNodeChangeReaction(AppStore appStore) {
|
||||||
print(e.toString());
|
print(e.toString());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
appStore.settingsStore.powNodes.observe((change) async {
|
||||||
|
try {
|
||||||
|
await appStore.wallet!.connectToPowNode(node: change.newValue!);
|
||||||
|
} catch (e) {
|
||||||
|
print(e.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ ReactionDisposer? _onCurrentWalletChangeReaction;
|
||||||
ReactionDisposer? _onCurrentWalletChangeFiatRateUpdateReaction;
|
ReactionDisposer? _onCurrentWalletChangeFiatRateUpdateReaction;
|
||||||
//ReactionDisposer _onCurrentWalletAddressChangeReaction;
|
//ReactionDisposer _onCurrentWalletAddressChangeReaction;
|
||||||
|
|
||||||
void startCurrentWalletChangeReaction(AppStore appStore,
|
void startCurrentWalletChangeReaction(
|
||||||
SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
|
AppStore appStore, SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
|
||||||
_onCurrentWalletChangeReaction?.reaction.dispose();
|
_onCurrentWalletChangeReaction?.reaction.dispose();
|
||||||
_onCurrentWalletChangeFiatRateUpdateReaction?.reaction.dispose();
|
_onCurrentWalletChangeFiatRateUpdateReaction?.reaction.dispose();
|
||||||
//_onCurrentWalletAddressChangeReaction?.reaction?dispose();
|
//_onCurrentWalletAddressChangeReaction?.reaction?dispose();
|
||||||
|
@ -48,8 +48,8 @@ void startCurrentWalletChangeReaction(AppStore appStore,
|
||||||
//}
|
//}
|
||||||
//});
|
//});
|
||||||
|
|
||||||
_onCurrentWalletChangeReaction = reaction((_) => appStore.wallet, (WalletBase<
|
_onCurrentWalletChangeReaction = reaction((_) => appStore.wallet,
|
||||||
Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
|
(WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
|
||||||
wallet) async {
|
wallet) async {
|
||||||
try {
|
try {
|
||||||
if (wallet == null) {
|
if (wallet == null) {
|
||||||
|
@ -57,14 +57,19 @@ void startCurrentWalletChangeReaction(AppStore appStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
final node = settingsStore.getCurrentNode(wallet.type);
|
final node = settingsStore.getCurrentNode(wallet.type);
|
||||||
|
|
||||||
startWalletSyncStatusChangeReaction(wallet, fiatConversionStore);
|
startWalletSyncStatusChangeReaction(wallet, fiatConversionStore);
|
||||||
startCheckConnectionReaction(wallet, settingsStore);
|
startCheckConnectionReaction(wallet, settingsStore);
|
||||||
|
await getIt.get<SharedPreferences>().setString(PreferencesKey.currentWalletName, wallet.name);
|
||||||
await getIt
|
await getIt
|
||||||
.get<SharedPreferences>()
|
.get<SharedPreferences>()
|
||||||
.setString(PreferencesKey.currentWalletName, wallet.name);
|
.setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type));
|
||||||
await getIt.get<SharedPreferences>().setInt(
|
|
||||||
PreferencesKey.currentWalletType, serializeToInt(wallet.type));
|
|
||||||
await wallet.connectToNode(node: node);
|
await wallet.connectToNode(node: node);
|
||||||
|
if (wallet.type == WalletType.nano || wallet.type == WalletType.banano) {
|
||||||
|
final powNode = settingsStore.getCurrentPowNode(wallet.type);
|
||||||
|
await wallet.connectToPowNode(node: powNode);
|
||||||
|
}
|
||||||
|
|
||||||
if (wallet.type == WalletType.haven) {
|
if (wallet.type == WalletType.haven) {
|
||||||
await updateHavenRate(fiatConversionStore);
|
await updateHavenRate(fiatConversionStore);
|
||||||
|
@ -82,9 +87,8 @@ void startCurrentWalletChangeReaction(AppStore appStore,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_onCurrentWalletChangeFiatRateUpdateReaction =
|
_onCurrentWalletChangeFiatRateUpdateReaction = reaction((_) => appStore.wallet,
|
||||||
reaction((_) => appStore.wallet, (WalletBase<Balance,
|
(WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
|
||||||
TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
|
|
||||||
wallet) async {
|
wallet) async {
|
||||||
try {
|
try {
|
||||||
if (wallet == null || settingsStore.fiatApiMode == FiatApiMode.disabled) {
|
if (wallet == null || settingsStore.fiatApiMode == FiatApiMode.disabled) {
|
||||||
|
@ -92,8 +96,7 @@ void startCurrentWalletChangeReaction(AppStore appStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
fiatConversionStore.prices[wallet.currency] = 0;
|
fiatConversionStore.prices[wallet.currency] = 0;
|
||||||
fiatConversionStore.prices[wallet.currency] =
|
fiatConversionStore.prices[wallet.currency] = await FiatConversionService.fetchPrice(
|
||||||
await FiatConversionService.fetchPrice(
|
|
||||||
crypto: wallet.currency,
|
crypto: wallet.currency,
|
||||||
fiat: settingsStore.fiatCurrency,
|
fiat: settingsStore.fiatCurrency,
|
||||||
torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly);
|
torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart
|
||||||
import 'package:cake_wallet/src/screens/settings/desktop_settings/desktop_settings_page.dart';
|
import 'package:cake_wallet/src/screens/settings/desktop_settings/desktop_settings_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/display_settings_page.dart';
|
import 'package:cake_wallet/src/screens/settings/display_settings_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart';
|
import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/settings/manage_pow_nodes_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/other_settings_page.dart';
|
import 'package:cake_wallet/src/screens/settings/other_settings_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/privacy_page.dart';
|
import 'package:cake_wallet/src/screens/settings/privacy_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/security_backup_page.dart';
|
import 'package:cake_wallet/src/screens/settings/security_backup_page.dart';
|
||||||
|
@ -573,6 +574,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
case Routes.manageNodes:
|
case Routes.manageNodes:
|
||||||
return MaterialPageRoute<void>(builder: (_) => getIt.get<ManageNodesPage>());
|
return MaterialPageRoute<void>(builder: (_) => getIt.get<ManageNodesPage>());
|
||||||
|
|
||||||
|
case Routes.managePowNodes:
|
||||||
|
return MaterialPageRoute<void>(builder: (_) => getIt.get<ManagePowNodesPage>());
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return MaterialPageRoute<void>(
|
return MaterialPageRoute<void>(
|
||||||
builder: (_) => Scaffold(
|
builder: (_) => Scaffold(
|
||||||
|
|
|
@ -92,4 +92,6 @@ class Routes {
|
||||||
static const homeSettings = '/home_settings';
|
static const homeSettings = '/home_settings';
|
||||||
static const editToken = '/edit_token';
|
static const editToken = '/edit_token';
|
||||||
static const manageNodes = '/manage_nodes';
|
static const manageNodes = '/manage_nodes';
|
||||||
|
static const managePowNodes = '/manage_pow_nodes';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,17 @@ class ConnectionSyncPage extends BasePage {
|
||||||
title: S.current.manage_nodes,
|
title: S.current.manage_nodes,
|
||||||
handler: (context) => Navigator.of(context).pushNamed(Routes.manageNodes),
|
handler: (context) => Navigator.of(context).pushNamed(Routes.manageNodes),
|
||||||
),
|
),
|
||||||
|
Observer(
|
||||||
|
builder: (context) {
|
||||||
|
if (!dashboardViewModel.hasPowNodes)
|
||||||
|
return const SizedBox();
|
||||||
|
|
||||||
|
return SettingsCellWithArrow(
|
||||||
|
title: S.current.manage_nodes,
|
||||||
|
handler: (context) => Navigator.of(context).pushNamed(Routes.managePowNodes),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
86
lib/src/screens/settings/manage_pow_nodes_page.dart
Normal file
86
lib/src/screens/settings/manage_pow_nodes_page.dart
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/nodes/widgets/node_list_row.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||||
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
|
import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
|
||||||
|
import 'package:cake_wallet/view_model/node_list/pow_node_list_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||||
|
|
||||||
|
class ManagePowNodesPage extends BasePage {
|
||||||
|
ManagePowNodesPage(this.nodeListViewModel);
|
||||||
|
|
||||||
|
final PowNodeListViewModel nodeListViewModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get title => S.current.manage_nodes;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget body(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(top: 10),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Semantics(
|
||||||
|
button: true,
|
||||||
|
child: NodeHeaderListRow(
|
||||||
|
title: S.of(context).add_new_node,
|
||||||
|
onTap: (_) async => await Navigator.of(context).pushNamed(Routes.newNode),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
Observer(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return Flexible(
|
||||||
|
child: SectionStandardList(
|
||||||
|
sectionCount: 1,
|
||||||
|
context: context,
|
||||||
|
dividerPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
itemCounter: (int sectionIndex) {
|
||||||
|
return nodeListViewModel.nodes.length;
|
||||||
|
},
|
||||||
|
itemBuilder: (_, sectionIndex, index) {
|
||||||
|
final node = nodeListViewModel.nodes[index];
|
||||||
|
final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex;
|
||||||
|
final nodeListRow = NodeListRow(
|
||||||
|
title: node.uriRaw,
|
||||||
|
node: node,
|
||||||
|
isSelected: isSelected,
|
||||||
|
onTap: (_) async {
|
||||||
|
if (isSelected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await showPopUp<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertWithTwoActions(
|
||||||
|
alertTitle: S.of(context).change_current_node_title,
|
||||||
|
alertContent: nodeListViewModel.getAlertContent(node.uriRaw),
|
||||||
|
leftButtonText: S.of(context).cancel,
|
||||||
|
rightButtonText: S.of(context).change,
|
||||||
|
actionLeftButton: () => Navigator.of(context).pop(),
|
||||||
|
actionRightButton: () async {
|
||||||
|
await nodeListViewModel.setAsCurrent(node);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return nodeListRow;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -82,6 +82,7 @@ abstract class SettingsStoreBase with Store {
|
||||||
TransactionPriority? initialLitecoinTransactionPriority,
|
TransactionPriority? initialLitecoinTransactionPriority,
|
||||||
TransactionPriority? initialEthereumTransactionPriority})
|
TransactionPriority? initialEthereumTransactionPriority})
|
||||||
: nodes = ObservableMap<WalletType, Node>.of(nodes),
|
: nodes = ObservableMap<WalletType, Node>.of(nodes),
|
||||||
|
powNodes = ObservableMap<WalletType, Node>.of(nodes),
|
||||||
_sharedPreferences = sharedPreferences,
|
_sharedPreferences = sharedPreferences,
|
||||||
_backgroundTasks = backgroundTasks,
|
_backgroundTasks = backgroundTasks,
|
||||||
fiatCurrency = initialFiatCurrency,
|
fiatCurrency = initialFiatCurrency,
|
||||||
|
@ -456,6 +457,7 @@ abstract class SettingsStoreBase with Store {
|
||||||
final BackgroundTasks _backgroundTasks;
|
final BackgroundTasks _backgroundTasks;
|
||||||
|
|
||||||
ObservableMap<WalletType, Node> nodes;
|
ObservableMap<WalletType, Node> nodes;
|
||||||
|
ObservableMap<WalletType, Node> powNodes;
|
||||||
|
|
||||||
Node getCurrentNode(WalletType walletType) {
|
Node getCurrentNode(WalletType walletType) {
|
||||||
final node = nodes[walletType];
|
final node = nodes[walletType];
|
||||||
|
@ -467,6 +469,16 @@ abstract class SettingsStoreBase with Store {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node getCurrentPowNode(WalletType walletType) {
|
||||||
|
final node = powNodes[walletType];
|
||||||
|
|
||||||
|
if (node == null) {
|
||||||
|
throw Exception('No pow node found for wallet type: ${walletType.toString()}');
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
bool isBitcoinBuyEnabled;
|
bool isBitcoinBuyEnabled;
|
||||||
|
|
||||||
bool get shouldShowReceiveWarning =>
|
bool get shouldShowReceiveWarning =>
|
||||||
|
@ -477,6 +489,7 @@ abstract class SettingsStoreBase with Store {
|
||||||
|
|
||||||
static Future<SettingsStore> load(
|
static Future<SettingsStore> load(
|
||||||
{required Box<Node> nodeSource,
|
{required Box<Node> nodeSource,
|
||||||
|
required Box<Node> powNodeSource,
|
||||||
required bool isBitcoinBuyEnabled,
|
required bool isBitcoinBuyEnabled,
|
||||||
FiatCurrency initialFiatCurrency = FiatCurrency.usd,
|
FiatCurrency initialFiatCurrency = FiatCurrency.usd,
|
||||||
BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance,
|
BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance,
|
||||||
|
@ -577,8 +590,7 @@ abstract class SettingsStoreBase with Store {
|
||||||
SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0];
|
SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0];
|
||||||
final pinNativeTokenAtTop =
|
final pinNativeTokenAtTop =
|
||||||
sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true;
|
sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true;
|
||||||
final useEtherscan =
|
final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
|
||||||
sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
|
|
||||||
|
|
||||||
// If no value
|
// If no value
|
||||||
if (pinLength == null || pinLength == 0) {
|
if (pinLength == null || pinLength == 0) {
|
||||||
|
@ -601,11 +613,13 @@ abstract class SettingsStoreBase with Store {
|
||||||
final havenNode = nodeSource.get(havenNodeId);
|
final havenNode = nodeSource.get(havenNodeId);
|
||||||
final ethereumNode = nodeSource.get(ethereumNodeId);
|
final ethereumNode = nodeSource.get(ethereumNodeId);
|
||||||
final nanoNode = nodeSource.get(nanoNodeId);
|
final nanoNode = nodeSource.get(nanoNodeId);
|
||||||
|
final nanoPowNode = powNodeSource.get(nanoNodeId);
|
||||||
final packageInfo = await PackageInfo.fromPlatform();
|
final packageInfo = await PackageInfo.fromPlatform();
|
||||||
final deviceName = await _getDeviceName() ?? '';
|
final deviceName = await _getDeviceName() ?? '';
|
||||||
final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true;
|
final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true;
|
||||||
|
|
||||||
final nodes = <WalletType, Node>{};
|
final nodes = <WalletType, Node>{};
|
||||||
|
final powNodes = <WalletType, Node>{};
|
||||||
|
|
||||||
if (moneroNode != null) {
|
if (moneroNode != null) {
|
||||||
nodes[WalletType.monero] = moneroNode;
|
nodes[WalletType.monero] = moneroNode;
|
||||||
|
@ -630,6 +644,9 @@ abstract class SettingsStoreBase with Store {
|
||||||
if (nanoNode != null) {
|
if (nanoNode != null) {
|
||||||
nodes[WalletType.nano] = nanoNode;
|
nodes[WalletType.nano] = nanoNode;
|
||||||
}
|
}
|
||||||
|
if (nanoPowNode != null) {
|
||||||
|
powNodes[WalletType.nano] = nanoPowNode;
|
||||||
|
}
|
||||||
|
|
||||||
final savedSyncMode = SyncMode.all.firstWhere((element) {
|
final savedSyncMode = SyncMode.all.firstWhere((element) {
|
||||||
return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1);
|
return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1);
|
||||||
|
|
|
@ -61,7 +61,7 @@ abstract class DashboardViewModelBase with Store {
|
||||||
FilterItem(
|
FilterItem(
|
||||||
value: () => transactionFilterStore.displayIncoming,
|
value: () => transactionFilterStore.displayIncoming,
|
||||||
caption: S.current.incoming,
|
caption: S.current.incoming,
|
||||||
onChanged:transactionFilterStore.toggleIncoming),
|
onChanged: transactionFilterStore.toggleIncoming),
|
||||||
FilterItem(
|
FilterItem(
|
||||||
value: () => transactionFilterStore.displayOutgoing,
|
value: () => transactionFilterStore.displayOutgoing,
|
||||||
caption: S.current.outgoing,
|
caption: S.current.outgoing,
|
||||||
|
@ -75,28 +75,28 @@ abstract class DashboardViewModelBase with Store {
|
||||||
FilterItem(
|
FilterItem(
|
||||||
value: () => tradeFilterStore.displayAllTrades,
|
value: () => tradeFilterStore.displayAllTrades,
|
||||||
caption: S.current.all_trades,
|
caption: S.current.all_trades,
|
||||||
onChanged: () => tradeFilterStore
|
onChanged: () =>
|
||||||
.toggleDisplayExchange(ExchangeProviderDescription.all)),
|
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.all)),
|
||||||
FilterItem(
|
FilterItem(
|
||||||
value: () => tradeFilterStore.displayChangeNow,
|
value: () => tradeFilterStore.displayChangeNow,
|
||||||
caption: ExchangeProviderDescription.changeNow.title,
|
caption: ExchangeProviderDescription.changeNow.title,
|
||||||
onChanged: () => tradeFilterStore
|
onChanged: () =>
|
||||||
.toggleDisplayExchange(ExchangeProviderDescription.changeNow)),
|
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.changeNow)),
|
||||||
FilterItem(
|
FilterItem(
|
||||||
value: () => tradeFilterStore.displaySideShift,
|
value: () => tradeFilterStore.displaySideShift,
|
||||||
caption: ExchangeProviderDescription.sideShift.title,
|
caption: ExchangeProviderDescription.sideShift.title,
|
||||||
onChanged: () => tradeFilterStore
|
onChanged: () =>
|
||||||
.toggleDisplayExchange(ExchangeProviderDescription.sideShift)),
|
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.sideShift)),
|
||||||
FilterItem(
|
FilterItem(
|
||||||
value: () => tradeFilterStore.displaySimpleSwap,
|
value: () => tradeFilterStore.displaySimpleSwap,
|
||||||
caption: ExchangeProviderDescription.simpleSwap.title,
|
caption: ExchangeProviderDescription.simpleSwap.title,
|
||||||
onChanged: () => tradeFilterStore
|
onChanged: () =>
|
||||||
.toggleDisplayExchange(ExchangeProviderDescription.simpleSwap)),
|
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.simpleSwap)),
|
||||||
FilterItem(
|
FilterItem(
|
||||||
value: () => tradeFilterStore.displayTrocador,
|
value: () => tradeFilterStore.displayTrocador,
|
||||||
caption: ExchangeProviderDescription.trocador.title,
|
caption: ExchangeProviderDescription.trocador.title,
|
||||||
onChanged: () => tradeFilterStore
|
onChanged: () =>
|
||||||
.toggleDisplayExchange(ExchangeProviderDescription.trocador)),
|
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.trocador)),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
subname = '',
|
subname = '',
|
||||||
|
@ -118,15 +118,17 @@ abstract class DashboardViewModelBase with Store {
|
||||||
if (_wallet.type == WalletType.monero) {
|
if (_wallet.type == WalletType.monero) {
|
||||||
subname = monero!.getCurrentAccount(_wallet).label;
|
subname = monero!.getCurrentAccount(_wallet).label;
|
||||||
|
|
||||||
_onMoneroAccountChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet)
|
_onMoneroAccountChangeReaction = reaction(
|
||||||
.account, (Account account) => _onMoneroAccountChange(_wallet));
|
(_) => monero!.getMoneroWalletDetails(wallet).account,
|
||||||
|
(Account account) => _onMoneroAccountChange(_wallet));
|
||||||
|
|
||||||
_onMoneroBalanceChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet).balance,
|
_onMoneroBalanceChangeReaction = reaction(
|
||||||
|
(_) => monero!.getMoneroWalletDetails(wallet).balance,
|
||||||
(MoneroBalance balance) => _onMoneroTransactionsUpdate(_wallet));
|
(MoneroBalance balance) => _onMoneroTransactionsUpdate(_wallet));
|
||||||
|
|
||||||
final _accountTransactions = _wallet
|
final _accountTransactions = _wallet.transactionHistory.transactions.values
|
||||||
.transactionHistory.transactions.values
|
.where((tx) =>
|
||||||
.where((tx) => monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
transactions = ObservableList.of(_accountTransactions.map((transaction) =>
|
transactions = ObservableList.of(_accountTransactions.map((transaction) =>
|
||||||
|
@ -135,9 +137,8 @@ abstract class DashboardViewModelBase with Store {
|
||||||
balanceViewModel: balanceViewModel,
|
balanceViewModel: balanceViewModel,
|
||||||
settingsStore: appStore.settingsStore)));
|
settingsStore: appStore.settingsStore)));
|
||||||
} else {
|
} else {
|
||||||
transactions = ObservableList.of(wallet
|
transactions = ObservableList.of(wallet.transactionHistory.transactions.values.map(
|
||||||
.transactionHistory.transactions.values
|
(transaction) => TransactionListItem(
|
||||||
.map((transaction) => TransactionListItem(
|
|
||||||
transaction: transaction,
|
transaction: transaction,
|
||||||
balanceViewModel: balanceViewModel,
|
balanceViewModel: balanceViewModel,
|
||||||
settingsStore: appStore.settingsStore)));
|
settingsStore: appStore.settingsStore)));
|
||||||
|
@ -151,15 +152,15 @@ abstract class DashboardViewModelBase with Store {
|
||||||
(TransactionInfo? transaction) => TransactionListItem(
|
(TransactionInfo? transaction) => TransactionListItem(
|
||||||
transaction: transaction!,
|
transaction: transaction!,
|
||||||
balanceViewModel: balanceViewModel,
|
balanceViewModel: balanceViewModel,
|
||||||
settingsStore: appStore.settingsStore),
|
settingsStore: appStore.settingsStore), filter: (TransactionInfo? transaction) {
|
||||||
filter: (TransactionInfo? transaction) {
|
|
||||||
if (transaction == null) {
|
if (transaction == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final wallet = _wallet;
|
final wallet = _wallet;
|
||||||
if (wallet.type == WalletType.monero) {
|
if (wallet.type == WalletType.monero) {
|
||||||
return monero!.getTransactionInfoAccountId(transaction) == monero!.getCurrentAccount(wallet).id;
|
return monero!.getTransactionInfoAccountId(transaction) ==
|
||||||
|
monero!.getCurrentAccount(wallet).id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -209,8 +210,7 @@ abstract class DashboardViewModelBase with Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
BalanceDisplayMode get balanceDisplayMode =>
|
BalanceDisplayMode get balanceDisplayMode => appStore.settingsStore.balanceDisplayMode;
|
||||||
appStore.settingsStore.balanceDisplayMode;
|
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
bool get shouldShowMarketPlaceInDashboard {
|
bool get shouldShowMarketPlaceInDashboard {
|
||||||
|
@ -218,14 +218,12 @@ abstract class DashboardViewModelBase with Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
List<TradeListItem> get trades => tradesStore.trades
|
List<TradeListItem> get trades =>
|
||||||
.where((trade) => trade.trade.walletId == wallet.id)
|
tradesStore.trades.where((trade) => trade.trade.walletId == wallet.id).toList();
|
||||||
.toList();
|
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
List<OrderListItem> get orders => ordersStore.orders
|
List<OrderListItem> get orders =>
|
||||||
.where((item) => item.order.walletId == wallet.id)
|
ordersStore.orders.where((item) => item.order.walletId == wallet.id).toList();
|
||||||
.toList();
|
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
List<AnonpayTransactionListItem> get anonpayTransactons => anonpayTransactionsStore.transactions
|
List<AnonpayTransactionListItem> get anonpayTransactons => anonpayTransactionsStore.transactions
|
||||||
|
@ -239,7 +237,8 @@ abstract class DashboardViewModelBase with Store {
|
||||||
List<ActionListItem> get items {
|
List<ActionListItem> get items {
|
||||||
final _items = <ActionListItem>[];
|
final _items = <ActionListItem>[];
|
||||||
|
|
||||||
_items.addAll(transactionFilterStore.filtered(transactions: [...transactions, ...anonpayTransactons]));
|
_items.addAll(
|
||||||
|
transactionFilterStore.filtered(transactions: [...transactions, ...anonpayTransactons]));
|
||||||
_items.addAll(tradeFilterStore.filtered(trades: trades, wallet: wallet));
|
_items.addAll(tradeFilterStore.filtered(trades: trades, wallet: wallet));
|
||||||
_items.addAll(orders);
|
_items.addAll(orders);
|
||||||
|
|
||||||
|
@ -247,8 +246,7 @@ abstract class DashboardViewModelBase with Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>
|
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet;
|
||||||
wallet;
|
|
||||||
|
|
||||||
bool get hasRescan => wallet.type == WalletType.monero || wallet.type == WalletType.haven;
|
bool get hasRescan => wallet.type == WalletType.monero || wallet.type == WalletType.haven;
|
||||||
|
|
||||||
|
@ -277,8 +275,7 @@ abstract class DashboardViewModelBase with Store {
|
||||||
bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup;
|
bool get shouldShowYatPopup => settingsStore.shouldShowYatPopup;
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void furtherShowYatPopup(bool shouldShow) =>
|
void furtherShowYatPopup(bool shouldShow) => settingsStore.shouldShowYatPopup = shouldShow;
|
||||||
settingsStore.shouldShowYatPopup = shouldShow;
|
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
bool get isEnabledExchangeAction => settingsStore.exchangeStatus != ExchangeApiMode.disabled;
|
bool get isEnabledExchangeAction => settingsStore.exchangeStatus != ExchangeApiMode.disabled;
|
||||||
|
@ -287,8 +284,7 @@ abstract class DashboardViewModelBase with Store {
|
||||||
bool hasExchangeAction;
|
bool hasExchangeAction;
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
bool get isEnabledBuyAction =>
|
bool get isEnabledBuyAction => !settingsStore.disableBuy && wallet.type != WalletType.haven;
|
||||||
!settingsStore.disableBuy && wallet.type != WalletType.haven;
|
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
bool hasBuyAction;
|
bool hasBuyAction;
|
||||||
|
@ -309,16 +305,21 @@ abstract class DashboardViewModelBase with Store {
|
||||||
@observable
|
@observable
|
||||||
bool isOutdatedElectrumWallet;
|
bool isOutdatedElectrumWallet;
|
||||||
|
|
||||||
|
@computed
|
||||||
|
bool get hasPowNodes => wallet.type == WalletType.nano || wallet.type != WalletType.banano;
|
||||||
|
|
||||||
Future<void> reconnect() async {
|
Future<void> reconnect() async {
|
||||||
final node = appStore.settingsStore.getCurrentNode(wallet.type);
|
final node = appStore.settingsStore.getCurrentNode(wallet.type);
|
||||||
await wallet.connectToNode(node: node);
|
await wallet.connectToNode(node: node);
|
||||||
|
if (hasPowNodes) {
|
||||||
|
final powNode = settingsStore.getCurrentPowNode(wallet.type);
|
||||||
|
await wallet.connectToPowNode(node: powNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void _onWalletChange(
|
void _onWalletChange(
|
||||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
|
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>? wallet) {
|
||||||
TransactionInfo>?
|
|
||||||
wallet) {
|
|
||||||
if (wallet == null) {
|
if (wallet == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -336,10 +337,12 @@ abstract class DashboardViewModelBase with Store {
|
||||||
_onMoneroAccountChangeReaction?.reaction.dispose();
|
_onMoneroAccountChangeReaction?.reaction.dispose();
|
||||||
_onMoneroBalanceChangeReaction?.reaction.dispose();
|
_onMoneroBalanceChangeReaction?.reaction.dispose();
|
||||||
|
|
||||||
_onMoneroAccountChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet)
|
_onMoneroAccountChangeReaction = reaction(
|
||||||
.account, (Account account) => _onMoneroAccountChange(wallet));
|
(_) => monero!.getMoneroWalletDetails(wallet).account,
|
||||||
|
(Account account) => _onMoneroAccountChange(wallet));
|
||||||
|
|
||||||
_onMoneroBalanceChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet).balance,
|
_onMoneroBalanceChangeReaction = reaction(
|
||||||
|
(_) => monero!.getMoneroWalletDetails(wallet).balance,
|
||||||
(MoneroBalance balance) => _onMoneroTransactionsUpdate(wallet));
|
(MoneroBalance balance) => _onMoneroTransactionsUpdate(wallet));
|
||||||
|
|
||||||
_onMoneroTransactionsUpdate(wallet);
|
_onMoneroTransactionsUpdate(wallet);
|
||||||
|
@ -350,8 +353,8 @@ abstract class DashboardViewModelBase with Store {
|
||||||
|
|
||||||
transactions.clear();
|
transactions.clear();
|
||||||
|
|
||||||
transactions.addAll(wallet.transactionHistory.transactions.values.map(
|
transactions.addAll(wallet.transactionHistory.transactions.values.map((transaction) =>
|
||||||
(transaction) => TransactionListItem(
|
TransactionListItem(
|
||||||
transaction: transaction,
|
transaction: transaction,
|
||||||
balanceViewModel: balanceViewModel,
|
balanceViewModel: balanceViewModel,
|
||||||
settingsStore: appStore.settingsStore)));
|
settingsStore: appStore.settingsStore)));
|
||||||
|
@ -360,12 +363,10 @@ abstract class DashboardViewModelBase with Store {
|
||||||
connectMapToListWithTransform(
|
connectMapToListWithTransform(
|
||||||
appStore.wallet!.transactionHistory.transactions,
|
appStore.wallet!.transactionHistory.transactions,
|
||||||
transactions,
|
transactions,
|
||||||
(TransactionInfo? transaction)
|
(TransactionInfo? transaction) => TransactionListItem(
|
||||||
=> TransactionListItem(
|
|
||||||
transaction: transaction!,
|
transaction: transaction!,
|
||||||
balanceViewModel: balanceViewModel,
|
balanceViewModel: balanceViewModel,
|
||||||
settingsStore: appStore.settingsStore),
|
settingsStore: appStore.settingsStore), filter: (TransactionInfo? tx) {
|
||||||
filter: (TransactionInfo? tx) {
|
|
||||||
if (tx == null) {
|
if (tx == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -388,12 +389,15 @@ abstract class DashboardViewModelBase with Store {
|
||||||
void _onMoneroTransactionsUpdate(WalletBase wallet) {
|
void _onMoneroTransactionsUpdate(WalletBase wallet) {
|
||||||
transactions.clear();
|
transactions.clear();
|
||||||
|
|
||||||
final _accountTransactions = monero!.getTransactionHistory(wallet).transactions.values
|
final _accountTransactions = monero!
|
||||||
.where((tx) => monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
.getTransactionHistory(wallet)
|
||||||
|
.transactions
|
||||||
|
.values
|
||||||
|
.where(
|
||||||
|
(tx) => monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
transactions.addAll(_accountTransactions.map((transaction) =>
|
transactions.addAll(_accountTransactions.map((transaction) => TransactionListItem(
|
||||||
TransactionListItem(
|
|
||||||
transaction: transaction,
|
transaction: transaction,
|
||||||
balanceViewModel: balanceViewModel,
|
balanceViewModel: balanceViewModel,
|
||||||
settingsStore: appStore.settingsStore)));
|
settingsStore: appStore.settingsStore)));
|
||||||
|
|
|
@ -15,9 +15,8 @@ part 'node_list_view_model.g.dart';
|
||||||
class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
|
class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
|
||||||
|
|
||||||
abstract class NodeListViewModelBase with Store {
|
abstract class NodeListViewModelBase with Store {
|
||||||
NodeListViewModelBase(this._nodeSource, this._powNodeSource, this._appStore)
|
NodeListViewModelBase(this._nodeSource, this._appStore)
|
||||||
: nodes = ObservableList<Node>(),
|
: nodes = ObservableList<Node>(),
|
||||||
powNodes = ObservableList<Node>(),
|
|
||||||
settingsStore = _appStore.settingsStore {
|
settingsStore = _appStore.settingsStore {
|
||||||
_bindNodes();
|
_bindNodes();
|
||||||
|
|
||||||
|
@ -41,11 +40,9 @@ abstract class NodeListViewModelBase with Store {
|
||||||
S.current.change_current_node(uri) +
|
S.current.change_current_node(uri) +
|
||||||
'${uri.endsWith('.onion') || uri.contains('.onion:') ? '\n' + S.current.orbot_running_alert : ''}';
|
'${uri.endsWith('.onion') || uri.contains('.onion:') ? '\n' + S.current.orbot_running_alert : ''}';
|
||||||
|
|
||||||
final SettingsStore settingsStore;
|
|
||||||
final ObservableList<Node> nodes;
|
final ObservableList<Node> nodes;
|
||||||
final ObservableList<Node> powNodes;
|
final SettingsStore settingsStore;
|
||||||
final Box<Node> _nodeSource;
|
final Box<Node> _nodeSource;
|
||||||
final Box<Node> _powNodeSource;
|
|
||||||
final AppStore _appStore;
|
final AppStore _appStore;
|
||||||
|
|
||||||
Future<void> reset() async {
|
Future<void> reset() async {
|
||||||
|
|
211
lib/view_model/node_list/pow_node_create_or_edit_view_model.dart
Normal file
211
lib/view_model/node_list/pow_node_create_or_edit_view_model.dart
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
import 'package:cake_wallet/core/execution_state.dart';
|
||||||
|
import 'package:cake_wallet/entities/qr_scanner.dart';
|
||||||
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cw_core/node.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
|
|
||||||
|
part 'pow_node_create_or_edit_view_model.g.dart';
|
||||||
|
|
||||||
|
class PowNodeCreateOrEditViewModel = PowNodeCreateOrEditViewModelBase
|
||||||
|
with _$PowNodeCreateOrEditViewModel;
|
||||||
|
|
||||||
|
abstract class PowNodeCreateOrEditViewModelBase with Store {
|
||||||
|
PowNodeCreateOrEditViewModelBase(
|
||||||
|
this._nodeSource, this._walletType, this._settingsStore)
|
||||||
|
: state = InitialExecutionState(),
|
||||||
|
connectionState = InitialExecutionState(),
|
||||||
|
useSSL = false,
|
||||||
|
address = '',
|
||||||
|
port = '',
|
||||||
|
login = '',
|
||||||
|
password = '',
|
||||||
|
trusted = false,
|
||||||
|
useSocksProxy = false,
|
||||||
|
socksProxyAddress = '';
|
||||||
|
|
||||||
|
@observable
|
||||||
|
ExecutionState state;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String address;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String port;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String login;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String password;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
ExecutionState connectionState;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool useSSL;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool trusted;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
bool useSocksProxy;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String socksProxyAddress;
|
||||||
|
|
||||||
|
@computed
|
||||||
|
bool get isReady => address.isNotEmpty && port.isNotEmpty;
|
||||||
|
|
||||||
|
bool get hasAuthCredentials =>
|
||||||
|
_walletType == WalletType.monero || _walletType == WalletType.haven;
|
||||||
|
|
||||||
|
String get uri {
|
||||||
|
var uri = address;
|
||||||
|
|
||||||
|
if (port.isNotEmpty) {
|
||||||
|
uri += ':' + port;
|
||||||
|
}
|
||||||
|
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
final WalletType _walletType;
|
||||||
|
final Box<Node> _nodeSource;
|
||||||
|
final SettingsStore _settingsStore;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void reset() {
|
||||||
|
address = '';
|
||||||
|
port = '';
|
||||||
|
login = '';
|
||||||
|
password = '';
|
||||||
|
useSSL = false;
|
||||||
|
trusted = false;
|
||||||
|
useSocksProxy = false;
|
||||||
|
socksProxyAddress = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setPort(String val) => port = val;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setAddress(String val) => address = val;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setLogin(String val) => login = val;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setPassword(String val) => password = val;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setSSL(bool val) => useSSL = val;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setTrusted(bool val) => trusted = val;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setSocksProxy(bool val) => useSocksProxy = val;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setSocksProxyAddress(String val) => socksProxyAddress = val;
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> save({Node? editingNode, bool saveAsCurrent = false}) async {
|
||||||
|
final node = Node(
|
||||||
|
uri: uri,
|
||||||
|
type: _walletType,
|
||||||
|
login: login,
|
||||||
|
password: password,
|
||||||
|
useSSL: useSSL,
|
||||||
|
trusted: trusted,
|
||||||
|
socksProxyAddress: socksProxyAddress);
|
||||||
|
try {
|
||||||
|
state = IsExecutingState();
|
||||||
|
if (editingNode != null) {
|
||||||
|
await _nodeSource.put(editingNode.key, node);
|
||||||
|
} else if (_existingNode(node) != null) {
|
||||||
|
setAsCurrent(_existingNode(node)!);
|
||||||
|
} else {
|
||||||
|
await _nodeSource.add(node);
|
||||||
|
setAsCurrent(_nodeSource.values.last);
|
||||||
|
}
|
||||||
|
if (saveAsCurrent) {
|
||||||
|
setAsCurrent(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
state = ExecutedSuccessfullyState();
|
||||||
|
} catch (e) {
|
||||||
|
state = FailureState(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> connect() async {
|
||||||
|
final node = Node(
|
||||||
|
uri: uri,
|
||||||
|
type: _walletType,
|
||||||
|
login: login,
|
||||||
|
password: password,
|
||||||
|
useSSL: useSSL,
|
||||||
|
trusted: trusted,
|
||||||
|
socksProxyAddress: socksProxyAddress);
|
||||||
|
try {
|
||||||
|
connectionState = IsExecutingState();
|
||||||
|
final isAlive = await node.requestNode();
|
||||||
|
connectionState = ExecutedSuccessfullyState(payload: isAlive);
|
||||||
|
} catch (e) {
|
||||||
|
connectionState = FailureState(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Node? _existingNode(Node node) {
|
||||||
|
final nodes = _nodeSource.values.toList();
|
||||||
|
nodes.forEach((item) {
|
||||||
|
item.login ??= '';
|
||||||
|
item.password ??= '';
|
||||||
|
item.useSSL ??= false;
|
||||||
|
});
|
||||||
|
return nodes.firstWhereOrNull((item) => item == node);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
void setAsCurrent(Node node) => _settingsStore.nodes[_walletType] = node;
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> scanQRCodeForNewNode() async {
|
||||||
|
try {
|
||||||
|
String code = await presentQRScanner();
|
||||||
|
|
||||||
|
if (code.isEmpty) {
|
||||||
|
throw Exception('Unexpected scan QR code value: value is empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
final uri = Uri.tryParse(code);
|
||||||
|
|
||||||
|
if (uri == null) {
|
||||||
|
throw Exception('Unexpected scan QR code value: Value is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
final userInfo = uri.userInfo.split(':');
|
||||||
|
|
||||||
|
if (userInfo.length < 2) {
|
||||||
|
throw Exception('Unexpected scan QR code value: Value is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
final rpcUser = userInfo[0];
|
||||||
|
final rpcPassword = userInfo[1];
|
||||||
|
final ipAddress = uri.host;
|
||||||
|
final port = uri.port.toString();
|
||||||
|
|
||||||
|
setAddress(ipAddress);
|
||||||
|
setPassword(rpcPassword);
|
||||||
|
setLogin(rpcUser);
|
||||||
|
setPort(port);
|
||||||
|
} on Exception catch (e) {
|
||||||
|
connectionState = FailureState(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
93
lib/view_model/node_list/pow_node_list_view_model.dart
Normal file
93
lib/view_model/node_list/pow_node_list_view_model.dart
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/store/app_store.dart';
|
||||||
|
import 'package:cake_wallet/utils/mobx.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cw_core/wallet_base.dart';
|
||||||
|
import 'package:cake_wallet/store/settings_store.dart';
|
||||||
|
import 'package:cw_core/node.dart';
|
||||||
|
import 'package:cake_wallet/entities/node_list.dart';
|
||||||
|
import 'package:cake_wallet/entities/default_settings_migration.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
|
||||||
|
part 'pow_node_list_view_model.g.dart';
|
||||||
|
|
||||||
|
class PowNodeListViewModel = PowNodeListViewModelBase with _$PowNodeListViewModel;
|
||||||
|
|
||||||
|
abstract class PowNodeListViewModelBase with Store {
|
||||||
|
PowNodeListViewModelBase(this._nodeSource, this._appStore)
|
||||||
|
: nodes = ObservableList<Node>(),
|
||||||
|
settingsStore = _appStore.settingsStore {
|
||||||
|
_bindNodes();
|
||||||
|
|
||||||
|
reaction((_) => _appStore.wallet, (WalletBase? _wallet) {
|
||||||
|
_bindNodes();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed
|
||||||
|
Node get currentNode {
|
||||||
|
final node = settingsStore.nodes[_appStore.wallet!.type];
|
||||||
|
|
||||||
|
if (node == null) {
|
||||||
|
throw Exception('No node for wallet type: ${_appStore.wallet!.type}');
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getAlertContent(String uri) =>
|
||||||
|
S.current.change_current_node(uri) +
|
||||||
|
'${uri.endsWith('.onion') || uri.contains('.onion:') ? '\n' + S.current.orbot_running_alert : ''}';
|
||||||
|
|
||||||
|
final ObservableList<Node> nodes;
|
||||||
|
final SettingsStore settingsStore;
|
||||||
|
final Box<Node> _nodeSource;
|
||||||
|
final AppStore _appStore;
|
||||||
|
|
||||||
|
Future<void> reset() async {
|
||||||
|
await resetToDefault(_nodeSource);
|
||||||
|
|
||||||
|
Node node;
|
||||||
|
|
||||||
|
switch (_appStore.wallet!.type) {
|
||||||
|
case WalletType.bitcoin:
|
||||||
|
node = getBitcoinDefaultElectrumServer(nodes: _nodeSource)!;
|
||||||
|
break;
|
||||||
|
case WalletType.monero:
|
||||||
|
node = getMoneroDefaultNode(nodes: _nodeSource);
|
||||||
|
break;
|
||||||
|
case WalletType.litecoin:
|
||||||
|
node = getLitecoinDefaultElectrumServer(nodes: _nodeSource)!;
|
||||||
|
break;
|
||||||
|
case WalletType.haven:
|
||||||
|
node = getHavenDefaultNode(nodes: _nodeSource)!;
|
||||||
|
break;
|
||||||
|
case WalletType.ethereum:
|
||||||
|
node = getEthereumDefaultNode(nodes: _nodeSource)!;
|
||||||
|
break;
|
||||||
|
case WalletType.nano:
|
||||||
|
node = getNanoDefaultNode(nodes: _nodeSource)!;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw Exception('Unexpected wallet type: ${_appStore.wallet!.type}');
|
||||||
|
}
|
||||||
|
|
||||||
|
await setAsCurrent(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
Future<void> delete(Node node) async => node.delete();
|
||||||
|
|
||||||
|
Future<void> setAsCurrent(Node node) async => settingsStore.nodes[_appStore.wallet!.type] = node;
|
||||||
|
|
||||||
|
@action
|
||||||
|
void _bindNodes() {
|
||||||
|
nodes.clear();
|
||||||
|
_nodeSource.bindToList(
|
||||||
|
nodes,
|
||||||
|
filter: (val) => val.type == _appStore.wallet!.type,
|
||||||
|
initialFire: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue