Cw 925 improve automatic subaddress generation behavior (#2217)

* fix: update usedAddresses for monero * fix: subaddresses generation for bitcoin * fix: minor fix * fix: update receive address UI when used * minor fix [skip ci]

Serhii committed Apr 30, 2025 at 19:11 UTC 4448adb49ddc698baeb97687d91970233111989c
3 files changed +28 -22
cw_bitcoin/lib/bitcoin_address_record.dart
+5 -4
@@ -1,4 +1,5 @@
1 import 'dart:convert';
2 +import 'package:mobx/mobx.dart';
3
4 import 'package:bitcoin_base/bitcoin_base.dart';
5
@@ -16,7 +17,7 @@ abstract class BaseBitcoinAddressRecord {
17 }) : _txCount = txCount,
18 _balance = balance,
19 _name = name,
19 - _isUsed = isUsed;
20 + _isUsed = Observable(isUsed);
21
22 @override
23 bool operator ==(Object o) => o is BaseBitcoinAddressRecord && address == o.address;
@@ -27,7 +28,7 @@ abstract class BaseBitcoinAddressRecord {
28 int _txCount;
29 int _balance;
30 String _name;
30 - bool _isUsed;
31 + final Observable<bool> _isUsed;
32 BasedUtxoNetwork? network;
33
34 int get txCount => _txCount;
@@ -40,9 +41,9 @@ abstract class BaseBitcoinAddressRecord {
41
42 set balance(int value) => _balance = value;
43
43 - bool get isUsed => _isUsed;
44 + bool get isUsed => _isUsed.value;
45
45 - void setAsUsed() => _isUsed = true;
46 + void setAsUsed() => _isUsed.value = true;
47 void setNewName(String label) => _name = label;
48
49 int get hashCode => address.hashCode;
cw_bitcoin/lib/electrum_wallet_addresses.dart
+21 -16
@@ -144,27 +144,32 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
144 return silentAddress.toString();
145 }
146
147 - String receiveAddress;
147 + final typeMatchingAddresses = _addresses.where((addr) => !addr.isHidden && _isAddressPageTypeMatch(addr)).toList();
148 + final typeMatchingReceiveAddresses = typeMatchingAddresses.where((addr) => !addr.isUsed).toList();
149
149 - final typeMatchingReceiveAddresses =
150 - receiveAddresses.where(_isAddressPageTypeMatch).where((addr) => !addr.isUsed);
151 -
152 - if ((isEnabledAutoGenerateSubaddress && receiveAddresses.isEmpty) ||
153 - typeMatchingReceiveAddresses.isEmpty) {
154 - receiveAddress = generateNewAddress().address;
155 - } else {
156 - final previousAddressMatchesType =
157 - previousAddressRecord != null && previousAddressRecord!.type == addressPageType;
150 + if (!isEnabledAutoGenerateSubaddress) {
151 + if (previousAddressRecord != null &&
152 + previousAddressRecord!.type == addressPageType) {
153 + return previousAddressRecord!.address;
154 + }
155
159 - if (previousAddressMatchesType &&
160 - typeMatchingReceiveAddresses.first.address != addressesByReceiveType.first.address) {
161 - receiveAddress = previousAddressRecord!.address;
162 - } else {
163 - receiveAddress = typeMatchingReceiveAddresses.first.address;
156 + if (typeMatchingAddresses.isNotEmpty) {
157 + return typeMatchingAddresses.first.address;
158 }
159 +
160 + return generateNewAddress().address;
161 + }
162 +
163 + if (typeMatchingAddresses.isEmpty || typeMatchingReceiveAddresses.isEmpty) {
164 + return generateNewAddress().address;
165 + }
166 +
167 + final prev = previousAddressRecord;
168 + if (prev != null && prev.type == addressPageType && !prev.isUsed) {
169 + return prev.address;
170 }
171
167 - return receiveAddress;
172 + return typeMatchingReceiveAddresses.first.address;
173 }
174
175 @observable
cw_monero/lib/monero_wallet_addresses.dart
+2 -2
@@ -130,8 +130,8 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store {
130 final transactions = _moneroTransactionHistory.transactions.values.toList();
131
132 transactions.forEach((element) {
133 - final accountIndex = element.accountIndex;
134 - final addressIndex = element.addressIndex;
133 + final accountIndex = element.additionalInfo['accountIndex'] as int? ?? 0;
134 + final addressIndex = element.additionalInfo['addressIndex'] as int? ?? 0;
135 usedAddresses.add(getAddress(accountIndex: accountIndex, addressIndex: addressIndex));
136 });
137 }