From d772beda455ea0e25fc5fbd369a67ce7c0288c7e Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 27 Nov 2024 15:23:46 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../ui/notifications/NotificationsFactory.kt | 13 +++++- .../tangem/utils/coroutines/CoroutineExt.kt | 3 +- .../state/confirm/SendNotificationFactory.kt | 2 +- .../AddStakingNotificationsTransformer.kt | 2 +- .../feature/swap/domain/SwapInteractor.kt | 3 ++ .../feature/swap/domain/SwapInteractorImpl.kt | 32 +++++++++++--- .../tangem/feature/swap/models/UiActions.kt | 5 ++- .../presentation/SwapNotificationsFactory.kt | 24 +++++----- .../swap/viewmodels/SwapProcessDataState.kt | 2 + .../feature/swap/viewmodels/SwapViewModel.kt | 44 ++++++++++++------- .../com/tangem/lib/crypto/BlockchainUtils.kt | 1 - 11 files changed, 90 insertions(+), 41 deletions(-) diff --git a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt index e50a8bdfa7..306b8c1922 100644 --- a/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt +++ b/common/ui/src/main/java/com/tangem/common/ui/notifications/NotificationsFactory.kt @@ -113,10 +113,19 @@ object NotificationsFactory { } } + /** + * Adds Existential Warning + * + * @param existentialDeposit existential deposit of blockchain + * @param feeAmount amount of fee spending for transaction + * @param sendingAmount amount sending by user (excluding fee for coins) + * @param cryptoCurrencyStatus blockchain currency status + * @param onReduceClick action to leave existential amount in balance after transaction + */ fun MutableList.addExistentialWarningNotification( existentialDeposit: BigDecimal?, feeAmount: BigDecimal, - receivedAmount: BigDecimal, + sendingAmount: BigDecimal, cryptoCurrencyStatus: CryptoCurrencyStatus, onReduceClick: ( reduceAmountBy: BigDecimal, @@ -129,7 +138,7 @@ object NotificationsFactory { val spendingAmount = if (cryptoCurrency is CryptoCurrency.Token) { feeAmount } else { - receivedAmount + feeAmount + sendingAmount } val diff = balance.minus(spendingAmount) if (existentialDeposit != null && diff >= BigDecimal.ZERO && existentialDeposit > diff) { diff --git a/core/utils/src/main/java/com/tangem/utils/coroutines/CoroutineExt.kt b/core/utils/src/main/java/com/tangem/utils/coroutines/CoroutineExt.kt index cfa0536804..d0b50ceab4 100644 --- a/core/utils/src/main/java/com/tangem/utils/coroutines/CoroutineExt.kt +++ b/core/utils/src/main/java/com/tangem/utils/coroutines/CoroutineExt.kt @@ -25,11 +25,12 @@ class Debouncer { coroutineScope: CoroutineScope, waitMs: Long = 300L, context: CoroutineContext = EmptyCoroutineContext, + forceUpdate: Boolean = false, destinationFunction: suspend () -> Unit, ) { debounceJob?.cancel() debounceJob = coroutineScope.launch(context) { - delay(waitMs) + if (!forceUpdate) delay(waitMs) destinationFunction.invoke() } } diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt index 4c92572d5b..f4eb2fd9c4 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/confirm/SendNotificationFactory.kt @@ -234,7 +234,7 @@ internal class SendNotificationFactory( addExistentialWarningNotification( existentialDeposit = currencyCheck.existentialDeposit, feeAmount = feeState.fee?.amount?.value.orZero(), - receivedAmount = sendingAmount, + sendingAmount = sendingAmount, cryptoCurrencyStatus = cryptoCurrencyStatus, onReduceClick = clickIntents::onAmountReduceByClick, ) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt index f89e821f79..c46880d541 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt @@ -198,7 +198,7 @@ internal class AddStakingNotificationsTransformer( addExistentialWarningNotification( existentialDeposit = currencyCheck.existentialDeposit, feeAmount = feeState?.fee?.amount?.value.orZero(), - receivedAmount = sendingAmount, + sendingAmount = sendingAmount, cryptoCurrencyStatus = cryptoCurrencyStatus, onReduceClick = prevState.clickIntents::onAmountReduceByClick, ) diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt index 3154fa4293..871f5f5e70 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractor.kt @@ -9,6 +9,7 @@ import com.tangem.feature.swap.domain.models.domain.PermissionOptions import com.tangem.feature.swap.domain.models.domain.SwapDataModel import com.tangem.feature.swap.domain.models.domain.SwapProvider import com.tangem.feature.swap.domain.models.ui.* +import java.math.BigDecimal interface SwapInteractor { @@ -39,6 +40,7 @@ interface SwapInteractor { toToken: CryptoCurrencyStatus, providers: List, amountToSwap: String, + reduceBalanceBy: BigDecimal, selectedFee: FeeType = FeeType.NORMAL, ): Map @@ -70,6 +72,7 @@ interface SwapInteractor { selectedFee: FeeType, fromToken: CryptoCurrencyStatus, amountToSwap: String, + reduceBalanceBy: BigDecimal, ): SwapState.QuotesLoadedState /** diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt index e57ea6fcf7..270b21d6bb 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/SwapInteractorImpl.kt @@ -4,8 +4,8 @@ import arrow.core.Either import arrow.core.getOrElse import com.tangem.blockchain.common.Amount import com.tangem.blockchain.common.AmountType -import com.tangem.blockchain.common.Blockchain.* import com.tangem.blockchain.common.Blockchain +import com.tangem.blockchain.common.Blockchain.* import com.tangem.blockchain.common.TransactionExtras import com.tangem.blockchain.common.transaction.Fee import com.tangem.blockchain.common.transaction.TransactionFee @@ -251,6 +251,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( toToken: CryptoCurrencyStatus, providers: List, amountToSwap: String, + reduceBalanceBy: BigDecimal, selectedFee: FeeType, ): Map { Timber.i( @@ -291,6 +292,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( toToken = toToken, provider = provider, amount = amount, + reduceBalanceBy = reduceBalanceBy, isBalanceWithoutFeeEnough = isBalanceWithoutFeeEnough, ) } @@ -369,11 +371,13 @@ internal class SwapInteractorImpl @AssistedInject constructor( toToken: CryptoCurrencyStatus, provider: SwapProvider, amount: SwapAmount, + reduceBalanceBy: BigDecimal, isBalanceWithoutFeeEnough: Boolean, ): Pair { return provider to loadCexQuoteData( networkId = networkId, amount = amount, + reduceBalanceBy = reduceBalanceBy, fromTokenStatus = fromToken, toTokenStatus = toToken, isAllowedToSpend = true, @@ -392,12 +396,15 @@ internal class SwapInteractorImpl @AssistedInject constructor( is TxFeeState.MultipleFeeState -> feeState.priorityFee.feeValue is TxFeeState.SingleFeeState -> feeState.fee.feeValue } + val statusValue = fromTokenStatus.value as? CryptoCurrencyStatus.Loaded + val balanceAfterTransaction = statusValue?.let { it.amount - amount.value - fee } val currencyCheck = getCurrencyCheckUseCase( userWalletId = userWalletId, currencyStatus = fromTokenStatus, amount = amount.value, fee = fee, + balanceAfterTransaction = balanceAfterTransaction, ) return currencyCheck @@ -494,6 +501,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( selectedFee: FeeType, fromToken: CryptoCurrencyStatus, amountToSwap: String, + reduceBalanceBy: BigDecimal, ): SwapState.QuotesLoadedState { val amountDecimal = toBigDecimalOrNull(amountToSwap) if (amountDecimal == null || amountDecimal.signum() == 0) { @@ -504,6 +512,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( networkId = fromToken.currency.network.backendId, txFee = state.txFee, amount = amount, + reduceBalanceBy = reduceBalanceBy, fromToken = fromToken.currency, ) val fee = when (val txFee = state.txFee) { @@ -1023,6 +1032,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( private suspend fun loadCexQuoteData( networkId: String, amount: SwapAmount, + reduceBalanceBy: BigDecimal, fromTokenStatus: CryptoCurrencyStatus, toTokenStatus: CryptoCurrencyStatus, provider: SwapProvider, @@ -1048,6 +1058,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( networkId = networkId, txFee = txFee, amount = amount, + reduceBalanceBy = reduceBalanceBy, fromToken = fromToken, ) val amountToRequest = if (includeFeeInAmount is IncludeFeeInAmount.Included) { @@ -1200,6 +1211,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( networkId: String, txFee: TxFeeState, amount: SwapAmount, + reduceBalanceBy: BigDecimal, fromToken: CryptoCurrency, ): IncludeFeeInAmount { val feeValue = when (txFee) { @@ -1219,13 +1231,20 @@ internal class SwapInteractorImpl @AssistedInject constructor( IncludeFeeInAmount.BalanceNotEnough } } - else -> getIncludeFeeAmountForCoinFee(networkId, amount, feeValue, fromToken) + else -> getIncludeFeeAmountForCoinFee( + networkId = networkId, + amount = amount, + reduceBalanceBy = reduceBalanceBy, + feeValue = feeValue, + fromToken = fromToken, + ) } } private suspend fun getIncludeFeeAmountForCoinFee( networkId: String, amount: SwapAmount, + reduceBalanceBy: BigDecimal, feeValue: BigDecimal, fromToken: CryptoCurrency, ): IncludeFeeInAmount { @@ -1234,26 +1253,27 @@ internal class SwapInteractorImpl @AssistedInject constructor( networkId, fromToken.network.derivationPath.value, ) ?: ProxyAmount.empty() + val reducedBalance = tokenForFeeBalance.value - reduceBalanceBy val amountWithFee = amount.value + feeValue return when { fromToken is CryptoCurrency.Token -> { - if (feeValue > tokenForFeeBalance.value || tokenForFeeBalance.value.signum() == 0) { + if (feeValue > reducedBalance || reducedBalance.signum() == 0) { IncludeFeeInAmount.BalanceNotEnough } else { IncludeFeeInAmount.Excluded } } - amount.value > tokenForFeeBalance.value -> { + amount.value > reducedBalance -> { IncludeFeeInAmount.BalanceNotEnough } - amountWithFee < tokenForFeeBalance.value -> { + amountWithFee < reducedBalance -> { IncludeFeeInAmount.Excluded } else -> { if (feeValue < amount.value) { IncludeFeeInAmount.Included( SwapAmount( - tokenForFeeBalance.value - feeValue, + reducedBalance - feeValue, getNativeToken(fromToken.network.backendId).decimals, ), ) diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/UiActions.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/UiActions.kt index c25fc38225..05e17e542b 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/UiActions.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/UiActions.kt @@ -4,6 +4,7 @@ import com.tangem.common.ui.bottomsheet.permission.state.ApproveType import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.feature.swap.domain.models.SwapAmount import com.tangem.feature.swap.domain.models.ui.TxFee +import java.math.BigDecimal data class UiActions( val onSearchEntered: (String) -> Unit, @@ -15,8 +16,8 @@ data class UiActions( val onChangeCardsClicked: () -> Unit, val onBackClicked: () -> Unit, val onMaxAmountSelected: () -> Unit, - val onReduceAmount: (SwapAmount) -> Unit, - val onLeaveExistentialDeposit: (SwapAmount) -> Unit, + val onReduceToAmount: (SwapAmount) -> Unit, + val onReduceByAmount: (SwapAmount, reduceBy: BigDecimal) -> Unit, val openPermissionBottomSheet: () -> Unit, val onChangeApproveType: (ApproveType) -> Unit, // region new actions diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapNotificationsFactory.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapNotificationsFactory.kt index 38fc6507ad..d648e03355 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapNotificationsFactory.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/presentation/SwapNotificationsFactory.kt @@ -134,10 +134,11 @@ internal class SwapNotificationsFactory( ) { val fromCurrencyStatus = quoteModel.fromTokenInfo.cryptoCurrencyStatus val includeFeeInAmount = quoteModel.preparedSwapConfigState.includeFeeInAmount + val amount = quoteModel.fromTokenInfo.tokenAmount val amountToRequest = if (includeFeeInAmount is IncludeFeeInAmount.Included) { includeFeeInAmount.amountSubtractFee } else { - quoteModel.fromTokenInfo.tokenAmount + amount } val fee = when (val feeState = quoteModel.txFee) { TxFeeState.Empty -> null @@ -154,13 +155,12 @@ internal class SwapNotificationsFactory( addExistentialWarningNotification( existentialDeposit = quoteModel.currencyCheck?.existentialDeposit, feeAmount = fee?.feeValue.orZero(), - receivedAmount = amountToRequest.value, + sendingAmount = amount.value, cryptoCurrencyStatus = fromCurrencyStatus, - onReduceClick = { _, reduceByDiff, _ -> - actions.onLeaveExistentialDeposit( - amountToRequest.copy( - value = amountToRequest.value.minus(reduceByDiff).minus(fee?.feeValue.orZero()), - ), + onReduceClick = { reduceBy, reduceByDiff, _ -> + actions.onReduceByAmount( + amount.copy(value = amount.value.minus(reduceByDiff)), + reduceBy, ) }, ) @@ -170,7 +170,7 @@ internal class SwapNotificationsFactory( cryptoCurrency = fromCurrencyStatus.currency, minAdaValue = quoteModel.minAdaValue, onReduceClick = { reduceTo, _ -> - actions.onLeaveExistentialDeposit(amountToRequest.copy(value = reduceTo)) + actions.onReduceToAmount(amount.copy(value = reduceTo)) }, ) if (!isCardano) { @@ -191,13 +191,13 @@ internal class SwapNotificationsFactory( addReduceAmountNotification( cryptoCurrencyStatus = fromCurrencyStatus, fromAmount = quoteModel.fromTokenInfo.tokenAmount, - onReduceAmount = actions.onReduceAmount, + onReduceByAmount = actions.onReduceByAmount, ) addTransactionLimitErrorNotification( utxoLimit = quoteModel.currencyCheck?.utxoAmountLimit, cryptoCurrency = fromCurrencyStatus.currency, onReduceClick = { reduceTo, _ -> - actions.onReduceAmount(amountToRequest.copy(value = reduceTo)) + actions.onReduceToAmount(amountToRequest.copy(value = reduceTo)) }, ) } @@ -294,7 +294,7 @@ internal class SwapNotificationsFactory( private fun MutableList.addReduceAmountNotification( cryptoCurrencyStatus: CryptoCurrencyStatus, fromAmount: SwapAmount, - onReduceAmount: (SwapAmount) -> Unit, + onReduceByAmount: (SwapAmount, BigDecimal) -> Unit, ) { val isTezos = isTezos(cryptoCurrencyStatus.currency.network.id.value) val balance = cryptoCurrencyStatus.value.amount ?: BigDecimal.ZERO @@ -309,7 +309,7 @@ internal class SwapNotificationsFactory( val patchedAmount = fromAmount.copy( value = fromAmount.value - threshold, ) - onReduceAmount(patchedAmount) + onReduceByAmount(patchedAmount, threshold) }, ), ) diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapProcessDataState.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapProcessDataState.kt index 65f4774f5f..3d53f18f52 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapProcessDataState.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapProcessDataState.kt @@ -7,6 +7,7 @@ import com.tangem.feature.swap.domain.models.ui.RequestApproveStateData import com.tangem.feature.swap.domain.models.ui.SwapState import com.tangem.feature.swap.domain.models.ui.TokensDataStateExpress import com.tangem.feature.swap.domain.models.ui.TxFee +import java.math.BigDecimal data class SwapProcessDataState( // Initial network id @@ -15,6 +16,7 @@ data class SwapProcessDataState( val feePaidCryptoCurrency: CryptoCurrencyStatus? = null, // Amount from input val amount: String? = null, + val reduceBalanceBy: BigDecimal = BigDecimal.ZERO, val approveDataModel: RequestApproveStateData? = null, val swapDataModel: SwapDataModel? = null, val selectedFee: TxFee? = null, diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt index d3dc6a591e..bdffaf4f6b 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt @@ -25,11 +25,7 @@ import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.BlockchainErrorInfo import com.tangem.domain.feedback.models.FeedbackEmailType -import com.tangem.domain.tokens.GetCryptoCurrencyStatusSyncUseCase -import com.tangem.domain.tokens.GetCurrencyStatusUpdatesUseCase -import com.tangem.domain.tokens.GetMinimumTransactionAmountSyncUseCase -import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase -import com.tangem.domain.tokens.UpdateDelayedNetworkStatusUseCase +import com.tangem.domain.tokens.* import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.Network @@ -144,6 +140,7 @@ internal class SwapViewModel @Inject constructor( // shows currency order (direct - swap initial to selected, reversed = selected to initial) private var isOrderReversed = false private val lastAmount = mutableStateOf(INITIAL_AMOUNT) + private val lastReducedBalanceBy = mutableStateOf(BigDecimal.ZERO) private var swapRouter: SwapRouter by Delegates.notNull() private val isUserResolvableError: (SwapState) -> Boolean = { @@ -304,6 +301,7 @@ internal class SwapViewModel @Inject constructor( fromToken = fromCurrencyStatus, toToken = toCurrencyStatus, amount = lastAmount.value, + reduceBalanceBy = lastReducedBalanceBy.value, toProvidersList = findSwapProviders(fromCurrencyStatus, toCurrencyStatus), ) } @@ -321,6 +319,7 @@ internal class SwapViewModel @Inject constructor( fromToken: CryptoCurrencyStatus, toToken: CryptoCurrencyStatus, amount: String, + reduceBalanceBy: BigDecimal, toProvidersList: List, isSilent: Boolean = false, ) { @@ -339,6 +338,7 @@ internal class SwapViewModel @Inject constructor( fromToken = fromToken, toToken = toToken, amount = amount, + reduceBalanceBy = reduceBalanceBy, toProvidersList = toProvidersList, ), ) @@ -354,6 +354,7 @@ internal class SwapViewModel @Inject constructor( toToken = toCurrency, amount = amount, isSilent = isSilent, + reduceBalanceBy = dataState.reduceBalanceBy, toProvidersList = findSwapProviders(fromCurrency, toCurrency), ) } @@ -363,6 +364,7 @@ internal class SwapViewModel @Inject constructor( fromToken: CryptoCurrencyStatus, toToken: CryptoCurrencyStatus, amount: String, + reduceBalanceBy: BigDecimal, toProvidersList: List, ): PeriodicTask> { return PeriodicTask( @@ -372,6 +374,7 @@ internal class SwapViewModel @Inject constructor( runCatching(dispatchers.io) { dataState = dataState.copy( amount = amount, + reduceBalanceBy = reduceBalanceBy, swapDataModel = null, approveDataModel = null, ) @@ -380,6 +383,7 @@ internal class SwapViewModel @Inject constructor( toToken = toToken, providers = toProvidersList, amountToSwap = amount, + reduceBalanceBy = reduceBalanceBy, selectedFee = dataState.selectedFee?.feeType ?: FeeType.NORMAL, ) } @@ -817,6 +821,7 @@ internal class SwapViewModel @Inject constructor( fromToken = fromToken, toToken = toToken, amount = lastAmount.value, + reduceBalanceBy = lastReducedBalanceBy.value, toProvidersList = findSwapProviders(fromToken, toToken), ) swapRouter.openScreen(SwapNavScreen.Main) @@ -886,6 +891,7 @@ internal class SwapViewModel @Inject constructor( ).getOrNull() val decimals = newFromToken.currency.decimals lastAmount.value = cutAmountWithDecimals(decimals, lastAmount.value) + lastReducedBalanceBy.value = BigDecimal.ZERO uiState = stateBuilder.updateSwapAmount( uiState = uiState, amountFormatted = inputNumberFormatter.formatWithThousands(lastAmount.value, decimals), @@ -897,13 +903,18 @@ internal class SwapViewModel @Inject constructor( fromToken = newFromToken, toToken = newToToken, amount = lastAmount.value, + reduceBalanceBy = lastReducedBalanceBy.value, toProvidersList = findSwapProviders(newFromToken, newToToken), ) } } } - private fun onAmountChanged(value: String) { + private fun onAmountChanged( + value: String, + forceQuotesUpdate: Boolean = false, + reduceBalanceBy: BigDecimal = BigDecimal.ZERO, + ) { viewModelScope.launch { val fromToken = dataState.fromCryptoCurrency val toToken = dataState.toCryptoCurrency @@ -915,6 +926,7 @@ internal class SwapViewModel @Inject constructor( fromToken, ).getOrNull() lastAmount.value = cutValue + lastReducedBalanceBy.value = reduceBalanceBy uiState = stateBuilder.updateSwapAmount( uiState = uiState, amountFormatted = inputNumberFormatter.formatWithThousands(cutValue, decimals), @@ -928,11 +940,12 @@ internal class SwapViewModel @Inject constructor( isAmountChangedByUser = true } - amountDebouncer.debounce(viewModelScope, DEBOUNCE_AMOUNT_DELAY) { + amountDebouncer.debounce(viewModelScope, DEBOUNCE_AMOUNT_DELAY, forceUpdate = forceQuotesUpdate) { startLoadingQuotes( fromToken = fromToken, toToken = toToken, amount = lastAmount.value, + reduceBalanceBy = lastReducedBalanceBy.value, toProvidersList = findSwapProviders(fromToken, toToken), ) } @@ -948,12 +961,12 @@ internal class SwapViewModel @Inject constructor( } } - private fun onReduceAmountClicked(newAmount: SwapAmount) { - onAmountChanged(newAmount.formatToUIRepresentation()) - } - - private fun onLeaveExistentialDepositClicked(newAmount: SwapAmount) { - onAmountChanged(newAmount.formatToUIRepresentation()) + private fun onReduceAmountClicked(newAmount: SwapAmount, reduceBalanceBy: BigDecimal = BigDecimal.ZERO) { + onAmountChanged( + value = newAmount.formatToUIRepresentation(), + forceQuotesUpdate = true, + reduceBalanceBy = reduceBalanceBy, + ) } private fun onAmountSelected(selected: Boolean) { @@ -1014,8 +1027,8 @@ internal class SwapViewModel @Inject constructor( onSearchEntered("") }, onMaxAmountSelected = ::onMaxAmountClicked, - onReduceAmount = ::onReduceAmountClicked, - onLeaveExistentialDeposit = ::onLeaveExistentialDepositClicked, + onReduceToAmount = ::onReduceAmountClicked, + onReduceByAmount = ::onReduceAmountClicked, openPermissionBottomSheet = { singleTaskScheduler.cancelTask() analyticsEventHandler.send(SwapEvents.ButtonGivePermissionClicked) @@ -1054,6 +1067,7 @@ internal class SwapViewModel @Inject constructor( selectedFee = it.feeType, fromToken = fromToken, amountToSwap = amountToSwap, + reduceBalanceBy = dataState.reduceBalanceBy, ) setupLoadedState(selectedProvider, updatedState, fromToken) } diff --git a/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt b/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt index 46a15a7443..aa94f8b29c 100644 --- a/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt +++ b/libs/crypto/src/main/java/com/tangem/lib/crypto/BlockchainUtils.kt @@ -5,7 +5,6 @@ import com.tangem.blockchain.common.Blockchain import com.tangem.blockchainsdk.compatibility.l2BlockchainsList import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.blockchainsdk.utils.fromNetworkId -import com.tangem.blockchainsdk.utils.isSupportedInApp import com.tangem.blockchainsdk.utils.minimalAmount import com.tangem.lib.crypto.converter.XrpTaggedAddressConverter import com.tangem.lib.crypto.models.XrpTaggedAddress