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 839bc9a964..f3e444ddbb 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 @@ -185,6 +185,7 @@ internal class SwapModel @Inject constructor( appCurrencyProvider = Provider(selectedAppCurrencyFlow::value), isAccountsModeProvider = Provider { isAccountsMode }, iGaslessFeeSupportedForNetwork = iGaslessFeeSupportedForNetwork, + appRouter = appRouter, ) private val inputNumberFormatter = InputNumberFormatter( @@ -1499,16 +1500,6 @@ internal class SwapModel @Inject constructor( ) } }, - onBuyClick = { - val fromSwapCurrencyStatus = dataState.fromSwapCurrencyStatus ?: return@UiActions - val feePaidCryptoCurrency = dataState.feePaidCryptoCurrency ?: return@UiActions - val route = AppRoute.CurrencyDetails( - userWalletId = fromSwapCurrencyStatus.userWalletId, - currency = feePaidCryptoCurrency.currency, - ) - - appRouter.push(route) - }, onRetryClick = { startLoadingQuotesFromLastState() }, diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt index 6f203e2e72..f4199313f4 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapNotificationsFactory.kt @@ -1,5 +1,7 @@ package com.tangem.feature.swap.model +import com.tangem.common.routing.AppRoute +import com.tangem.common.routing.AppRouter import com.tangem.common.ui.notifications.NotificationUM import com.tangem.common.ui.notifications.NotificationsFactory.addDustWarningNotification import com.tangem.common.ui.notifications.NotificationsFactory.addExistentialWarningNotification @@ -106,6 +108,7 @@ internal class SwapNotificationsFactory( selectedFeeType: FeeType, providerName: String, hideFee: Boolean, + appRouter: AppRouter, ): ImmutableList { val warnings = buildList { maybeAddRentExemptionError(quoteModel) @@ -113,7 +116,12 @@ internal class SwapNotificationsFactory( maybeAddNeedReserveToCreateAccountWarning(quoteModel) maybeAddPermissionNeededWarning(quoteModel, providerName) maybeAddNetworkFeeCoverageWarning(quoteModel, selectedFeeType) - maybeAddUnableCoverFeeWarning(quoteModel, feeCryptoCurrencyStatus, hideFee) + maybeAddUnableCoverFeeWarning( + quoteModel = quoteModel, + feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, + hideFee = hideFee, + appRouter = appRouter, + ) maybeAddTransactionInProgressWarning(quoteModel) maybeAddPriceImpactNotification(quoteModel.priceImpact) } @@ -299,17 +307,20 @@ internal class SwapNotificationsFactory( } } + @Suppress("CyclomaticComplexMethod") private fun MutableList.maybeAddUnableCoverFeeWarning( quoteModel: SwapState.QuotesLoadedState, feeCryptoCurrencyStatus: CryptoCurrencyStatus?, hideFee: Boolean, + appRouter: AppRouter, ) { - if (hideFee) return - val fromCurrency = quoteModel.fromTokenInfo.swapCurrencyStatus.currency + if (hideFee || feeCryptoCurrencyStatus == null) return + val fromSwapCurrency = quoteModel.fromTokenInfo.swapCurrencyStatus + val fromCurrency = fromSwapCurrency.currency val feeEnoughState = quoteModel.preparedSwapConfigState.feeState as? SwapFeeState.NotEnough val shouldShowCoverWarning = !quoteModel.preparedSwapConfigState.isBalanceEnough && quoteModel.permissionState !is PermissionDataState.PermissionLoading && - feeCryptoCurrencyStatus?.currency != fromCurrency + feeCryptoCurrencyStatus.currency != fromCurrency val isCEXProvider = quoteModel.swapProvider.type == ExchangeProviderType.CEX @@ -320,13 +331,25 @@ internal class SwapNotificationsFactory( if (shouldShowCoverWarning && !isGaslessAvailable || isNotEnoughFee) { add( - SwapNotificationUM.Error.UnableToCoverFeeWarning( - fromToken = fromCurrency, - feeCurrency = feeCryptoCurrencyStatus?.currency, - currencyName = feeEnoughState?.currencyName ?: fromCurrency.network.name, - currencySymbol = feeEnoughState?.currencySymbol ?: fromCurrency.network.currencySymbol, - onConfirmClick = actions.onBuyClick, - ), + if (fromCurrency.id == feeCryptoCurrencyStatus.currency.id) { + SwapNotificationUM.Error.InsufficientFunds + } else { + val route = AppRoute.CurrencyDetails( + userWalletId = fromSwapCurrency.userWalletId, + currency = feeCryptoCurrencyStatus.currency, + ) + SwapNotificationUM.Error.UnableToCoverFeeWarning( + fromToken = fromCurrency, + feeCurrency = feeCryptoCurrencyStatus.currency, + currencyName = feeEnoughState?.currencyName ?: fromCurrency.network.name, + currencySymbol = feeEnoughState?.currencySymbol ?: fromCurrency.network.currencySymbol, + onConfirmClick = if (!appRouter.stack.contains(route)) { + { appRouter.push(route) } + } else { + null + }, + ) + }, ) } } diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/UiActions.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/models/UiActions.kt index ac922cd6f9..73cb3aa224 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/UiActions.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/models/UiActions.kt @@ -20,7 +20,6 @@ internal data class UiActions( val onSelectFeeType: (TxFee.Legacy) -> Unit, val onProviderClick: (String) -> Unit, val onProviderSelect: (String) -> Unit, - val onBuyClick: () -> Unit, val onSelectTokenClick: (TokenSelectionDirection) -> Unit, val onSuccess: () -> Unit, val onLinkClick: (String) -> Unit, diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/SwapNotificationUM.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/SwapNotificationUM.kt index 1cb665edc9..476edcbc27 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/SwapNotificationUM.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/models/states/SwapNotificationUM.kt @@ -55,12 +55,17 @@ internal object SwapNotificationUM { ), ) + data object InsufficientFunds : Error( + title = resourceReference(R.string.swapping_insufficient_funds), + subtitle = resourceReference(R.string.swapping_insufficient_funds_description), + ) + data class UnableToCoverFeeWarning( val fromToken: CryptoCurrency, val currencyName: String, val currencySymbol: String, - val feeCurrency: CryptoCurrency?, - val onConfirmClick: () -> Unit, + val feeCurrency: CryptoCurrency, + val onConfirmClick: (() -> Unit)?, ) : Error( title = resourceReference( R.string.warning_express_not_enough_fee_for_token_tx_title, @@ -71,7 +76,7 @@ internal object SwapNotificationUM { wrappedList(currencyName, currencySymbol), ), iconResId = fromToken.networkIconResId, - buttonState = feeCurrency?.let { + buttonState = onConfirmClick?.let { NotificationConfig.ButtonsState.SecondaryButtonConfig( text = resourceReference(R.string.common_buy_currency, wrappedList(currencySymbol)), onClick = onConfirmClick, 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 deb2acdde2..e1b77b1fc2 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 @@ -3,6 +3,7 @@ package com.tangem.feature.swap.ui import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue +import com.tangem.common.routing.AppRouter import com.tangem.common.ui.account.AccountIconUM import com.tangem.common.ui.account.AccountTitleUM import com.tangem.common.ui.account.CryptoPortfolioIconConverter @@ -58,6 +59,7 @@ internal class StateBuilder( private val appCurrencyProvider: Provider, private val isAccountsModeProvider: Provider, private val iGaslessFeeSupportedForNetwork: IsGaslessFeeSupportedForNetwork, + private val appRouter: AppRouter, ) { private val iconStateConverter by lazy(::CryptoCurrencyToIconStateConverter) @@ -463,6 +465,7 @@ internal class StateBuilder( selectedFeeType = selectedFeeType, providerName = swapProvider.name, hideFee = hideFee, + appRouter = appRouter, ) val fromAccountTitleUM = when { diff --git a/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderInitialStateTest.kt b/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderInitialStateTest.kt index e8724ad601..c59fbb8255 100644 --- a/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderInitialStateTest.kt +++ b/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderInitialStateTest.kt @@ -1,6 +1,7 @@ package com.tangem.feature.swap import com.google.common.truth.Truth.assertThat +import com.tangem.common.routing.AppRouter import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.express.models.ExpressError import com.tangem.domain.models.account.Account @@ -31,6 +32,7 @@ internal class StateBuilderInitialStateTest { private val appCurrencyProvider: Provider = mockk() private val isAccountsModeProvider: Provider = mockk() private val iGaslessFeeSupportedForNetwork: IsGaslessFeeSupportedForNetwork = mockk() + private val appRouter: AppRouter = mockk() private lateinit var sut: StateBuilder @@ -48,6 +50,7 @@ internal class StateBuilderInitialStateTest { appCurrencyProvider = appCurrencyProvider, isAccountsModeProvider = isAccountsModeProvider, iGaslessFeeSupportedForNetwork = iGaslessFeeSupportedForNetwork, + appRouter = appRouter ) } diff --git a/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderPairsTest.kt b/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderPairsTest.kt index c1f52f0e5d..6a4bd0b2e2 100644 --- a/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderPairsTest.kt +++ b/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderPairsTest.kt @@ -1,6 +1,7 @@ package com.tangem.feature.swap import com.google.common.truth.Truth.assertThat +import com.tangem.common.routing.AppRouter import com.tangem.core.ui.extensions.stringReference import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.wallet.UserWallet @@ -26,6 +27,7 @@ internal class StateBuilderPairsTest { private val appCurrencyProvider: Provider = mockk() private val isAccountsModeProvider: Provider = mockk() private val iGaslessFeeSupportedForNetwork: IsGaslessFeeSupportedForNetwork = mockk() + private val appRouter: AppRouter = mockk() private lateinit var sut: StateBuilder @@ -53,6 +55,7 @@ internal class StateBuilderPairsTest { appCurrencyProvider = appCurrencyProvider, isAccountsModeProvider = isAccountsModeProvider, iGaslessFeeSupportedForNetwork = iGaslessFeeSupportedForNetwork, + appRouter = appRouter, ) } diff --git a/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderQuotesTest.kt b/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderQuotesTest.kt index e335298820..fcc7fa39b6 100644 --- a/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderQuotesTest.kt +++ b/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderQuotesTest.kt @@ -1,8 +1,8 @@ package com.tangem.feature.swap import com.google.common.truth.Truth.assertThat +import com.tangem.common.routing.AppRouter import com.tangem.domain.appcurrency.model.AppCurrency -import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.swap.models.SwapCurrencyStatus @@ -14,12 +14,10 @@ import com.tangem.feature.swap.domain.models.ui.* import com.tangem.feature.swap.models.* import com.tangem.feature.swap.models.states.FeeItemState import com.tangem.feature.swap.models.states.ProviderState -import com.tangem.feature.swap.models.states.SwapNotificationUM import com.tangem.feature.swap.ui.StateBuilder import com.tangem.utils.Provider import io.mockk.every import io.mockk.mockk -import kotlinx.collections.immutable.persistentListOf import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test @@ -32,6 +30,7 @@ internal class StateBuilderQuotesTest { private val appCurrencyProvider: Provider = mockk() private val isAccountsModeProvider: Provider = mockk() private val iGaslessFeeSupportedForNetwork: IsGaslessFeeSupportedForNetwork = mockk() + private val appRouter: AppRouter = mockk() private lateinit var sut: StateBuilder @@ -60,6 +59,7 @@ internal class StateBuilderQuotesTest { appCurrencyProvider = appCurrencyProvider, isAccountsModeProvider = isAccountsModeProvider, iGaslessFeeSupportedForNetwork = iGaslessFeeSupportedForNetwork, + appRouter = appRouter, ) } diff --git a/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderSwapDataTest.kt b/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderSwapDataTest.kt index ed55977ec8..fb7636352b 100644 --- a/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderSwapDataTest.kt +++ b/features/swap/impl/src/test/java/com/tangem/feature/swap/StateBuilderSwapDataTest.kt @@ -1,16 +1,15 @@ package com.tangem.feature.swap import com.google.common.truth.Truth.assertThat +import com.tangem.common.routing.AppRouter import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId -import com.tangem.domain.swap.models.SwapCurrencyStatus import com.tangem.domain.transaction.usecase.gasless.IsGaslessFeeSupportedForNetwork import com.tangem.feature.swap.domain.models.domain.* import com.tangem.feature.swap.domain.models.ui.* import com.tangem.feature.swap.model.SwapProcessDataState import com.tangem.feature.swap.models.* -import com.tangem.feature.swap.models.states.FeeItemState import com.tangem.feature.swap.models.states.ProviderState import com.tangem.feature.swap.models.states.SwapNotificationUM import com.tangem.feature.swap.ui.StateBuilder @@ -31,6 +30,7 @@ internal class StateBuilderSwapDataTest { private val appCurrencyProvider: Provider = mockk() private val isAccountsModeProvider: Provider = mockk() private val iGaslessFeeSupportedForNetwork: IsGaslessFeeSupportedForNetwork = mockk() + private val appRouter: AppRouter = mockk() private lateinit var sut: StateBuilder @@ -59,6 +59,7 @@ internal class StateBuilderSwapDataTest { appCurrencyProvider = appCurrencyProvider, isAccountsModeProvider = isAccountsModeProvider, iGaslessFeeSupportedForNetwork = iGaslessFeeSupportedForNetwork, + appRouter = appRouter, ) }