From 54094ffa2f5050929ea0f4a318cc500372356839 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 27 Aug 2025 16:17:25 +0500 Subject: [PATCH 1/4] Updated on 2026-08-14 --- .../swap/v2/impl/amount/model/SwapAmountModel.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt index 3c4c055991..cce6ac9985 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt @@ -105,10 +105,10 @@ internal class SwapAmountModel @Inject constructor( private var secondaryMaximumAmountBoundary: EnterAmountBoundary? = null private var secondaryMinimumAmountBoundary: EnterAmountBoundary? = null - var userCountry: UserCountry = UserCountry.Other(Locale.getDefault().country) + private var userCountry: UserCountry = UserCountry.Other(Locale.getDefault().country) val bottomSheetNavigation: SlotNavigation = SlotNavigation() - var showBestRateAnimation: Boolean = false + private var showBestRateAnimation: Boolean = false val uiState: StateFlow field = MutableStateFlow(params.amountUM) @@ -134,7 +134,10 @@ internal class SwapAmountModel @Inject constructor( } fun onStart() { - startLoadingQuotesTask(isSilentReload = false) + quoteTaskScheduler.scheduleTask( + scope = modelScope, + task = loadQuotesTask(), + ) } fun onStop() { From 5e17abbf91460d8566d2659bd2c991fbf79eefbc Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 27 Aug 2025 16:18:02 +0500 Subject: [PATCH 2/4] Updated on 2026-08-14 --- .../v2/impl/amount/model/SwapAmountModel.kt | 12 ++--- .../SwapAmountSetQuotesTransformer.kt | 6 ++- .../SwapAmountValueChangeTransformer.kt | 1 + .../SwapAmountValueMaxTransformer.kt | 49 ++++++++++--------- 4 files changed, 36 insertions(+), 32 deletions(-) diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt index cce6ac9985..616b5a1166 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/SwapAmountModel.kt @@ -536,18 +536,17 @@ internal class SwapAmountModel @Inject constructor( } as? AmountState.Data val fromAmountValue = fromAmount?.amountTextField?.cryptoAmount?.value.orZero() - - if (fromAmount?.amountTextField?.isError == true || fromAmountValue.isNullOrZero()) { + val isAmountScreen = params is SwapAmountComponentParams.AmountParams + val isAmountError = fromAmount?.amountTextField?.isError == true || fromAmountValue.isNullOrZero() + if (isAmountScreen && isAmountError) { uiState.transformerUpdate(SwapQuoteEmptyStateTransformer) return } - val swapGroups = state.swapCurrencies.getGroupWithDirection(state.swapDirection) - - uiState.transformerUpdate(SwapQuoteLoadingStateTransformer) + if (!isSilentReload) { uiState.transformerUpdate(SwapQuoteLoadingStateTransformer) } modelScope.launch { - val quotes = swapGroups.available.filter { + val quotes = state.swapCurrencies.getGroupWithDirection(state.swapDirection).available.filter { it.currencyStatus.currency.id == toCryptoCurrency.id }.flatMap { it.providers @@ -594,7 +593,6 @@ internal class SwapAmountModel @Inject constructor( needApplyFcaRestrictions = userCountry.needApplyFCARestrictions(), ), ) - feeSelectorReloadTrigger.triggerUpdate() } } diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountSetQuotesTransformer.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountSetQuotesTransformer.kt index adfcc37a91..941fa7e8ec 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountSetQuotesTransformer.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountSetQuotesTransformer.kt @@ -34,8 +34,10 @@ internal class SwapAmountSetQuotesTransformer( val sortedQuotes = quotes.sortedWith(SwapQuotesComparator) val bestQuote = findBestQuote(quotes) ?: SwapQuoteUM.Empty + val quotesWithDiff = getQuotesWithDiff(sortedQuotes, bestQuote, isSingleProvider) val selectedQuote = if (isSilentReload && prevState.selectedQuote !is SwapQuoteUM.Loading) { - prevState.selectedQuote + quotesWithDiff.firstOrNull { it.provider?.providerId == prevState.selectedQuote.provider?.providerId } + ?: prevState.selectedQuote } else { (bestQuote as? SwapQuoteUM.Content)?.copy( diffPercent = DifferencePercent.Best, @@ -55,7 +57,7 @@ internal class SwapAmountSetQuotesTransformer( if (updatedState !is SwapAmountUM.Content) return prevState return updatedState.copy( - isPrimaryButtonEnabled = updatedState.isPrimaryButtonEnabled && quotes.isNotEmpty(), + isPrimaryButtonEnabled = updatedState.isPrimaryButtonEnabled && quotesWithDiff.isNotEmpty(), swapQuotes = getQuotesWithDiff(sortedQuotes, bestQuote, isSingleProvider), ) } diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountValueChangeTransformer.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountValueChangeTransformer.kt index c364fd36a0..639f994b78 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountValueChangeTransformer.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountValueChangeTransformer.kt @@ -45,6 +45,7 @@ internal class SwapAmountValueChangeTransformer( ) return (updatedState as? SwapAmountUM.Content)?.copy( + isPrimaryButtonEnabled = false, selectedQuote = if (updatedState.isPrimaryButtonEnabled) { SwapQuoteUM.Empty } else { diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountValueMaxTransformer.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountValueMaxTransformer.kt index 59c38f1c94..abc50a6e78 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountValueMaxTransformer.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/amount/model/transformers/SwapAmountValueMaxTransformer.kt @@ -16,31 +16,34 @@ internal class SwapAmountValueMaxTransformer( override fun transform(prevState: SwapAmountUM): SwapAmountUM { if (prevState !is SwapAmountUM.Content) return prevState - return prevState - .copy(selectedQuote = SwapQuoteUM.Loading) - .updateAmount( - onPrimaryAmount = { primaryStatus -> + val updatedState = prevState.updateAmount( + onPrimaryAmount = { primaryStatus -> + copy( + amountField = AmountFieldSetMaxAmountTransformer( + cryptoCurrencyStatus = primaryStatus, + maxAmount = primaryMaximumAmountBoundary, + minAmount = primaryMinimumAmountBoundary, + ).transform(prevState.primaryAmount.amountField), + ) + }, + onSecondaryAmount = { secondaryStatus -> + if (secondaryMaximumAmountBoundary != null) { copy( amountField = AmountFieldSetMaxAmountTransformer( - cryptoCurrencyStatus = primaryStatus, - maxAmount = primaryMaximumAmountBoundary, - minAmount = primaryMinimumAmountBoundary, - ).transform(prevState.primaryAmount.amountField), + cryptoCurrencyStatus = secondaryStatus, + maxAmount = secondaryMaximumAmountBoundary, + minAmount = secondaryMinimumAmountBoundary, + ).transform(prevState.secondaryAmount.amountField), ) - }, - onSecondaryAmount = { secondaryStatus -> - if (secondaryMaximumAmountBoundary != null) { - copy( - amountField = AmountFieldSetMaxAmountTransformer( - cryptoCurrencyStatus = secondaryStatus, - maxAmount = secondaryMaximumAmountBoundary, - minAmount = secondaryMinimumAmountBoundary, - ).transform(prevState.secondaryAmount.amountField), - ) - } else { - this - } - }, - ) + } else { + this + } + }, + ) + + return (updatedState as? SwapAmountUM.Content)?.copy( + isPrimaryButtonEnabled = false, + selectedQuote = SwapQuoteUM.Loading, + ) ?: updatedState } } \ No newline at end of file From cf705ab04e4fe6af056149bbfb2690bc6f173498 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 27 Aug 2025 16:18:15 +0500 Subject: [PATCH 3/4] Updated on 2026-08-14 --- .../model/converter/SwapProviderStateConverter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/model/converter/SwapProviderStateConverter.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/model/converter/SwapProviderStateConverter.kt index 4a7a127735..317f0d733f 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/model/converter/SwapProviderStateConverter.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/chooseprovider/model/converter/SwapProviderStateConverter.kt @@ -42,7 +42,7 @@ internal class SwapProviderStateConverter( val additionalBadge = when { needApplyFCARestrictions && provider.isRestrictedByFCA() -> AdditionalBadge.FCAWarningList - isNeedBestRateBadge && isBestRate && !needApplyFCARestrictions -> AdditionalBadge.BestTrade + isNeedBestRateBadge && isBestRate -> AdditionalBadge.BestTrade else -> AdditionalBadge.Empty } From 99532083092af11974f209724d031fedb9edcea1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 27 Aug 2025 16:18:20 +0500 Subject: [PATCH 4/4] Updated on 2026-08-14 --- .../v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt | 6 ++++-- .../sendviaswap/analytics/SendWithSwapAnalyticEvents.kt | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt index bc241e0ec0..712782f490 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt @@ -94,13 +94,15 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor( ) activeComponent.updateState(model.uiState.value.destinationUM) } - is SendWithSwapConfirmComponent -> if (model.currentRoute.value.isEditMode) { + is SendWithSwapConfirmComponent -> { analyticsEventHandler.send( CommonSendAnalyticEvents.ConfirmationScreenOpened( categoryName = model.analyticCategoryName, ), ) - activeComponent.updateState(model.uiState.value) + if (model.currentRoute.value.isEditMode) { + activeComponent.updateState(model.uiState.value) + } } } model.currentRoute.emit(stack.active.configuration) diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/analytics/SendWithSwapAnalyticEvents.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/analytics/SendWithSwapAnalyticEvents.kt index ad1927f7cd..6daa91c3d8 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/analytics/SendWithSwapAnalyticEvents.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/analytics/SendWithSwapAnalyticEvents.kt @@ -2,6 +2,7 @@ package com.tangem.features.swap.v2.impl.sendviaswap.analytics import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.analytics.models.AnalyticsParam.Key.FEE_TYPE import com.tangem.core.analytics.models.AnalyticsParam.Key.PROVIDER import com.tangem.core.analytics.models.AnalyticsParam.Key.RECEIVE_BLOCKCHAIN import com.tangem.core.analytics.models.AnalyticsParam.Key.RECEIVE_TOKEN @@ -24,7 +25,7 @@ internal sealed class SendWithSwapAnalyticEvents( event = "Send With Swap In Progress Screen Opened", params = mapOf( PROVIDER to providerName, - "Commission" to if (feeType is AnalyticsParam.FeeType.Normal) "Market" else "Fast", + FEE_TYPE to if (feeType is AnalyticsParam.FeeType.Normal) "Market" else "Fast", SEND_TOKEN to fromToken.symbol, RECEIVE_TOKEN to toToken.symbol, SEND_BLOCKCHAIN to fromToken.network.name,