feat: allow all for no-fixed monero swaps (#2353)

* feat: allow all for no-fixed monero swaps

* fix: deposit amount calculation logic and remove unused print statements

* feat: integrate UnspentCoinsListViewModel into ExchangeViewModel for more streamlined unspent coins management

* fix: unpopulating the fiat field due to a race condition

* fix: ReceiveAmount not updating on all if bestRate changes

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
Konstantin Ullrich
2025-07-09 17:08:21 +03:00
committed by GitHub
co-authored by Omar Hatem
parent cd91c783d8
commit 0a3c51206c
4 changed files with 58 additions and 44 deletions
+1
View File
@@ -521,6 +521,7 @@ Future<void> setup({
getIt.get<AppStore>().settingsStore,
getIt.get<SharedPreferences>(),
getIt.get<ContactListViewModel>(),
getIt.get<UnspentCoinsListViewModel>(),
getIt.get<FeesViewModel>(),
),
);
+11 -8
View File
@@ -6,7 +6,6 @@ import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart';
import 'package:cake_wallet/src/widgets/add_template_button.dart';
import 'package:cake_wallet/themes/core/material_base_theme.dart';
import 'package:cake_wallet/utils/debounce.dart';
import 'package:cake_wallet/utils/payment_request.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
@@ -417,12 +416,12 @@ class ExchangePage extends BasePage {
reaction(
(_) => exchangeViewModel.wallet.name,
(String _) =>
(_) =>
_onWalletNameChange(exchangeViewModel, exchangeViewModel.receiveCurrency, receiveKey));
reaction(
(_) => exchangeViewModel.wallet.name,
(String _) =>
(_) =>
_onWalletNameChange(exchangeViewModel, exchangeViewModel.depositCurrency, depositKey));
reaction((_) => exchangeViewModel.receiveCurrency,
@@ -432,8 +431,10 @@ class ExchangePage extends BasePage {
(CryptoCurrency currency) => _onCurrencyChange(currency, exchangeViewModel, depositKey));
reaction((_) => exchangeViewModel.depositAmount, (String amount) {
if (depositKey.currentState!.amountController.text != amount && amount != S.of(context).all) {
depositKey.currentState!.amountController.text = amount;
if (exchangeViewModel.isSendAllEnabled) {
depositAmountController.text = S.of(context).all;
} else if (depositAmountController.text != amount && amount != S.of(context).all) {
depositAmountController.text = amount;
}
});
@@ -521,7 +522,10 @@ class ExchangePage extends BasePage {
if (exchangeViewModel.isFixedRateMode) {
exchangeViewModel.changeReceiveAmount(amount: receiveAmountController.text);
} else {
exchangeViewModel.changeDepositAmount(amount: depositAmountController.text);
if (depositAmountController.text == S.current.all)
exchangeViewModel.changeDepositAmount(amount: exchangeViewModel.depositAmount);
else
exchangeViewModel.changeDepositAmount(amount: depositAmountController.text);
}
});
@@ -642,8 +646,7 @@ class ExchangePage extends BasePage {
Future<String> fetchParsedAddress(
BuildContext context, String domain, CryptoCurrency currency) async {
final parsedAddress = await getIt.get<AddressResolver>().resolve(context, domain, currency);
final address = await extractAddressFromParsed(context, parsedAddress);
return address;
return extractAddressFromParsed(context, parsedAddress);
}
void _showFeeAlert(BuildContext context) async {
+1 -4
View File
@@ -528,10 +528,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
});
reaction((_) => output.sendAll, (bool all) {
if (all) {
cryptoAmountController.text = S.current.all;
fiatAmountController.text = '';
}
if (all) cryptoAmountController.text = S.current.all;
});
reaction((_) => sendViewModel.selectedCryptoCurrency, (Currency currency) async {
@@ -3,25 +3,9 @@ import 'dart:collection';
import 'dart:convert';
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:cake_wallet/core/create_trade_result.dart';
import 'package:cake_wallet/exchange/provider/chainflip_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/stealth_ex_exchange_provider.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cake_wallet/view_model/send/fees_view_model.dart';
import 'package:cake_wallet/exchange/provider/xoswap_exchange_provider.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/unspent_coin_type.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:hive/hive.dart';
import 'package:intl/intl.dart';
import 'package:mobx/mobx.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/core/create_trade_result.dart';
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
@@ -31,13 +15,17 @@ import 'package:cake_wallet/exchange/exchange_template.dart';
import 'package:cake_wallet/exchange/exchange_trade_state.dart';
import 'package:cake_wallet/exchange/limits.dart';
import 'package:cake_wallet/exchange/limits_state.dart';
import 'package:cake_wallet/exchange/provider/chainflip_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/changenow_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/exolix_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/swaptrade_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/letsexchange_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/sideshift_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/stealth_ex_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/swaptrade_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
import 'package:cake_wallet/exchange/provider/xoswap_exchange_provider.dart';
import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/exchange/trade_request.dart';
import 'package:cake_wallet/generated/i18n.dart';
@@ -47,6 +35,19 @@ import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/store/templates/exchange_template_store.dart';
import 'package:cake_wallet/utils/feature_flag.dart';
import 'package:cake_wallet/view_model/contact_list/contact_list_view_model.dart';
import 'package:cake_wallet/view_model/send/fees_view_model.dart';
import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/unspent_coin_type.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/utils/proxy_wrapper.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:hive/hive.dart';
import 'package:intl/intl.dart';
import 'package:mobx/mobx.dart';
import 'package:shared_preferences/shared_preferences.dart';
part 'exchange_view_model.g.dart';
@@ -67,6 +68,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
this._settingsStore,
this.sharedPreferences,
this.contactListViewModel,
this.unspentCoinsListViewModel,
this.feesViewModel,
) : _cryptoNumberFormat = NumberFormat(),
isSendAllEnabled = false,
@@ -100,6 +102,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
];
_initialPairBasedOnWallet();
unspentCoinsListViewModel.initialSetup().then((_) {
unspentCoinsListViewModel.resetUnspentCoinsInfoSelections();
});
final Map<String, dynamic> exchangeProvidersSelection =
json.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}")
as Map<String, dynamic>;
@@ -160,13 +166,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
}
bool get isElectrumWallet =>
wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.litecoin ||
wallet.type == WalletType.bitcoinCash;
[WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type);
bool get hideAddressAfterExchange =>
wallet.type == WalletType.monero ||
wallet.type == WalletType.wownero;
[WalletType.monero, WalletType.wownero].contains(wallet.type);
bool _useTorOnly;
final Box<Trade> trades;
@@ -187,7 +190,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
useTorOnly: _useTorOnly, providerStates: _settingsStore.trocadorProviderStates),
];
@observable
ExchangeProvider? provider;
@@ -306,9 +308,12 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
}
bool get hasAllAmount =>
(wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.litecoin ||
wallet.type == WalletType.bitcoinCash) &&
[
WalletType.monero,
WalletType.bitcoin,
WalletType.litecoin,
WalletType.bitcoinCash,
].contains(wallet.type) &&
depositCurrency == wallet.currency;
bool get isMoneroWallet => wallet.type == WalletType.monero;
@@ -323,6 +328,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
final ContactListViewModel contactListViewModel;
final UnspentCoinsListViewModel unspentCoinsListViewModel;
final FeesViewModel feesViewModel;
@observable
@@ -468,7 +475,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
if (depositCurrency == receiveCurrency) {
limitsState = LimitsLoadedSuccessfully(limits: Limits(min: 0, max: 0));
return;
};
}
if (selectedProviders.isEmpty) return;
limitsState = LimitsIsLoading();
@@ -661,9 +668,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
@action
Future<void> calculateDepositAllAmount() async {
if (wallet.type == WalletType.litecoin ||
wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.bitcoinCash) {
if ([
WalletType.litecoin,
WalletType.bitcoin,
WalletType.bitcoinCash,
].contains(wallet.type)) {
final priority = _settingsStore.priority[wallet.type]!;
final amount = await bitcoin!.estimateFakeSendAllTxAmount(
@@ -673,7 +682,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
wallet.type == WalletType.litecoin ? UnspentCoinType.nonMweb : UnspentCoinType.any,
);
changeDepositAmount(amount: bitcoin!.formatterBitcoinAmountToString(amount: amount));
changeDepositAmount(amount: wallet.formatCryptoAmount(amount.toString()));
} else if (wallet.type == WalletType.monero) {
final amount = await unspentCoinsListViewModel.getSendingBalance(UnspentCoinType.any);
changeDepositAmount(amount: wallet.formatCryptoAmount(amount.toString()));
}
}