mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 20:19:25 +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;
|
||||
Node? _node;
|
||||
Node? _powNode;
|
||||
|
||||
bool connect(Node node) {
|
||||
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 {
|
||||
final response = await http.post(
|
||||
_node!.uri,
|
||||
|
@ -117,7 +127,7 @@ class NanoClient {
|
|||
Future<String> requestWork(String hash) async {
|
||||
return http
|
||||
.post(
|
||||
Uri.parse("https://rpc.nano.to"), // TODO: make a setting
|
||||
_powNode!.uri,
|
||||
headers: {'Content-type': 'application/json'},
|
||||
body: json.encode(
|
||||
{
|
||||
|
|
|
@ -134,6 +134,11 @@ abstract class NanoWalletBase
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> connectToPowNode({required Node node}) async {
|
||||
_client.connectPow(node);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||
credentials = credentials as NanoTransactionCredentials;
|
||||
|
@ -237,9 +242,7 @@ abstract class NanoWalletBase
|
|||
id: transactionModel.hash,
|
||||
amountRaw: transactionModel.amount,
|
||||
height: transactionModel.height,
|
||||
direction: transactionModel.account == address
|
||||
? TransactionDirection.outgoing
|
||||
: TransactionDirection.incoming,
|
||||
direction: transactionModel.type == "send" ? TransactionDirection.outgoing : TransactionDirection.incoming,
|
||||
confirmed: transactionModel.confirmed,
|
||||
date: transactionModel.date ?? DateTime.now(),
|
||||
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/settings/display_settings_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/privacy_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_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/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/restore/restore_from_qr_vm.dart';
|
||||
import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
|
||||
|
@ -212,7 +215,6 @@ final getIt = GetIt.instance;
|
|||
var _isSetupFinished = false;
|
||||
late Box<WalletInfo> _walletInfoSource;
|
||||
late Box<Node> _nodeSource;
|
||||
late Box<Node> _powNodeSource;
|
||||
late Box<Contact> _contactSource;
|
||||
late Box<Trade> _tradesSource;
|
||||
late Box<Template> _templates;
|
||||
|
@ -259,6 +261,7 @@ Future setup({
|
|||
|
||||
final settingsStore = await SettingsStoreBase.load(
|
||||
nodeSource: _nodeSource,
|
||||
powNodeSource: _nodeSource,
|
||||
isBitcoinBuyEnabled: isBitcoinBuyEnabled,
|
||||
// Enforce darkTheme on platforms other than mobile till the design for other themes is completed
|
||||
initialTheme: ResponsiveLayoutUtil.instance.isMobile && DeviceInfo.instance.isMobile
|
||||
|
@ -687,7 +690,12 @@ Future setup({
|
|||
|
||||
getIt.registerFactory(() {
|
||||
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>()));
|
||||
|
@ -707,6 +715,10 @@ Future setup({
|
|||
NodeCreateOrEditViewModel(
|
||||
_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?>(
|
||||
(Node? editingNode, bool? isSelected) => NodeCreateOrEditPage(
|
||||
nodeCreateOrEditViewModel: getIt.get<NodeCreateOrEditViewModel>(),
|
||||
|
@ -1068,6 +1080,8 @@ Future setup({
|
|||
);
|
||||
|
||||
getIt.registerFactory<ManageNodesPage>(() => ManageNodesPage(getIt.get<NodeListViewModel>()));
|
||||
getIt.registerFactory<ManagePowNodesPage>(
|
||||
() => ManagePowNodesPage(getIt.get<PowNodeListViewModel>()));
|
||||
|
||||
_isSetupFinished = true;
|
||||
}
|
||||
|
|
|
@ -13,4 +13,11 @@ void startOnCurrentNodeChangeReaction(AppStore appStore) {
|
|||
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 _onCurrentWalletAddressChangeReaction;
|
||||
|
||||
void startCurrentWalletChangeReaction(AppStore appStore,
|
||||
SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
|
||||
void startCurrentWalletChangeReaction(
|
||||
AppStore appStore, SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
|
||||
_onCurrentWalletChangeReaction?.reaction.dispose();
|
||||
_onCurrentWalletChangeFiatRateUpdateReaction?.reaction.dispose();
|
||||
//_onCurrentWalletAddressChangeReaction?.reaction?dispose();
|
||||
|
@ -48,8 +48,8 @@ void startCurrentWalletChangeReaction(AppStore appStore,
|
|||
//}
|
||||
//});
|
||||
|
||||
_onCurrentWalletChangeReaction = reaction((_) => appStore.wallet, (WalletBase<
|
||||
Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
|
||||
_onCurrentWalletChangeReaction = reaction((_) => appStore.wallet,
|
||||
(WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
|
||||
wallet) async {
|
||||
try {
|
||||
if (wallet == null) {
|
||||
|
@ -57,14 +57,19 @@ void startCurrentWalletChangeReaction(AppStore appStore,
|
|||
}
|
||||
|
||||
final node = settingsStore.getCurrentNode(wallet.type);
|
||||
|
||||
startWalletSyncStatusChangeReaction(wallet, fiatConversionStore);
|
||||
startCheckConnectionReaction(wallet, settingsStore);
|
||||
await getIt.get<SharedPreferences>().setString(PreferencesKey.currentWalletName, wallet.name);
|
||||
await getIt
|
||||
.get<SharedPreferences>()
|
||||
.setString(PreferencesKey.currentWalletName, wallet.name);
|
||||
await getIt.get<SharedPreferences>().setInt(
|
||||
PreferencesKey.currentWalletType, serializeToInt(wallet.type));
|
||||
.setInt(PreferencesKey.currentWalletType, serializeToInt(wallet.type));
|
||||
|
||||
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) {
|
||||
await updateHavenRate(fiatConversionStore);
|
||||
|
@ -82,9 +87,8 @@ void startCurrentWalletChangeReaction(AppStore appStore,
|
|||
}
|
||||
});
|
||||
|
||||
_onCurrentWalletChangeFiatRateUpdateReaction =
|
||||
reaction((_) => appStore.wallet, (WalletBase<Balance,
|
||||
TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
|
||||
_onCurrentWalletChangeFiatRateUpdateReaction = reaction((_) => appStore.wallet,
|
||||
(WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
|
||||
wallet) async {
|
||||
try {
|
||||
if (wallet == null || settingsStore.fiatApiMode == FiatApiMode.disabled) {
|
||||
|
@ -92,8 +96,7 @@ void startCurrentWalletChangeReaction(AppStore appStore,
|
|||
}
|
||||
|
||||
fiatConversionStore.prices[wallet.currency] = 0;
|
||||
fiatConversionStore.prices[wallet.currency] =
|
||||
await FiatConversionService.fetchPrice(
|
||||
fiatConversionStore.prices[wallet.currency] = await FiatConversionService.fetchPrice(
|
||||
crypto: wallet.currency,
|
||||
fiat: settingsStore.fiatCurrency,
|
||||
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/display_settings_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/privacy_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:
|
||||
return MaterialPageRoute<void>(builder: (_) => getIt.get<ManageNodesPage>());
|
||||
|
||||
case Routes.managePowNodes:
|
||||
return MaterialPageRoute<void>(builder: (_) => getIt.get<ManagePowNodesPage>());
|
||||
|
||||
default:
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (_) => Scaffold(
|
||||
|
|
|
@ -92,4 +92,6 @@ class Routes {
|
|||
static const homeSettings = '/home_settings';
|
||||
static const editToken = '/edit_token';
|
||||
static const manageNodes = '/manage_nodes';
|
||||
static const managePowNodes = '/manage_pow_nodes';
|
||||
|
||||
}
|
||||
|
|
|
@ -65,6 +65,17 @@ class ConnectionSyncPage extends BasePage {
|
|||
title: S.current.manage_nodes,
|
||||
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)),
|
||||
],
|
||||
),
|
||||
|
|
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? initialEthereumTransactionPriority})
|
||||
: nodes = ObservableMap<WalletType, Node>.of(nodes),
|
||||
powNodes = ObservableMap<WalletType, Node>.of(nodes),
|
||||
_sharedPreferences = sharedPreferences,
|
||||
_backgroundTasks = backgroundTasks,
|
||||
fiatCurrency = initialFiatCurrency,
|
||||
|
@ -456,6 +457,7 @@ abstract class SettingsStoreBase with Store {
|
|||
final BackgroundTasks _backgroundTasks;
|
||||
|
||||
ObservableMap<WalletType, Node> nodes;
|
||||
ObservableMap<WalletType, Node> powNodes;
|
||||
|
||||
Node getCurrentNode(WalletType walletType) {
|
||||
final node = nodes[walletType];
|
||||
|
@ -467,6 +469,16 @@ abstract class SettingsStoreBase with Store {
|
|||
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 get shouldShowReceiveWarning =>
|
||||
|
@ -477,6 +489,7 @@ abstract class SettingsStoreBase with Store {
|
|||
|
||||
static Future<SettingsStore> load(
|
||||
{required Box<Node> nodeSource,
|
||||
required Box<Node> powNodeSource,
|
||||
required bool isBitcoinBuyEnabled,
|
||||
FiatCurrency initialFiatCurrency = FiatCurrency.usd,
|
||||
BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance,
|
||||
|
@ -577,8 +590,7 @@ abstract class SettingsStoreBase with Store {
|
|||
SortBalanceBy.values[sharedPreferences.getInt(PreferencesKey.sortBalanceBy) ?? 0];
|
||||
final pinNativeTokenAtTop =
|
||||
sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop) ?? true;
|
||||
final useEtherscan =
|
||||
sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
|
||||
final useEtherscan = sharedPreferences.getBool(PreferencesKey.useEtherscan) ?? true;
|
||||
|
||||
// If no value
|
||||
if (pinLength == null || pinLength == 0) {
|
||||
|
@ -601,11 +613,13 @@ abstract class SettingsStoreBase with Store {
|
|||
final havenNode = nodeSource.get(havenNodeId);
|
||||
final ethereumNode = nodeSource.get(ethereumNodeId);
|
||||
final nanoNode = nodeSource.get(nanoNodeId);
|
||||
final nanoPowNode = powNodeSource.get(nanoNodeId);
|
||||
final packageInfo = await PackageInfo.fromPlatform();
|
||||
final deviceName = await _getDeviceName() ?? '';
|
||||
final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true;
|
||||
|
||||
final nodes = <WalletType, Node>{};
|
||||
final powNodes = <WalletType, Node>{};
|
||||
|
||||
if (moneroNode != null) {
|
||||
nodes[WalletType.monero] = moneroNode;
|
||||
|
@ -630,6 +644,9 @@ abstract class SettingsStoreBase with Store {
|
|||
if (nanoNode != null) {
|
||||
nodes[WalletType.nano] = nanoNode;
|
||||
}
|
||||
if (nanoPowNode != null) {
|
||||
powNodes[WalletType.nano] = nanoPowNode;
|
||||
}
|
||||
|
||||
final savedSyncMode = SyncMode.all.firstWhere((element) {
|
||||
return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1);
|
||||
|
|
|
@ -75,28 +75,28 @@ abstract class DashboardViewModelBase with Store {
|
|||
FilterItem(
|
||||
value: () => tradeFilterStore.displayAllTrades,
|
||||
caption: S.current.all_trades,
|
||||
onChanged: () => tradeFilterStore
|
||||
.toggleDisplayExchange(ExchangeProviderDescription.all)),
|
||||
onChanged: () =>
|
||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.all)),
|
||||
FilterItem(
|
||||
value: () => tradeFilterStore.displayChangeNow,
|
||||
caption: ExchangeProviderDescription.changeNow.title,
|
||||
onChanged: () => tradeFilterStore
|
||||
.toggleDisplayExchange(ExchangeProviderDescription.changeNow)),
|
||||
onChanged: () =>
|
||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.changeNow)),
|
||||
FilterItem(
|
||||
value: () => tradeFilterStore.displaySideShift,
|
||||
caption: ExchangeProviderDescription.sideShift.title,
|
||||
onChanged: () => tradeFilterStore
|
||||
.toggleDisplayExchange(ExchangeProviderDescription.sideShift)),
|
||||
onChanged: () =>
|
||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.sideShift)),
|
||||
FilterItem(
|
||||
value: () => tradeFilterStore.displaySimpleSwap,
|
||||
caption: ExchangeProviderDescription.simpleSwap.title,
|
||||
onChanged: () => tradeFilterStore
|
||||
.toggleDisplayExchange(ExchangeProviderDescription.simpleSwap)),
|
||||
onChanged: () =>
|
||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.simpleSwap)),
|
||||
FilterItem(
|
||||
value: () => tradeFilterStore.displayTrocador,
|
||||
caption: ExchangeProviderDescription.trocador.title,
|
||||
onChanged: () => tradeFilterStore
|
||||
.toggleDisplayExchange(ExchangeProviderDescription.trocador)),
|
||||
onChanged: () =>
|
||||
tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.trocador)),
|
||||
]
|
||||
},
|
||||
subname = '',
|
||||
|
@ -118,15 +118,17 @@ abstract class DashboardViewModelBase with Store {
|
|||
if (_wallet.type == WalletType.monero) {
|
||||
subname = monero!.getCurrentAccount(_wallet).label;
|
||||
|
||||
_onMoneroAccountChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet)
|
||||
.account, (Account account) => _onMoneroAccountChange(_wallet));
|
||||
_onMoneroAccountChangeReaction = reaction(
|
||||
(_) => monero!.getMoneroWalletDetails(wallet).account,
|
||||
(Account account) => _onMoneroAccountChange(_wallet));
|
||||
|
||||
_onMoneroBalanceChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet).balance,
|
||||
_onMoneroBalanceChangeReaction = reaction(
|
||||
(_) => monero!.getMoneroWalletDetails(wallet).balance,
|
||||
(MoneroBalance balance) => _onMoneroTransactionsUpdate(_wallet));
|
||||
|
||||
final _accountTransactions = _wallet
|
||||
.transactionHistory.transactions.values
|
||||
.where((tx) => monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||
final _accountTransactions = _wallet.transactionHistory.transactions.values
|
||||
.where((tx) =>
|
||||
monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||
.toList();
|
||||
|
||||
transactions = ObservableList.of(_accountTransactions.map((transaction) =>
|
||||
|
@ -135,9 +137,8 @@ abstract class DashboardViewModelBase with Store {
|
|||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
} else {
|
||||
transactions = ObservableList.of(wallet
|
||||
.transactionHistory.transactions.values
|
||||
.map((transaction) => TransactionListItem(
|
||||
transactions = ObservableList.of(wallet.transactionHistory.transactions.values.map(
|
||||
(transaction) => TransactionListItem(
|
||||
transaction: transaction,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
|
@ -151,15 +152,15 @@ abstract class DashboardViewModelBase with Store {
|
|||
(TransactionInfo? transaction) => TransactionListItem(
|
||||
transaction: transaction!,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore),
|
||||
filter: (TransactionInfo? transaction) {
|
||||
settingsStore: appStore.settingsStore), filter: (TransactionInfo? transaction) {
|
||||
if (transaction == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final wallet = _wallet;
|
||||
if (wallet.type == WalletType.monero) {
|
||||
return monero!.getTransactionInfoAccountId(transaction) == monero!.getCurrentAccount(wallet).id;
|
||||
return monero!.getTransactionInfoAccountId(transaction) ==
|
||||
monero!.getCurrentAccount(wallet).id;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -209,8 +210,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
}
|
||||
|
||||
@computed
|
||||
BalanceDisplayMode get balanceDisplayMode =>
|
||||
appStore.settingsStore.balanceDisplayMode;
|
||||
BalanceDisplayMode get balanceDisplayMode => appStore.settingsStore.balanceDisplayMode;
|
||||
|
||||
@computed
|
||||
bool get shouldShowMarketPlaceInDashboard {
|
||||
|
@ -218,14 +218,12 @@ abstract class DashboardViewModelBase with Store {
|
|||
}
|
||||
|
||||
@computed
|
||||
List<TradeListItem> get trades => tradesStore.trades
|
||||
.where((trade) => trade.trade.walletId == wallet.id)
|
||||
.toList();
|
||||
List<TradeListItem> get trades =>
|
||||
tradesStore.trades.where((trade) => trade.trade.walletId == wallet.id).toList();
|
||||
|
||||
@computed
|
||||
List<OrderListItem> get orders => ordersStore.orders
|
||||
.where((item) => item.order.walletId == wallet.id)
|
||||
.toList();
|
||||
List<OrderListItem> get orders =>
|
||||
ordersStore.orders.where((item) => item.order.walletId == wallet.id).toList();
|
||||
|
||||
@computed
|
||||
List<AnonpayTransactionListItem> get anonpayTransactons => anonpayTransactionsStore.transactions
|
||||
|
@ -239,7 +237,8 @@ abstract class DashboardViewModelBase with Store {
|
|||
List<ActionListItem> get items {
|
||||
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(orders);
|
||||
|
||||
|
@ -247,8 +246,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
}
|
||||
|
||||
@observable
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>
|
||||
wallet;
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet;
|
||||
|
||||
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;
|
||||
|
||||
@action
|
||||
void furtherShowYatPopup(bool shouldShow) =>
|
||||
settingsStore.shouldShowYatPopup = shouldShow;
|
||||
void furtherShowYatPopup(bool shouldShow) => settingsStore.shouldShowYatPopup = shouldShow;
|
||||
|
||||
@computed
|
||||
bool get isEnabledExchangeAction => settingsStore.exchangeStatus != ExchangeApiMode.disabled;
|
||||
|
@ -287,8 +284,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
bool hasExchangeAction;
|
||||
|
||||
@computed
|
||||
bool get isEnabledBuyAction =>
|
||||
!settingsStore.disableBuy && wallet.type != WalletType.haven;
|
||||
bool get isEnabledBuyAction => !settingsStore.disableBuy && wallet.type != WalletType.haven;
|
||||
|
||||
@observable
|
||||
bool hasBuyAction;
|
||||
|
@ -309,16 +305,21 @@ abstract class DashboardViewModelBase with Store {
|
|||
@observable
|
||||
bool isOutdatedElectrumWallet;
|
||||
|
||||
@computed
|
||||
bool get hasPowNodes => wallet.type == WalletType.nano || wallet.type != WalletType.banano;
|
||||
|
||||
Future<void> reconnect() async {
|
||||
final node = appStore.settingsStore.getCurrentNode(wallet.type);
|
||||
await wallet.connectToNode(node: node);
|
||||
if (hasPowNodes) {
|
||||
final powNode = settingsStore.getCurrentPowNode(wallet.type);
|
||||
await wallet.connectToPowNode(node: powNode);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
void _onWalletChange(
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
|
||||
TransactionInfo>?
|
||||
wallet) {
|
||||
WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>? wallet) {
|
||||
if (wallet == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -336,10 +337,12 @@ abstract class DashboardViewModelBase with Store {
|
|||
_onMoneroAccountChangeReaction?.reaction.dispose();
|
||||
_onMoneroBalanceChangeReaction?.reaction.dispose();
|
||||
|
||||
_onMoneroAccountChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet)
|
||||
.account, (Account account) => _onMoneroAccountChange(wallet));
|
||||
_onMoneroAccountChangeReaction = reaction(
|
||||
(_) => monero!.getMoneroWalletDetails(wallet).account,
|
||||
(Account account) => _onMoneroAccountChange(wallet));
|
||||
|
||||
_onMoneroBalanceChangeReaction = reaction((_) => monero!.getMoneroWalletDetails(wallet).balance,
|
||||
_onMoneroBalanceChangeReaction = reaction(
|
||||
(_) => monero!.getMoneroWalletDetails(wallet).balance,
|
||||
(MoneroBalance balance) => _onMoneroTransactionsUpdate(wallet));
|
||||
|
||||
_onMoneroTransactionsUpdate(wallet);
|
||||
|
@ -350,8 +353,8 @@ abstract class DashboardViewModelBase with Store {
|
|||
|
||||
transactions.clear();
|
||||
|
||||
transactions.addAll(wallet.transactionHistory.transactions.values.map(
|
||||
(transaction) => TransactionListItem(
|
||||
transactions.addAll(wallet.transactionHistory.transactions.values.map((transaction) =>
|
||||
TransactionListItem(
|
||||
transaction: transaction,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
|
@ -360,12 +363,10 @@ abstract class DashboardViewModelBase with Store {
|
|||
connectMapToListWithTransform(
|
||||
appStore.wallet!.transactionHistory.transactions,
|
||||
transactions,
|
||||
(TransactionInfo? transaction)
|
||||
=> TransactionListItem(
|
||||
(TransactionInfo? transaction) => TransactionListItem(
|
||||
transaction: transaction!,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore),
|
||||
filter: (TransactionInfo? tx) {
|
||||
settingsStore: appStore.settingsStore), filter: (TransactionInfo? tx) {
|
||||
if (tx == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -388,12 +389,15 @@ abstract class DashboardViewModelBase with Store {
|
|||
void _onMoneroTransactionsUpdate(WalletBase wallet) {
|
||||
transactions.clear();
|
||||
|
||||
final _accountTransactions = monero!.getTransactionHistory(wallet).transactions.values
|
||||
.where((tx) => monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||
final _accountTransactions = monero!
|
||||
.getTransactionHistory(wallet)
|
||||
.transactions
|
||||
.values
|
||||
.where(
|
||||
(tx) => monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
|
||||
.toList();
|
||||
|
||||
transactions.addAll(_accountTransactions.map((transaction) =>
|
||||
TransactionListItem(
|
||||
transactions.addAll(_accountTransactions.map((transaction) => TransactionListItem(
|
||||
transaction: transaction,
|
||||
balanceViewModel: balanceViewModel,
|
||||
settingsStore: appStore.settingsStore)));
|
||||
|
|
|
@ -15,9 +15,8 @@ part 'node_list_view_model.g.dart';
|
|||
class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
|
||||
|
||||
abstract class NodeListViewModelBase with Store {
|
||||
NodeListViewModelBase(this._nodeSource, this._powNodeSource, this._appStore)
|
||||
NodeListViewModelBase(this._nodeSource, this._appStore)
|
||||
: nodes = ObservableList<Node>(),
|
||||
powNodes = ObservableList<Node>(),
|
||||
settingsStore = _appStore.settingsStore {
|
||||
_bindNodes();
|
||||
|
||||
|
@ -41,11 +40,9 @@ abstract class NodeListViewModelBase with Store {
|
|||
S.current.change_current_node(uri) +
|
||||
'${uri.endsWith('.onion') || uri.contains('.onion:') ? '\n' + S.current.orbot_running_alert : ''}';
|
||||
|
||||
final SettingsStore settingsStore;
|
||||
final ObservableList<Node> nodes;
|
||||
final ObservableList<Node> powNodes;
|
||||
final SettingsStore settingsStore;
|
||||
final Box<Node> _nodeSource;
|
||||
final Box<Node> _powNodeSource;
|
||||
final AppStore _appStore;
|
||||
|
||||
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