mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 19:49:22 +00:00
f8b0c0ad2a
* subaddress fix * fix subaddress generation * rewrite usedAddresses for xmr and wow * [skip ci] remove print statements * refactor address handling * do not remove manual addresses, just mark them * monero display latest address on receive page when autogenerate is enabled [skip ci] * WIP subaddresses, hidden addresses, and UI improvements for monero * update configure script * fix subaddress generation, display latest address * Update lib/core/wallet_loading_service.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * Exclude manually created addresses Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * don't call .save function multiple times Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * - revert usedAddress functinality - add mutex to prevent crashes - fix UI flashing in tx screen - fixes from comments * account index fixes added code to wownero code comment * - added subaddress index - fixed received count also accounting for change (we don't want that) - fix bad state: no element - fix search - fix automatic generation * prevent crashes by acquiring mutex before setting the pointer * - fix ttDetails generation in larger/restored wallets - show manual add icon in monero/wownero even when autogeneration is enabled - disable colors on non-debug builds - cache getAddress call in xmr/wow [skip ci] * fix: silent payment error in address setter enable fancy new features only for xmr / wow * refresh subaddress list, when we add new address fix manual addresses marking * add toggle to hide and show address * update transaction details after restore * show only one address in address book for xmr, wow and haven * fix address book reset address only when autogenerate is on * enable isEnabledAutoGenerateSubaddress on new wallets * hide addresses after exchange only for XMR and WOW * fix: bad-state no element * Update cw_monero/lib/monero_wallet_addresses.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * Update cw_monero/lib/monero_wallet_addresses.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * improvements to performance * 0, 0 -> accountIndex, addressIndex * make constant variables final * Update cw_wownero/lib/wownero_wallet_addresses.dart [skip ci] * Update cw_wownero/lib/wownero_wallet_addresses.dart [skip ci] * Update cw_monero/lib/monero_wallet.dart [skip ci] * fix potential exception * fix after removing late * remove orElse, replaced it with a try catch block. fix strings * fix valid seed function * fix null check error [skip ci] * fix updateSubaddressList for wow and haven --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
161 lines
4.6 KiB
Dart
161 lines
4.6 KiB
Dart
import 'package:cw_core/subaddress.dart';
|
|
import 'package:cw_monero/api/coins_info.dart';
|
|
import 'package:cw_monero/api/subaddress_list.dart' as subaddress_list;
|
|
import 'package:cw_monero/api/wallet.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:mobx/mobx.dart';
|
|
|
|
part 'monero_subaddress_list.g.dart';
|
|
|
|
class MoneroSubaddressList = MoneroSubaddressListBase with _$MoneroSubaddressList;
|
|
|
|
abstract class MoneroSubaddressListBase with Store {
|
|
MoneroSubaddressListBase()
|
|
: _isRefreshing = false,
|
|
_isUpdating = false,
|
|
subaddresses = ObservableList<Subaddress>();
|
|
|
|
final List<String> _usedAddresses = [];
|
|
|
|
@observable
|
|
ObservableList<Subaddress> subaddresses;
|
|
|
|
bool _isRefreshing;
|
|
bool _isUpdating;
|
|
|
|
void update({required int accountIndex}) {
|
|
refreshCoins(accountIndex);
|
|
|
|
if (_isUpdating) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
_isUpdating = true;
|
|
refresh(accountIndex: accountIndex);
|
|
subaddresses.clear();
|
|
subaddresses.addAll(getAll());
|
|
_isUpdating = false;
|
|
} catch (e) {
|
|
_isUpdating = false;
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
List<Subaddress> getAll() {
|
|
var subaddresses = subaddress_list.getAllSubaddresses();
|
|
|
|
if (subaddresses.length > 2) {
|
|
final primary = subaddresses.first;
|
|
final rest = subaddresses.sublist(1).reversed;
|
|
subaddresses = [primary] + rest.toList();
|
|
}
|
|
|
|
return subaddresses.map((s) {
|
|
final address = s.address;
|
|
final label = s.label;
|
|
final id = s.addressIndex;
|
|
return Subaddress(
|
|
id: id,
|
|
address: address,
|
|
balance: (s.received/1e12).toStringAsFixed(6),
|
|
txCount: s.txCount,
|
|
label: label);
|
|
}).toList();
|
|
}
|
|
|
|
Future<void> addSubaddress({required int accountIndex, required String label}) async {
|
|
await subaddress_list.addSubaddress(accountIndex: accountIndex, label: label);
|
|
update(accountIndex: accountIndex);
|
|
}
|
|
|
|
Future<void> setLabelSubaddress(
|
|
{required int accountIndex, required int addressIndex, required String label}) async {
|
|
await subaddress_list.setLabelForSubaddress(
|
|
accountIndex: accountIndex, addressIndex: addressIndex, label: label);
|
|
update(accountIndex: accountIndex);
|
|
}
|
|
|
|
void refresh({required int accountIndex}) {
|
|
if (_isRefreshing) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
_isRefreshing = true;
|
|
subaddress_list.refreshSubaddresses(accountIndex: accountIndex);
|
|
_isRefreshing = false;
|
|
} on PlatformException catch (e) {
|
|
_isRefreshing = false;
|
|
print(e);
|
|
rethrow;
|
|
}
|
|
}
|
|
|
|
Future<void> updateWithAutoGenerate({
|
|
required int accountIndex,
|
|
required String defaultLabel,
|
|
required List<String> usedAddresses,
|
|
}) async {
|
|
_usedAddresses.addAll(usedAddresses);
|
|
final _all = _usedAddresses.toSet().toList();
|
|
_usedAddresses.clear();
|
|
_usedAddresses.addAll(_all);
|
|
if (_isUpdating) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
_isUpdating = true;
|
|
refresh(accountIndex: accountIndex);
|
|
subaddresses.clear();
|
|
final newSubAddresses =
|
|
await _getAllUnusedAddresses(accountIndex: accountIndex, label: defaultLabel);
|
|
subaddresses.addAll(newSubAddresses);
|
|
} catch (e) {
|
|
rethrow;
|
|
} finally {
|
|
_isUpdating = false;
|
|
}
|
|
}
|
|
|
|
Future<List<Subaddress>> _getAllUnusedAddresses(
|
|
{required int accountIndex, required String label}) async {
|
|
final allAddresses = subaddress_list.getAllSubaddresses();
|
|
// first because addresses come in reversed order.
|
|
if (allAddresses.isEmpty || _usedAddresses.contains(allAddresses.first.address)) {
|
|
final isAddressUnused = await _newSubaddress(accountIndex: accountIndex, label: label);
|
|
if (!isAddressUnused) {
|
|
return await _getAllUnusedAddresses(accountIndex: accountIndex, label: label);
|
|
}
|
|
}
|
|
|
|
return allAddresses
|
|
.map((s) {
|
|
final id = s.addressIndex;
|
|
final address = s.address;
|
|
final label = s.label;
|
|
return Subaddress(
|
|
id: id,
|
|
address: address,
|
|
balance: (s.received/1e12).toStringAsFixed(6),
|
|
txCount: s.txCount,
|
|
label: id == 0 &&
|
|
label.toLowerCase() == 'Primary account'.toLowerCase()
|
|
? 'Primary address'
|
|
: label);
|
|
}).toList().reversed.toList();
|
|
}
|
|
|
|
Future<bool> _newSubaddress({required int accountIndex, required String label}) async {
|
|
await subaddress_list.addSubaddress(accountIndex: accountIndex, label: label);
|
|
|
|
return subaddress_list
|
|
.getAllSubaddresses()
|
|
.where((s) {
|
|
final address = s.address;
|
|
return !_usedAddresses.contains(address);
|
|
})
|
|
.isNotEmpty;
|
|
}
|
|
}
|