CW-681 Add address and account list to Wownero (#1538)
cyan committed
Jul 21, 2024 at 02:58 UTC
649305acc343f75d26892b92f878e18747ddc8a2
9 files changed
+171
-33
lib/di.dart
+2
-1
@@ -678,7 +678,7 @@ Future<void> setup({
678
679
getIt.registerFactory<MoneroAccountListViewModel>(() {
680
final wallet = getIt.get<AppStore>().wallet!;
681
- if (wallet.type == WalletType.monero || wallet.type == WalletType.haven) {
681
+ if (wallet.type == WalletType.monero || wallet.type == WalletType.wownero || wallet.type == WalletType.haven) {
682
return MoneroAccountListViewModel(wallet);
683
}
684
throw Exception(
@@ -709,6 +709,7 @@ Future<void> setup({
709
getIt.registerFactoryParam<MoneroAccountEditOrCreateViewModel, AccountListItem?, void>(
710
(AccountListItem? account, _) => MoneroAccountEditOrCreateViewModel(
711
monero!.getAccountList(getIt.get<AppStore>().wallet!),
712
+ wownero?.getAccountList(getIt.get<AppStore>().wallet!),
713
haven?.getAccountList(getIt.get<AppStore>().wallet!),
714
wallet: getIt.get<AppStore>().wallet!,
715
accountListItem: account));
lib/src/screens/receive/receive_page.dart
+1
@@ -139,6 +139,7 @@ class ReceivePage extends BasePage {
139
walletAddressListViewModel: addressListViewModel,
140
trailingButtonTap: () async {
141
if (addressListViewModel.type == WalletType.monero ||
142
+ addressListViewModel.type == WalletType.wownero ||
143
addressListViewModel.type == WalletType.haven) {
144
await showPopUp<void>(
145
context: context,
lib/view_model/dashboard/balance_view_model.dart
+1
-1
@@ -88,7 +88,7 @@ abstract class BalanceViewModelBase with Store {
88
wallet.type == WalletType.tron;
89
90
@computed
91
- bool get hasAccounts => wallet.type == WalletType.monero;
91
+ bool get hasAccounts => wallet.type == WalletType.monero || wallet.type == WalletType.wownero;
92
93
@computed
94
SortBalanceBy get sortBalanceBy => settingsStore.sortBalanceBy;
lib/view_model/dashboard/dashboard_view_model.dart
+77
-12
@@ -31,6 +31,7 @@ import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
31
import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
32
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
33
import 'package:cake_wallet/wallet_type_utils.dart';
34
+import 'package:cake_wallet/wownero/wownero.dart' as wow;
35
import 'package:cryptography/cryptography.dart';
36
import 'package:cw_core/balance.dart';
37
import 'package:cw_core/cake_hive.dart';
@@ -163,6 +164,29 @@ abstract class DashboardViewModelBase with Store {
164
final sortedTransactions = [..._accountTransactions];
165
sortedTransactions.sort((a, b) => a.date.compareTo(b.date));
166
167
+ transactions = ObservableList.of(sortedTransactions.map((transaction) => TransactionListItem(
168
+ transaction: transaction,
169
+ balanceViewModel: balanceViewModel,
170
+ settingsStore: appStore.settingsStore)));
171
+ } else if (_wallet.type == WalletType.wownero) {
172
+ subname = wow.wownero!.getCurrentAccount(_wallet).label;
173
+
174
+ _onMoneroAccountChangeReaction = reaction(
175
+ (_) => wow.wownero!.getWowneroWalletDetails(wallet).account,
176
+ (wow.Account account) => _onMoneroAccountChange(_wallet));
177
+
178
+ _onMoneroBalanceChangeReaction = reaction(
179
+ (_) => wow.wownero!.getWowneroWalletDetails(wallet).balance,
180
+ (wow.WowneroBalance balance) => _onMoneroTransactionsUpdate(_wallet));
181
+
182
+ final _accountTransactions = _wallet.transactionHistory.transactions.values
183
+ .where((tx) =>
184
+ wow.wownero!.getTransactionInfoAccountId(tx) == wow.wownero!.getCurrentAccount(wallet).id)
185
+ .toList();
186
+
187
+ final sortedTransactions = [..._accountTransactions];
188
+ sortedTransactions.sort((a, b) => a.date.compareTo(b.date));
189
+
190
transactions = ObservableList.of(sortedTransactions.map((transaction) => TransactionListItem(
191
transaction: transaction,
192
balanceViewModel: balanceViewModel,
@@ -200,6 +224,10 @@ abstract class DashboardViewModelBase with Store {
224
return monero!.getTransactionInfoAccountId(transaction) ==
225
monero!.getCurrentAccount(wallet).id;
226
}
227
+ if (wallet.type == WalletType.wownero) {
228
+ return wow.wownero!.getTransactionInfoAccountId(transaction) ==
229
+ wow.wownero!.getCurrentAccount(wallet).id;
230
+ }
231
232
return true;
233
});
@@ -459,6 +487,21 @@ abstract class DashboardViewModelBase with Store {
487
(_) => monero!.getMoneroWalletDetails(wallet).balance,
488
(MoneroBalance balance) => _onMoneroTransactionsUpdate(wallet));
489
490
+ _onMoneroTransactionsUpdate(wallet);
491
+ } else if (wallet.type == WalletType.wownero) {
492
+ subname = wow.wownero!.getCurrentAccount(wallet).label;
493
+
494
+ _onMoneroAccountChangeReaction?.reaction.dispose();
495
+ _onMoneroBalanceChangeReaction?.reaction.dispose();
496
+
497
+ _onMoneroAccountChangeReaction = reaction(
498
+ (_) => wow.wownero!.getWowneroWalletDetails(wallet).account,
499
+ (wow.Account account) => _onMoneroAccountChange(wallet));
500
+
501
+ _onMoneroBalanceChangeReaction = reaction(
502
+ (_) => wow.wownero!.getWowneroWalletDetails(wallet).balance,
503
+ (wow.WowneroBalance balance) => _onMoneroTransactionsUpdate(wallet));
504
+
505
_onMoneroTransactionsUpdate(wallet);
506
} else {
507
// FIX-ME: Check for side effects
@@ -489,32 +532,54 @@ abstract class DashboardViewModelBase with Store {
532
return monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id;
533
}
534
535
+ if (wallet.type == WalletType.wownero) {
536
+ return wow.wownero!.getTransactionInfoAccountId(tx) == wow.wownero!.getCurrentAccount(wallet).id;
537
+ }
538
+
539
return true;
540
});
541
}
542
543
@action
544
void _onMoneroAccountChange(WalletBase wallet) {
498
- subname = monero!.getCurrentAccount(wallet).label;
545
+ if (wallet.type == WalletType.monero) {
546
+ subname = monero!.getCurrentAccount(wallet).label;
547
+ } else if (wallet.type == WalletType.wownero) {
548
+ subname = wow.wownero!.getCurrentAccount(wallet).label;
549
+ }
550
_onMoneroTransactionsUpdate(wallet);
551
}
552
553
@action
554
void _onMoneroTransactionsUpdate(WalletBase wallet) {
555
transactions.clear();
556
+ if (wallet.type == WalletType.monero) {
557
+ final _accountTransactions = monero!
558
+ .getTransactionHistory(wallet)
559
+ .transactions
560
+ .values
561
+ .where(
562
+ (tx) => monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
563
+ .toList();
564
506
- final _accountTransactions = monero!
507
- .getTransactionHistory(wallet)
508
- .transactions
509
- .values
510
- .where(
511
- (tx) => monero!.getTransactionInfoAccountId(tx) == monero!.getCurrentAccount(wallet).id)
512
- .toList();
565
+ transactions.addAll(_accountTransactions.map((transaction) => TransactionListItem(
566
+ transaction: transaction,
567
+ balanceViewModel: balanceViewModel,
568
+ settingsStore: appStore.settingsStore)));
569
+ } else if (wallet.type == WalletType.wownero) {
570
+ final _accountTransactions = wow.wownero!
571
+ .getTransactionHistory(wallet)
572
+ .transactions
573
+ .values
574
+ .where(
575
+ (tx) => wow.wownero!.getTransactionInfoAccountId(tx) == wow.wownero!.getCurrentAccount(wallet).id)
576
+ .toList();
577
514
- transactions.addAll(_accountTransactions.map((transaction) => TransactionListItem(
515
- transaction: transaction,
516
- balanceViewModel: balanceViewModel,
517
- settingsStore: appStore.settingsStore)));
578
+ transactions.addAll(_accountTransactions.map((transaction) => TransactionListItem(
579
+ transaction: transaction,
580
+ balanceViewModel: balanceViewModel,
581
+ settingsStore: appStore.settingsStore)));
582
+ }
583
}
584
585
void updateActions() {
lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart
+30
-1
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/wownero/wownero.dart';
2
import 'package:cw_core/wallet_base.dart';
3
import 'package:cw_core/wallet_type.dart';
4
import 'package:flutter/foundation.dart';
@@ -13,7 +14,7 @@ class MoneroAccountEditOrCreateViewModel = MoneroAccountEditOrCreateViewModelBas
14
with _$MoneroAccountEditOrCreateViewModel;
15
16
abstract class MoneroAccountEditOrCreateViewModelBase with Store {
16
- MoneroAccountEditOrCreateViewModelBase(this._moneroAccountList, this._havenAccountList,
17
+ MoneroAccountEditOrCreateViewModelBase(this._moneroAccountList, this._wowneroAccountList, this._havenAccountList,
18
{required WalletBase wallet, AccountListItem? accountListItem})
19
: state = InitialExecutionState(),
20
isEdit = accountListItem != null,
@@ -30,6 +31,7 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store {
31
String label;
32
33
final MoneroAccountList _moneroAccountList;
34
+ final WowneroAccountList? _wowneroAccountList;
35
final HavenAccountList? _havenAccountList;
36
final AccountListItem? _accountListItem;
37
final WalletBase _wallet;
@@ -42,6 +44,10 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store {
44
if (_wallet.type == WalletType.haven) {
45
await saveHaven();
46
}
47
+
48
+ if (_wallet.type == WalletType.wownero) {
49
+ await saveWownero();
50
+ }
51
}
52
53
Future<void> saveMonero() async {
@@ -91,4 +97,27 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store {
97
state = FailureState(e.toString());
98
}
99
}
100
+
101
+ Future<void> saveWownero() async {
102
+ try {
103
+ state = IsExecutingState();
104
+
105
+ if (_accountListItem != null) {
106
+ await _wowneroAccountList?.setLabelAccount(
107
+ _wallet,
108
+ accountIndex: _accountListItem!.id,
109
+ label: label);
110
+ } else {
111
+ await _wowneroAccountList?.addAccount(
112
+ _wallet,
113
+ label: label);
114
+ }
115
+
116
+ await _wallet.save();
117
+ state = ExecutedSuccessfullyState();
118
+ } catch (e) {
119
+ state = FailureState(e.toString());
120
+ }
121
+ }
122
+
123
}
lib/view_model/monero_account_list/monero_account_list_view_model.dart
+21
@@ -1,3 +1,4 @@
1
+import 'package:cake_wallet/wownero/wownero.dart';
2
import 'package:cw_core/crypto_currency.dart';
3
import 'package:cw_core/wallet_type.dart';
4
import 'package:mobx/mobx.dart';
@@ -47,6 +48,17 @@ abstract class MoneroAccountListViewModelBase with Store {
48
.toList();
49
}
50
51
+ if (_wallet.type == WalletType.wownero) {
52
+ return wownero
53
+ !.getAccountList(_wallet)
54
+ .accounts.map((acc) => AccountListItem(
55
+ label: acc.label,
56
+ id: acc.id,
57
+ balance: acc.balance,
58
+ isSelected: acc.id == wownero!.getCurrentAccount(_wallet).id))
59
+ .toList();
60
+ }
61
+
62
throw Exception('Unexpected wallet type: ${_wallet.type}');
63
}
64
@@ -62,6 +74,15 @@ abstract class MoneroAccountListViewModelBase with Store {
74
);
75
}
76
77
+ if (_wallet.type == WalletType.wownero) {
78
+ wownero!.setCurrentAccount(
79
+ _wallet,
80
+ item.id,
81
+ item.label,
82
+ item.balance,
83
+ );
84
+ }
85
+
86
if (_wallet.type == WalletType.haven) {
87
haven!.setCurrentAccount(
88
_wallet,
lib/view_model/node_list/node_create_or_edit_view_model.dart
+1
-1
@@ -65,7 +65,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
65
bool get isReady => address.isNotEmpty && port.isNotEmpty;
66
67
bool get hasAuthCredentials =>
68
- _walletType == WalletType.monero || _walletType == WalletType.haven;
68
+ _walletType == WalletType.monero || _walletType == WalletType.wownero || _walletType == WalletType.haven;
69
70
bool get hasTestnetSupport => _walletType == WalletType.bitcoin;
71
lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart
+16
@@ -1,4 +1,5 @@
1
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart';
2
+import 'package:cake_wallet/wownero/wownero.dart';
3
import 'package:mobx/mobx.dart';
4
import 'package:cw_core/wallet_base.dart';
5
import 'package:cake_wallet/bitcoin/bitcoin.dart';
@@ -80,6 +81,16 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store {
81
await wallet.save();
82
}
83
84
+ if (wallet.type == WalletType.wownero) {
85
+ await wownero
86
+ !.getSubaddressList(wallet)
87
+ .addSubaddress(
88
+ wallet,
89
+ accountIndex: wownero!.getCurrentAccount(wallet).id,
90
+ label: label);
91
+ await wallet.save();
92
+ }
93
+
94
if (wallet.type == WalletType.haven) {
95
await haven
96
!.getSubaddressList(wallet)
@@ -103,6 +114,11 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store {
114
accountIndex: monero!.getCurrentAccount(wallet).id, addressIndex: index, label: label);
115
await wallet.save();
116
}
117
+ if (wallet.type == WalletType.wownero) {
118
+ await wownero!.getSubaddressList(wallet).setLabelSubaddress(wallet,
119
+ accountIndex: wownero!.getCurrentAccount(wallet).id, addressIndex: index, label: label);
120
+ await wallet.save();
121
+ }
122
if (wallet.type == WalletType.haven) {
123
await haven!.getSubaddressList(wallet).setLabelSubaddress(wallet,
124
accountIndex: haven!.getCurrentAccount(wallet).id,
lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
+22
-17
@@ -217,7 +217,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
217
selectedCurrency = walletTypeToCryptoCurrency(appStore.wallet!.type),
218
_cryptoNumberFormat = NumberFormat(_cryptoNumberPattern),
219
hasAccounts =
220
- appStore.wallet!.type == WalletType.monero || appStore.wallet!.type == WalletType.haven,
220
+ appStore.wallet!.type == WalletType.monero || appStore.wallet!.type == WalletType.wownero || appStore.wallet!.type == WalletType.haven,
221
amount = '',
222
_settingsStore = appStore.settingsStore,
223
super(appStore: appStore) {
@@ -229,7 +229,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
229
_init();
230
231
selectedCurrency = walletTypeToCryptoCurrency(wallet.type);
232
- hasAccounts = wallet.type == WalletType.monero || wallet.type == WalletType.haven;
232
+ hasAccounts = wallet.type == WalletType.monero || wallet.type == WalletType.wownero || wallet.type == WalletType.haven;
233
}
234
235
static const String _cryptoNumberPattern = '0.00000000';
@@ -340,6 +340,20 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
340
addressList.addAll(addressItems);
341
}
342
343
+ if (wallet.type == WalletType.wownero) {
344
+ final primaryAddress = wownero!.getSubaddressList(wallet).subaddresses.first;
345
+ final addressItems = wownero!.getSubaddressList(wallet).subaddresses.map((subaddress) {
346
+ final isPrimary = subaddress == primaryAddress;
347
+
348
+ return WalletAddressListItem(
349
+ id: subaddress.id,
350
+ isPrimary: isPrimary,
351
+ name: subaddress.label,
352
+ address: subaddress.address);
353
+ });
354
+ addressList.addAll(addressItems);
355
+ }
356
+
357
if (wallet.type == WalletType.haven) {
358
final primaryAddress = haven!.getSubaddressList(wallet).subaddresses.first;
359
final addressItems = haven!.getSubaddressList(wallet).subaddresses.map((subaddress) {
@@ -430,20 +444,6 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
444
addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress));
445
}
446
433
- if (wallet.type == WalletType.wownero) {
434
- final primaryAddress = wownero!.getSubaddressList(wallet).subaddresses.first;
435
- final addressItems = wownero!.getSubaddressList(wallet).subaddresses.map((subaddress) {
436
- final isPrimary = subaddress == primaryAddress;
437
-
438
- return WalletAddressListItem(
439
- id: subaddress.id,
440
- isPrimary: isPrimary,
441
- name: subaddress.label,
442
- address: subaddress.address);
443
- });
444
- addressList.addAll(addressItems);
445
- }
446
-
447
if (searchText.isNotEmpty) {
448
return ObservableList.of(addressList.where((item) {
449
if (item is WalletAddressListItem) {
@@ -465,6 +465,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
465
return monero!.getCurrentAccount(wallet).label;
466
}
467
468
+ if (wallet.type == WalletType.wownero) {
469
+ return wownero!.getCurrentAccount(wallet).label;
470
+ }
471
+
472
if (wallet.type == WalletType.haven) {
473
return haven!.getCurrentAccount(wallet).label;
474
}
@@ -475,6 +479,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
479
@computed
480
bool get hasAddressList =>
481
wallet.type == WalletType.monero ||
482
+ wallet.type == WalletType.wownero ||
483
wallet.type == WalletType.haven ||
484
wallet.type == WalletType.bitcoinCash ||
485
wallet.type == WalletType.bitcoin ||
@@ -513,7 +518,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
518
void _init() {
519
_baseItems = [];
520
516
- if (wallet.type == WalletType.monero || wallet.type == WalletType.haven) {
521
+ if (wallet.type == WalletType.monero || wallet.type == WalletType.wownero || wallet.type == WalletType.haven) {
522
_baseItems.add(WalletAccountListHeader());
523
}
524