dev
dart 169 lines 5.62 KB
Raw
1 import 'package:cw_core/account.dart';
2 import 'package:cw_core/payment_uris.dart';
3 import 'package:cw_core/subaddress.dart';
4 import 'package:cw_core/utils/print_verbose.dart';
5 import 'package:cw_core/wallet_addresses.dart';
6 import 'package:cw_core/wallet_info.dart';
7 import 'package:cw_monero/api/subaddress_list.dart' as subaddress_list;
8 import 'package:cw_monero/api/wallet.dart';
9 import 'package:cw_monero/monero_account_list.dart';
10 import 'package:cw_monero/monero_subaddress_list.dart';
11 import 'package:cw_monero/monero_transaction_history.dart';
12 import 'package:mobx/mobx.dart';
13
14 part 'monero_wallet_addresses.g.dart';
15
16 class MoneroWalletAddresses = MoneroWalletAddressesBase with _$MoneroWalletAddresses;
17
18 abstract class MoneroWalletAddressesBase extends WalletAddresses with Store {
19 MoneroWalletAddressesBase(
20 WalletInfo walletInfo, MoneroTransactionHistory moneroTransactionHistory)
21 : accountList = MoneroAccountList(),
22 _moneroTransactionHistory = moneroTransactionHistory,
23 subaddressList = MoneroSubaddressList(),
24 address = '',
25 super(walletInfo);
26
27 final MoneroTransactionHistory _moneroTransactionHistory;
28 @override
29 @observable
30 String address;
31
32 @override
33 String get primaryAddress => getAddress(accountIndex: account?.id ?? 0, addressIndex: 0);
34
35 @override
36 String get latestAddress {
37 var addressIndex = subaddress_list.numSubaddresses(account?.id ?? 0) - 1;
38 var address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
39 while (hiddenAddresses.contains(address)) {
40 addressIndex++;
41 address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
42 subaddressList.update(accountIndex: account?.id ?? 0);
43 }
44 return address;
45 }
46
47 @override
48 String get addressForExchange {
49 var addressIndex = subaddress_list.numSubaddresses(account?.id ?? 0) - 1;
50 var address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
51 while (hiddenAddresses.contains(address) ||
52 manualAddresses.contains(address) ||
53 subaddress_list
54 .getRawLabel(accountIndex: account?.id ?? 0, addressIndex: addressIndex)
55 .isNotEmpty) {
56 addressIndex++;
57 address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
58 subaddressList.update(accountIndex: account?.id ?? 0);
59 }
60 return address;
61 }
62
63 @observable
64 Account? account;
65
66 @observable
67 Subaddress? subaddress;
68
69 MoneroSubaddressList subaddressList;
70
71 MoneroAccountList accountList;
72
73 Set<String> usedAddresses = Set();
74
75 @override
76 Future<void> init() async {
77 accountList.update();
78 account = accountList.accounts.isEmpty
79 ? Account(id: 0, label: "Primary address")
80 : accountList.accounts.first;
81 await updateSubaddressList(accountIndex: account?.id ?? 0);
82 await updateAddressesInBox();
83 }
84
85 @override
86 Future<void> updateAddressesInBox() async {
87 try {
88 final _subaddressList = MoneroSubaddressList();
89
90 addressesMap.clear();
91 addressInfos.clear();
92
93 for (final account in accountList.accounts) {
94 await _subaddressList.update(accountIndex: account.id);
95 _subaddressList.subaddresses.forEach((subaddress) {
96 addressesMap[subaddress.address] = subaddress.label;
97 addressInfos[account.id] ??= [];
98 addressInfos[account.id]?.add(WalletInfoAddressInfo(
99 walletInfoId: walletInfo.internalId,
100 mapKey: account.id,
101 accountIndex: account.id,
102 address: subaddress.address,
103 label: subaddress.label));
104 });
105 }
106
107 await saveAddressesInBox();
108 } catch (e) {
109 printV(e.toString());
110 }
111 }
112
113 bool validate() {
114 accountList.update();
115 final accountListLength = accountList.accounts.length;
116
117 if (accountListLength <= 0) {
118 return false;
119 }
120
121 subaddressList.update(accountIndex: accountList.accounts.first.id);
122 final subaddressListLength = subaddressList.subaddresses.length;
123
124 if (subaddressListLength <= 0) {
125 return false;
126 }
127
128 return true;
129 }
130
131 Future<void> updateSubaddressList({required int accountIndex}) async {
132 await subaddressList.update(accountIndex: accountIndex);
133 address = subaddressList.subaddresses.isNotEmpty
134 ? subaddressList.subaddresses.first.address
135 : getAddress();
136 }
137
138 Future<void> updateUsedSubaddress() async {
139 final transactions = _moneroTransactionHistory.transactions.values.toList();
140
141 transactions.forEach((element) {
142 final accountIndex = element.additionalInfo['accountIndex'] as int? ?? 0;
143 final addressIndex = element.additionalInfo['addressIndex'] as int? ?? 0;
144 usedAddresses.add(getAddress(accountIndex: accountIndex, addressIndex: addressIndex));
145 });
146 }
147
148 Future<void> updateUnusedSubaddress(
149 {required int accountIndex, required String defaultLabel}) async {
150 await subaddressList.updateWithAutoGenerate(
151 accountIndex: accountIndex,
152 defaultLabel: defaultLabel,
153 usedAddresses: usedAddresses.toList());
154 subaddress = (subaddressList.subaddresses.isEmpty)
155 ? Subaddress(id: 0, address: address, label: defaultLabel, balance: '0', txCount: 0)
156 : subaddressList.subaddresses.last;
157 if (num.tryParse(subaddress!.balance ?? '0') != 0) {
158 getAddress(accountIndex: accountIndex, addressIndex: (subaddress?.id ?? 0) + 1);
159 }
160 address = subaddress!.address;
161 }
162
163 @override
164 bool containsAddress(String address) =>
165 addressInfos[account?.id ?? 0]?.any((it) => it.address == address) ?? false;
166
167 @override
168 PaymentURI getPaymentUri(String amount) => MoneroURI(address: address, amount: amount);
169 }