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 f50380fc4b..71fd844cf0 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 @@ -842,7 +842,8 @@ internal class SwapModel @Inject constructor( fromTokenAmount: String, ) { val feePaidCryptoCurrency = dataState.feePaidCryptoCurrency - val selectedFee = getSelectedSwapFee()?.fee + val selectedSwapFee = getSelectedSwapFee() + val selectedFee = selectedSwapFee?.fee val swapState = swapTransferInteractor.updateTransfer( fromSwapCurrencyStatus = fromSwapCurrencyStatus, toSwapCurrencyStatus = toSwapCurrencyStatus, @@ -864,6 +865,7 @@ internal class SwapModel @Inject constructor( uiStateHolder = uiState, feePaidCryptoCurrencyStatus = feePaidCryptoCurrency, feeSelectorUM = feeSelectorRepository.state.value, + isHighNetworkFee = isHighNetworkFee(selectedSwapFee), ) when { uiState.successState != null -> Unit @@ -912,6 +914,7 @@ internal class SwapModel @Inject constructor( fee = fee, isTangemPayWithdrawal = isTangemPayWithdrawal(), feeSelectorUM = feeSelectorRepository.state.value, + isHighNetworkFee = isHighNetworkFee(getSelectedSwapFee()), ) } } diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/transfer/SwapTransferNotificationsFactory.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/transfer/SwapTransferNotificationsFactory.kt index 7166f53e31..1e1a502233 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/transfer/SwapTransferNotificationsFactory.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/transfer/SwapTransferNotificationsFactory.kt @@ -40,6 +40,7 @@ internal class SwapTransferNotificationsFactory @Inject constructor() { feeSelectorUM: FeeSelectorUM?, feeCryptoCurrencyStatus: CryptoCurrencyStatus?, actions: UiActions, + isHighNetworkFee: Boolean = false, ): ImmutableList { // The fee selector exposes a single sealed state; narrow it here so call sites pass the raw // FeeSelectorUM and this factory owns the Content/Error/Loading discrimination. @@ -71,9 +72,16 @@ internal class SwapTransferNotificationsFactory @Inject constructor() { feeError = getFeeError, actions = actions, ) + maybeAddHighNetworkFeeWarning(isHighNetworkFee) }.toPersistentList() } + private fun MutableList.maybeAddHighNetworkFeeWarning(isHighNetworkFee: Boolean) { + if (isHighNetworkFee) { + add(NotificationUM.Warning.HighNetworkFee) + } + } + private fun MutableList.maybeAddDomainWarnings( state: SwapState.Transfer, feeCryptoCurrencyStatus: CryptoCurrencyStatus?, diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/transfer/SwapTransferStateBuilder.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/transfer/SwapTransferStateBuilder.kt index 720be1f88f..bf6e039048 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/transfer/SwapTransferStateBuilder.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/ui/transfer/SwapTransferStateBuilder.kt @@ -60,6 +60,7 @@ internal class SwapTransferStateBuilder @Inject constructor( uiStateHolder: SwapStateHolder, feePaidCryptoCurrencyStatus: CryptoCurrencyStatus?, feeSelectorUM: FeeSelectorUM?, + isHighNetworkFee: Boolean = false, ): SwapStateHolder { val fromTokenSwapInfo = transferState.fromTokenInfo val isInsufficientBalance = transferState.isInsufficientBalance @@ -70,6 +71,7 @@ internal class SwapTransferStateBuilder @Inject constructor( feeSelectorUM = feeSelectorUM, feeCryptoCurrencyStatus = feePaidCryptoCurrencyStatus, actions = actions, + isHighNetworkFee = isHighNetworkFee, ) return uiStateHolder.copy( sendCardData = createSendSwapCardState( @@ -343,12 +345,14 @@ internal class SwapTransferStateBuilder @Inject constructor( fee: Fee?, isTangemPayWithdrawal: Boolean, feeSelectorUM: FeeSelectorUM?, + isHighNetworkFee: Boolean = false, ): SwapStateHolder { val notifications = notificationsFactory.getNotifications( transferState = transferState, feeCryptoCurrencyStatus = feePaidCryptoCurrencyStatus, feeSelectorUM = feeSelectorUM, actions = actions, + isHighNetworkFee = isHighNetworkFee, ) return uiStateHolder.copy( notifications = notifications, diff --git a/features/swap/impl/src/test/java/com/tangem/feature/swap/ui/transfer/SwapTransferNotificationsFactoryTest.kt b/features/swap/impl/src/test/java/com/tangem/feature/swap/ui/transfer/SwapTransferNotificationsFactoryTest.kt index 61eb7d7ac8..c9657eb252 100644 --- a/features/swap/impl/src/test/java/com/tangem/feature/swap/ui/transfer/SwapTransferNotificationsFactoryTest.kt +++ b/features/swap/impl/src/test/java/com/tangem/feature/swap/ui/transfer/SwapTransferNotificationsFactoryTest.kt @@ -56,6 +56,42 @@ internal class SwapTransferNotificationsFactoryTest { assertThat(result).isEmpty() } + @Test + fun `GIVEN isHighNetworkFee true WHEN getNotifications THEN HighNetworkFee warning is added`() = runTest { + // Arrange + val transferState = buildTransferState() + + // Act + val result = sut.getNotifications( + transferState = transferState, + feeSelectorUM = null, + feeCryptoCurrencyStatus = null, + actions = actions, + isHighNetworkFee = true, + ) + + // Assert + assertThat(result).contains(NotificationUM.Warning.HighNetworkFee) + } + + @Test + fun `GIVEN isHighNetworkFee false WHEN getNotifications THEN HighNetworkFee warning is absent`() = runTest { + // Arrange + val transferState = buildTransferState() + + // Act + val result = sut.getNotifications( + transferState = transferState, + feeSelectorUM = null, + feeCryptoCurrencyStatus = null, + actions = actions, + isHighNetworkFee = false, + ) + + // Assert + assertThat(result).doesNotContain(NotificationUM.Warning.HighNetworkFee) + } + @Test fun `GIVEN currencyCheck with rentWarning WHEN getNotifications THEN Solana RentInfo is added`() = runTest { val rentWarning = CryptoCurrencyWarning.Rent( diff --git a/features/swap/impl/src/test/java/com/tangem/feature/swap/ui/transfer/SwapTransferStateBuilderTest.kt b/features/swap/impl/src/test/java/com/tangem/feature/swap/ui/transfer/SwapTransferStateBuilderTest.kt index 930fa03b39..91c9a098e5 100644 --- a/features/swap/impl/src/test/java/com/tangem/feature/swap/ui/transfer/SwapTransferStateBuilderTest.kt +++ b/features/swap/impl/src/test/java/com/tangem/feature/swap/ui/transfer/SwapTransferStateBuilderTest.kt @@ -13,6 +13,7 @@ import com.tangem.common.ui.account.toUM import com.tangem.common.ui.amountScreen.models.AmountFieldModel import com.tangem.common.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter import com.tangem.common.ui.navigationButtons.NavigationUM +import com.tangem.common.ui.notifications.NotificationUM import com.tangem.common.ui.userwallet.ext.walletInterationIcon import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.resourceReference @@ -376,6 +377,76 @@ internal class SwapTransferStateBuilderTest { } } + @Test + fun `GIVEN high network fee WHEN createTransferState THEN flag is forwarded to notifications factory`() = + runTest { + // Arrange + val transferState = buildTransferState( + fromAmount = BigDecimal("1.5"), + toAmount = BigDecimal("1.5"), + isAccountsMode = false, + ) + + // Act + sut.createTransferState( + actions = actions, + transferState = transferState, + uiStateHolder = baseStateHolder(), + feePaidCryptoCurrencyStatus = null, + feeSelectorUM = null, + isHighNetworkFee = true, + ) + + // Assert + coVerify(exactly = 1) { + notificationsFactory.getNotifications( + transferState = transferState, + feeSelectorUM = any(), + feeCryptoCurrencyStatus = null, + actions = any(), + isHighNetworkFee = true, + ) + } + } + + @Test + fun `GIVEN high network fee warning WHEN updateTransferButtonEnableState THEN swap button stays enabled`() = + runTest { + // Arrange + val transferState = buildTransferState( + fromAmount = BigDecimal("1"), + toAmount = BigDecimal("1"), + isAccountsMode = false, + ) + val fee: Fee = mockk(relaxed = true) + coEvery { + notificationsFactory.getNotifications( + transferState = transferState, + feeSelectorUM = any(), + feeCryptoCurrencyStatus = null, + actions = any(), + isHighNetworkFee = true, + ) + } returns persistentListOf(NotificationUM.Warning.HighNetworkFee) + + // Act + val result = sut.updateTransferButtonEnableState( + dataState = SwapProcessDataState(), + transferState = transferState, + actions = actions, + uiStateHolder = baseStateHolder(), + feePaidCryptoCurrencyStatus = null, + fee = fee, + isTangemPayWithdrawal = false, + feeSelectorUM = null, + isHighNetworkFee = true, + ) + + // Assert + assertThat(result.notifications).contains(NotificationUM.Warning.HighNetworkFee) + assertThat(result.swapButton.isEnabled).isTrue() + } + @Test fun `GIVEN fee coverage reduces amount WHEN createTransferState THEN receive card shows reduced sendingAmount`() = runTest {