From c2211d24209f193f8130e85181d6fb01697051d2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 24 Mar 2026 20:47:34 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../feature/swap/DefaultSwapComponent.kt | 8 +++ .../tangem/feature/swap/model/SwapModel.kt | 62 +++++++++++++++---- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/DefaultSwapComponent.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/DefaultSwapComponent.kt index 033d257c1d..1ff45460be 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/DefaultSwapComponent.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/DefaultSwapComponent.kt @@ -38,6 +38,7 @@ import com.tangem.utils.extensions.isZero import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import timber.log.Timber import java.math.BigDecimal @Suppress("UnusedPrivateMember") @@ -130,16 +131,23 @@ internal class DefaultSwapComponent @AssistedInject constructor( LaunchedEffect(fromCryptoCurrency, feePaidCryptoCurrency, shouldHideBlock) { if (shouldHideBlock) { + Timber.e( + "Dismissing fee selector: " + + "shouldHideBlock = $shouldHideBlock, amount = ${dataState.amount}, " + + "isInsufficientFunds = ${model.uiState.isInsufficientFunds}", + ) slotNavigation.dismiss() return@LaunchedEffect } val sendingCryptoCurrencyStatus = fromCryptoCurrency ?: run { + Timber.e("Dismissing fee selector: fromCryptoCurrency is null") slotNavigation.dismiss() return@LaunchedEffect } val feeCurrencyStatus = feePaidCryptoCurrency ?: run { + Timber.e("Dismissing fee selector: feePaidCryptoCurrency is null") slotNavigation.dismiss() return@LaunchedEffect } diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt index 4c90fa3f34..f0a157cbe2 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt @@ -544,7 +544,11 @@ internal class SwapModel @Inject constructor( dataState.fromCryptoCurrency } - if (fromCryptoCurrency != null) updateFeePaidCryptoCurrencyFor(fromCryptoCurrency) + if (fromCryptoCurrency != null) { + updateFeePaidCryptoCurrencyFor(fromCryptoCurrency) + } else { + Timber.e("updateFeePaidCryptoCurrencyFor failed: fromCryptoCurrency is null") + } subscribeToCoinBalanceUpdatesIfNeeded() }.onFailure { error -> @@ -771,7 +775,14 @@ internal class SwapModel @Inject constructor( feePaidCryptoCurrency = getFeePaidCryptoCurrencyStatusSyncUseCase( userWalletId = userWalletId, cryptoCurrencyStatus = fromToken, - ).getOrNull(), + ) + .onLeft { Timber.e("Unable to get fee paid crypto currency status for ${fromToken.currency.id}") } + .onRight { currencyStatus -> + if (currencyStatus == null) { + Timber.e("Fee paid crypto currency status is null for ${fromToken.currency.id}") + } + } + .getOrNull(), ) } @@ -1046,6 +1057,7 @@ internal class SwapModel @Inject constructor( val fee = getSelectedFee() if (fee == null && tangemPayInput?.isWithdrawal != true) { + Timber.e("onSwapClick: fee is null and isWithdrawal is ${tangemPayInput?.isWithdrawal}") showAlert(resourceReference(R.string.swapping_fee_estimation_error_text)) modelScope.launch { delay(SWAP_IN_PROGRESS_DELAY) @@ -1072,6 +1084,7 @@ internal class SwapModel @Inject constructor( when (swapTransactionState) { is SwapTransactionState.TxSent -> { if (fee == null) { + Timber.e("onSwapClick: onSuccess: fee is null after swap") showAlert(resourceReference(R.string.swapping_fee_estimation_error_text)) return@onSuccess } @@ -1408,16 +1421,16 @@ internal class SwapModel @Inject constructor( } modelScope.launch { updateFeePaidCryptoCurrencyFor(fromToken) + startLoadingQuotes( + fromToken = fromToken, + fromAccount = fromAccount, + toToken = toToken, + toAccount = toAccount, + amount = lastAmount.value, + reduceBalanceBy = lastReducedBalanceBy.value, + toProvidersList = findSwapProviders(fromToken, toToken), + ) } - startLoadingQuotes( - fromToken = fromToken, - fromAccount = fromAccount, - toToken = toToken, - toAccount = toAccount, - amount = lastAmount.value, - reduceBalanceBy = lastReducedBalanceBy.value, - toProvidersList = findSwapProviders(fromToken, toToken), - ) updateTokensState(tokens) } } @@ -2314,10 +2327,14 @@ internal class SwapModel @Inject constructor( private fun getSelectedFeeState(): TxFeeSealedState { val feeStateUM = feeSelectorRepository.state.value as? FeeSelectorUM.Content - ?: return TxFeeSealedState.Legacy( + + if (feeStateUM == null) { + Timber.e("getSelectedFeeState: FeeSelectorUM is not Content: $feeStateUM, returning Legacy state") + return TxFeeSealedState.Legacy( txFeeState = TxFeeState.Empty, selectedFee = dataState.selectedFee?.feeType ?: FeeType.NORMAL, ) + } val transactionFeeExtended = feeStateUM.feeExtraInfo.transactionFeeExtended return TxFeeSealedState.Component( @@ -2331,7 +2348,13 @@ internal class SwapModel @Inject constructor( } private fun getSelectedFee(): TxFee? { - val feeStateUM = feeSelectorRepository.state.value as? FeeSelectorUM.Content ?: return null + val feeStateUM = feeSelectorRepository.state.value as? FeeSelectorUM.Content + + if (feeStateUM == null) { + Timber.e("getSelectedFee: FeeSelectorUM is not Content: $feeStateUM, returning null") + return null + } + val transactionFeeExtended = feeStateUM.feeExtraInfo.transactionFeeExtended return TxFee.FeeComponent( @@ -2387,6 +2410,7 @@ internal class SwapModel @Inject constructor( if (newState is FeeSelectorUM.Error) { modelScope.launch { + Timber.e("onResult: FeeSelectorUM is Error, isHidden = true") forceUpdateState.emit(newState.copy(isHidden = true)) } return @@ -2401,6 +2425,8 @@ internal class SwapModel @Inject constructor( newState.feeExtraInfo.feeCryptoCurrencyStatus.currency is CryptoCurrency.Coin if (isFeeCurrencySameAsFromCurrency || isCoinFeeSelected) { + Timber.e("onResult: Fee currency is same as from currency or coin fee selected, reloading quotes") + // block swap button until fee is loaded uiState = uiState.copy( swapButton = uiState.swapButton.copy( @@ -2423,15 +2449,19 @@ internal class SwapModel @Inject constructor( } override suspend fun loadFee(): Either { + Timber.e("loadFee: Start loading fee") + val fromToken = dataState.fromCryptoCurrency ?: return Either.Left(GetFeeError.UnknownError) val toToken = dataState.toCryptoCurrency ?: return Either.Left(GetFeeError.UnknownError) val selectedProvider = dataStateStateFlow.first { it.selectedProvider != null }.selectedProvider!! if (dataState.lastLoadedSwapStates[selectedProvider] !is SwapState.QuotesLoadedState) { + Timber.e("loadFee: Quotes not loaded ${dataState.lastLoadedSwapStates[selectedProvider]}") return Either.Left(GetFeeError.UnknownError) } if (isPermissionNotificationShown()) { + Timber.e("loadFee: Permission notification is shown, cannot load fee") return Either.Left(GetFeeError.UnknownError) } @@ -2444,6 +2474,12 @@ internal class SwapModel @Inject constructor( amount = lastAmount.value, reduceBalanceBy = lastReducedBalanceBy.value, ) + .onLeft { + Timber.e("loadFee: Failed to load fee with error $it") + } + .onRight { + Timber.e("loadFee: Fee loaded successfully") + } } override fun choosingInProgress(updatedState: Boolean) {