From dfbec1dee4ab741b5bec45a902c1e68c64322e68 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 27 Mar 2026 18:10:09 +0500 Subject: [PATCH] Updated on 2026-08-14 --- .../impl/amount/model/SwapAmountQuoteUtils.kt | 6 +-- .../impl/amount/ui/SwapAmountBlockContent.kt | 2 +- .../feature/swap/domain/SwapInteractorImpl.kt | 8 ++-- .../swap/domain/models/ui/SwapState.kt | 4 ++ .../tangem/feature/swap/ui/StateBuilder.kt | 44 +++++++++---------- 5 files changed, 34 insertions(+), 30 deletions(-) diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountQuoteUtils.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountQuoteUtils.kt index 3301fe3f9d..0c883b505c 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountQuoteUtils.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountQuoteUtils.kt @@ -34,10 +34,10 @@ internal object SwapAmountQuoteUtils { secondaryFiatRateUSD: BigDecimal?, primaryCryptoCurrencyStatus: CryptoCurrencyStatus, secondaryCryptoCurrencyStatus: CryptoCurrencyStatus?, - ): PriceImpact { - if (quoteContent == null) return PriceImpact.Empty + ): PriceImpact? { + if (quoteContent == null) return null - val fromAmount = quoteContent.fromAmount ?: return PriceImpact.Empty + val fromAmount = quoteContent.fromAmount ?: return null val toAmount = quoteContent.toAmount val (fromRate, toRate) = if (swapDirection == SwapDirection.Direct) { diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/ui/SwapAmountBlockContent.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/ui/SwapAmountBlockContent.kt index 8ffffab5a9..6db639d48a 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/ui/SwapAmountBlockContent.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/ui/SwapAmountBlockContent.kt @@ -86,7 +86,7 @@ internal fun SwapAmountBlockContent( val quoteContent = amountUM.selectedQuote as? SwapQuoteUM.Content val isBestRate = quoteContent?.diffPercent is SwapQuoteUM.Content.DifferencePercent.Best SwapChooseProviderContent( - isBestRate = isBestRate && amountUM.priceImpact?.shouldShowWarning() == true, + isBestRate = isBestRate && amountUM.priceImpact?.shouldShowWarning() != true, isSingleProvider = quoteContent?.isSingleProvider == true, showBestRateAnimation = amountUM.isShowBestRateAnimation, expressProvider = amountUM.selectedQuote.provider, 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 2a22cca812..405c0aa43b 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 @@ -68,7 +68,6 @@ import com.tangem.feature.swap.domain.models.toStringWithRightOffset import com.tangem.feature.swap.domain.models.ui.* import com.tangem.lib.crypto.BlockchainUtils.SOLANA_TRANSACTION_SIZE_THRESHOLD_BYTES import com.tangem.utils.coroutines.runSuspendCatching -import com.tangem.utils.extensions.orZero import com.tangem.utils.logging.TangemLogger import dagger.assisted.Assisted import dagger.assisted.AssistedFactory @@ -2457,7 +2456,8 @@ internal class SwapInteractorImpl @AssistedInject constructor( if (fromQuoteStatus == null) return PriceImpact.Empty val fromTokenFiatValue = fromTokenAmount.multiply(fromQuoteStatus.fiatRate) - val toTokenFiatValue = toTokenAmount.multiply(toRate.orZero()) + val toTokenFiatValue = toRate?.let { toTokenAmount.multiply(toRate) } ?: return PriceImpact.Empty + val value = BigDecimal.ONE - toTokenFiatValue.divide(fromTokenFiatValue, 2, RoundingMode.HALF_UP) val fromAmountUSD = if (fromQuoteStatus.fiatRateUSD != BigDecimal.ZERO) { @@ -2467,7 +2467,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( } val amountSignificance = when { - fromAmountUSD < PRICE_IMPACT_AMOUNT_MIN_THRESHOLD -> PriceImpact.AmountSignificance.LOW + fromAmountUSD <= PRICE_IMPACT_AMOUNT_MIN_THRESHOLD -> PriceImpact.AmountSignificance.LOW fromAmountUSD > PRICE_IMPACT_AMOUNT_MAX_THRESHOLD -> PriceImpact.AmountSignificance.HIGH else -> PriceImpact.AmountSignificance.MEDIUM } @@ -2552,7 +2552,7 @@ internal class SwapInteractorImpl @AssistedInject constructor( companion object { private const val INCREASE_GAS_LIMIT_FOR_DEX = 112 // 12% private const val INCREASE_GAS_LIMIT_FOR_SEND = 105 // 5% - private val PRICE_IMPACT_AMOUNT_MIN_THRESHOLD = 50.toBigDecimal() // in USD + private val PRICE_IMPACT_AMOUNT_MIN_THRESHOLD = 25.toBigDecimal() // in USD private val PRICE_IMPACT_AMOUNT_MAX_THRESHOLD = 5000.toBigDecimal() // in USD private val PRICE_IMPACT_LOW_THRESHOLD = 0.1.toBigDecimal() // 10% private val PRICE_IMPACT_HIGH_THRESHOLD = 0.5.toBigDecimal() // 50% diff --git a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt index fa1c9bdf73..a630100e2e 100644 --- a/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt +++ b/features/swap/domain/src/main/java/com/tangem/feature/swap/domain/models/ui/SwapState.kt @@ -66,6 +66,10 @@ data class PriceImpact( return type == Type.HIGH && amountSignificance == AmountSignificance.HIGH } + fun shouldShowWarning(): Boolean { + return type.ordinal > Type.LOW.ordinal || amountSignificance.ordinal > AmountSignificance.LOW.ordinal + } + companion object { val Empty = PriceImpact( value = BigDecimal.ZERO, diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index 6ba8b6a6e4..b6613eba32 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -387,26 +387,26 @@ internal class StateBuilder( .formatToUIRepresentation() .appendApproximateSign(), ), - amountEquivalent = combinedReference( - getFormattedFiatAmount(quoteModel.toTokenInfo.amountFiat), - stringReference(StringsSigns.WHITE_SPACE), - styledStringReference( - priceImpact.value.format { - percent(withoutSign = false) - }, - spanStyleReference = { - SpanStyle( - color = when (priceImpact.type) { - PriceImpact.Type.HIGH -> TangemTheme.colors.text.warning - PriceImpact.Type.MEDIUM -> TangemTheme.colors.text.attention - PriceImpact.Type.LOW, - PriceImpact.Type.NONE, - -> TangemTheme.colors.text.tertiary - }, - ) - }, - ), - ), + amountEquivalent = if (priceImpact.type.ordinal > PriceImpact.Type.LOW.ordinal) { + combinedReference( + getFormattedFiatAmount(quoteModel.toTokenInfo.amountFiat), + stringReference(StringsSigns.WHITE_SPACE), + styledStringReference( + value = "(${StringsSigns.MINUS}${priceImpact.value.format { percent() }})", + spanStyleReference = { + SpanStyle( + color = when (priceImpact.type) { + PriceImpact.Type.HIGH -> TangemTheme.colors.text.warning + PriceImpact.Type.MEDIUM -> TangemTheme.colors.text.attention + else -> TangemTheme.colors.text.tertiary + }, + ) + }, + ), + ) + } else { + getFormattedFiatAmount(quoteModel.toTokenInfo.amountFiat) + }, token = toCurrencyStatus, tokenIconUrl = uiStateHolder.receiveCardData.tokenIconUrl, coinId = toCurrencyStatus.currency.network.backendId, @@ -436,7 +436,7 @@ internal class StateBuilder( ), changeCardsButtonState = getChangeCardsButtonState(isReverseSwapPossible), providerState = swapProvider.convertToContentClickableProviderState( - isBestRate = bestRatedProviderId == swapProvider.providerId, + isBestRate = bestRatedProviderId == swapProvider.providerId && !priceImpact.shouldShowWarning(), fromTokenInfo = quoteModel.fromTokenInfo, toTokenInfo = quoteModel.toTokenInfo, isNeedBestRateBadge = isNeedBestRateBadge, @@ -444,7 +444,7 @@ internal class StateBuilder( onProviderClick = actions.onProviderClick, needApplyFCARestrictions = needApplyFCARestrictions, ), - priceImpact = quoteModel.priceImpact, + priceImpact = priceImpact, tosState = createTosState(swapProvider), shouldShowMaxAmount = shouldShowMaxAmount(fromToken, toCurrencyStatus.currency), )