mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-18 05:51:34 +02:00
CW-1260: Enable Swap all for EVM wallets and persist amount when currency changes (#2828)
* feat: Enable Swap all for EVM wallets and persist amount when currency changes * Update local * ffeat: Recalculate amounts when swapping all and currency changes * revert formatting * fix: Review comments * refactor: streamline currency change logic * refactor: simplify currency change handling * fix: handle amount and gas estimation for swap xyz trades for swap all * Revert "fix: handle amount and gas estimation for swap xyz trades for swap all" This reverts commit 408c9dbeffdc82e08e9349d0f14b229031060c62. * feat: exclude specific providers for swap all --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
co-authored by
Omar Hatem
parent
40c4118b66
commit
2651260fe4
@@ -401,8 +401,6 @@ class _NewSwapPageState extends State<NewSwapPage> {
|
||||
address: isCurrentTypeWallet
|
||||
? exchangeViewModel.wallet.walletAddresses.addressForExchange
|
||||
: '');
|
||||
|
||||
key.currentState!.changeAmount(amount: '');
|
||||
}
|
||||
|
||||
void _onWalletNameChange(ExchangeViewModel exchangeViewModel, CryptoCurrency currency,
|
||||
|
||||
@@ -636,8 +636,6 @@ class ExchangePage extends BasePage {
|
||||
key.currentState!.changeAddress(
|
||||
address:
|
||||
isCurrentTypeWallet ? exchangeViewModel.wallet.walletAddresses.addressForExchange : '');
|
||||
|
||||
key.currentState!.changeAmount(amount: '');
|
||||
}
|
||||
|
||||
void _onWalletNameChange(ExchangeViewModel exchangeViewModel, CryptoCurrency currency,
|
||||
|
||||
@@ -48,6 +48,7 @@ import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
|
||||
import 'package:cake_wallet/store/dashboard/trades_store.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/store/templates/exchange_template_store.dart';
|
||||
import 'package:cake_wallet/evm/evm.dart';
|
||||
import 'package:cake_wallet/reactions/wallet_connect.dart';
|
||||
import 'package:cake_wallet/utils/feature_flag.dart';
|
||||
import 'package:cake_wallet/utils/token_utilities.dart';
|
||||
@@ -250,6 +251,20 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
}
|
||||
return true;
|
||||
});
|
||||
} else if (isEVMCompatibleChain(wallet.type)) {
|
||||
final currency = depositCurrency;
|
||||
final balanceCurrency = wallet.balance.keys.firstWhereOrNull(
|
||||
(c) =>
|
||||
c.title == depositCurrency.title &&
|
||||
(c.tag == depositCurrency.tag || c.tag == depositCurrency.title),
|
||||
);
|
||||
final balanceForCurrency =
|
||||
balanceCurrency != null ? wallet.balance[balanceCurrency] : null;
|
||||
if (depositCurrency == currency && balanceForCurrency != null) {
|
||||
depositAvailableAmount = _appStore.amountParsingProxy
|
||||
.getDisplayCryptoStringFromBigInt(
|
||||
balanceForCurrency.fullAvailableBalance, balanceCurrency!);
|
||||
}
|
||||
} else {
|
||||
final currency = depositCurrency;
|
||||
final amount = _appStore.amountParsingProxy.getDisplayCryptoString(
|
||||
@@ -478,9 +493,20 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
|
||||
@computed
|
||||
String? get balanceDisplay {
|
||||
final bal = wallet.balance[depositCurrency]?.fullAvailableBalance;
|
||||
if(bal == null) return null;
|
||||
return amountParsingProxy.getDisplayCryptoStringFromBigInt(bal, depositCurrency);
|
||||
CryptoCurrency? balanceCurrency;
|
||||
if (isEVMCompatibleChain(wallet.type)) {
|
||||
balanceCurrency = wallet.balance.keys.firstWhereOrNull(
|
||||
(c) =>
|
||||
c.title == depositCurrency.title &&
|
||||
(c.tag == depositCurrency.tag || c.tag == depositCurrency.title),
|
||||
);
|
||||
} else {
|
||||
balanceCurrency = depositCurrency;
|
||||
}
|
||||
final bal = balanceCurrency != null ? wallet.balance[balanceCurrency]?.fullAvailableBalance : null;
|
||||
if (bal == null) return null;
|
||||
return amountParsingProxy.getDisplayCryptoStringFromBigInt(
|
||||
bal, balanceCurrency ?? depositCurrency);
|
||||
}
|
||||
|
||||
//* Still open to further optimize these checks
|
||||
@@ -515,15 +541,23 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
return priority;
|
||||
}
|
||||
|
||||
bool get hasAllAmount =>
|
||||
[
|
||||
WalletType.monero,
|
||||
WalletType.bitcoin,
|
||||
WalletType.litecoin,
|
||||
WalletType.bitcoinCash,
|
||||
WalletType.dogecoin,
|
||||
].contains(wallet.type) &&
|
||||
(depositCurrency == wallet.currency);
|
||||
bool get hasAllAmount {
|
||||
if ([
|
||||
WalletType.monero,
|
||||
WalletType.bitcoin,
|
||||
WalletType.litecoin,
|
||||
WalletType.bitcoinCash,
|
||||
WalletType.dogecoin,
|
||||
].contains(wallet.type)) return (depositCurrency == wallet.currency);
|
||||
|
||||
if (!isEVMCompatibleChain(wallet.type)) return false;
|
||||
|
||||
if (depositCurrency == wallet.currency) return true;
|
||||
|
||||
return wallet.balance.keys.any((c) =>
|
||||
c.title == depositCurrency.title &&
|
||||
(c.tag == depositCurrency.tag || c.tag == depositCurrency.title));
|
||||
}
|
||||
|
||||
bool get isMoneroWallet => wallet.type == WalletType.monero;
|
||||
|
||||
@@ -706,26 +740,38 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
|
||||
@action
|
||||
void changeDepositCurrency({required CryptoCurrency currency}) {
|
||||
final previousCurrency = depositCurrency;
|
||||
final wasSendAllEnabled = isSendAllEnabled;
|
||||
|
||||
depositCurrency = currency;
|
||||
isFixedRateMode = false;
|
||||
_onPairChange();
|
||||
isDepositAddressEnabled = !useSameWalletAddress(depositCurrency);
|
||||
|
||||
if (previousCurrency != currency) {
|
||||
_onPairChange(clearBoth: wasSendAllEnabled);
|
||||
}
|
||||
fetchFiatPrice(currency);
|
||||
updateDepositAvailableAmount();
|
||||
}
|
||||
|
||||
@action
|
||||
void changeReceiveCurrency({required CryptoCurrency currency}) {
|
||||
final previousCurrency = receiveCurrency;
|
||||
|
||||
if (!(currency.tag == receiveCurrency.tag ||
|
||||
currency.tag == receiveCurrency.title ||
|
||||
currency.title == receiveCurrency.tag ||
|
||||
currency == receiveCurrency)) {
|
||||
receiveAddress = "";
|
||||
}
|
||||
|
||||
receiveCurrency = currency;
|
||||
isFixedRateMode = false;
|
||||
_onPairChange();
|
||||
isDepositAddressEnabled = !useSameWalletAddress(depositCurrency);
|
||||
|
||||
if (previousCurrency != currency) {
|
||||
_onPairChange();
|
||||
}
|
||||
fetchFiatPrice(currency);
|
||||
}
|
||||
|
||||
@@ -836,6 +882,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
isReceiveAmount: isFixedRateMode);
|
||||
}
|
||||
|
||||
bool _excludeProviderForSwapAll(ExchangeProvider provider) =>
|
||||
isSendAllEnabled &&
|
||||
(provider.description == ExchangeProviderDescription.swapsXyz ||
|
||||
provider.description == ExchangeProviderDescription.nearIntents);
|
||||
|
||||
Future<void> calculateBestRate() async {
|
||||
if (depositCurrency == receiveCurrency) {
|
||||
bestRate = 0.0;
|
||||
@@ -846,6 +897,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
initialAmountByAssets(isFixedRateMode ? receiveCurrency : depositCurrency);
|
||||
|
||||
final validProvidersForAmount = _tradeAvailableProviders.where((provider) {
|
||||
if (_excludeProviderForSwapAll(provider)) return false;
|
||||
|
||||
final limits = _providerLimits[provider];
|
||||
|
||||
if (limits == null) return false;
|
||||
@@ -962,7 +1015,6 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
|
||||
if (lowestMin != double.maxFinite) {
|
||||
limits = Limits(min: lowestMin, max: highestMax);
|
||||
|
||||
limitsState = LimitsLoadedSuccessfully(limits: limits);
|
||||
} else {
|
||||
limitsState = LimitsLoadedFailure(error: 'Limits loading failed');
|
||||
@@ -1081,6 +1133,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
|
||||
printV('createTrade: trying provider=${provider.title}');
|
||||
|
||||
if (_excludeProviderForSwapAll(provider)) {
|
||||
printV('Skipping Swaps.xyz or Near Intents for swap all');
|
||||
continue;
|
||||
}
|
||||
// should not happen but just as an extra check
|
||||
if (isFixedRateMode && provider.supportsFixedRate == false) {
|
||||
continue;
|
||||
@@ -1254,6 +1310,56 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
final amount = await unspentCoinsListViewModel.getSendingBalance(UnspentCoinType.any);
|
||||
|
||||
changeDepositAmount(amount: wallet.currency.formatAmount(BigInt.from(amount)), isCanonical: true);
|
||||
} else if (isEVMCompatibleChain(wallet.type)) {
|
||||
final balanceCurrency = wallet.balance.keys.firstWhereOrNull(
|
||||
(currency) =>
|
||||
currency.title == depositCurrency.title &&
|
||||
(currency.tag == depositCurrency.tag || currency.tag == depositCurrency.title),
|
||||
);
|
||||
|
||||
final balanceForCurrency = balanceCurrency != null ? wallet.balance[balanceCurrency] : null;
|
||||
if (balanceForCurrency == null) {
|
||||
changeDepositAmount(amount: wallet.currency.formatAmount(BigInt.zero), isCanonical: true);
|
||||
return;
|
||||
}
|
||||
|
||||
final balanceAmount = _appStore.amountParsingProxy.getDisplayCryptoStringFromBigInt(balanceForCurrency.fullAvailableBalance, balanceCurrency!);
|
||||
final balanceDouble = double.tryParse(balanceAmount.replaceAll(',', '.')) ?? 0.0;
|
||||
if (balanceDouble <= 0) {
|
||||
changeDepositAmount(amount: wallet.currency.formatAmount(BigInt.zero), isCanonical: true);
|
||||
return;
|
||||
}
|
||||
|
||||
final isNative = depositCurrency == wallet.currency;
|
||||
|
||||
if (!isNative) {
|
||||
changeDepositAmount(amount: balanceAmount, isCanonical: true);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final priority = _settingsStore.getPriority(wallet.type, chainId: wallet.chainId);
|
||||
await wallet.updateEstimatedFeesParams(priority);
|
||||
|
||||
String? feeString;
|
||||
if (isEVMCompatibleChain(wallet.type)) {
|
||||
feeString = evm!.getEVMNativeEstimatedFee(wallet);
|
||||
}
|
||||
|
||||
if (feeString == null || feeString.isEmpty) {
|
||||
changeDepositAmount(amount: balanceAmount, isCanonical: true);
|
||||
return;
|
||||
}
|
||||
|
||||
final balanceWei = balanceForCurrency.fullAvailableBalance;
|
||||
final feeWei = BigInt.parse(feeString);
|
||||
final amountAfterFeeWei = balanceWei > feeWei ? balanceWei - feeWei : BigInt.zero;
|
||||
changeDepositAmount(
|
||||
amount: wallet.currency.formatAmount(amountAfterFeeWei), isCanonical: true);
|
||||
} catch (e) {
|
||||
printV('Error calculating send all for EVM: $e');
|
||||
changeDepositAmount(amount: balanceAmount, isCanonical: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1293,13 +1399,26 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
||||
void removeTemplate({required ExchangeTemplate template}) =>
|
||||
_exchangeTemplateStore.remove(template: template);
|
||||
|
||||
void _onPairChange() {
|
||||
_depositAmount = '';
|
||||
_receiveAmount = '';
|
||||
void _onPairChange({bool clearBoth = false}) {
|
||||
if (clearBoth) {
|
||||
_depositAmount = '';
|
||||
_receiveAmount = '';
|
||||
if (!hasAllAmount) isSendAllEnabled = false;
|
||||
} else {
|
||||
if (isFixedRateMode) {
|
||||
_depositAmount = '';
|
||||
} else {
|
||||
_receiveAmount = '';
|
||||
}
|
||||
}
|
||||
bestRate = 0.0;
|
||||
bestRateProvider = null;
|
||||
_sortedAvailableProviders.clear();
|
||||
loadLimits();
|
||||
loadLimits().then((_) {
|
||||
if (clearBoth && hasAllAmount) {
|
||||
calculateDepositAllAmount();
|
||||
}
|
||||
});
|
||||
_setAvailableProviders();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user