From b2291e9864fac09716609ed7a853a8e6036a0ed0 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 16 Nov 2023 15:50:21 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tokens/GetCryptoCurrencyStatusUseCase.kt | 1 + .../tangem/feature/swap/SwapRepositoryImpl.kt | 5 -- .../feature/swap/domain/SwapInteractorImpl.kt | 1 + .../feature/swap/models/SwapStateHolder.kt | 6 ++- .../tangem/feature/swap/ui/StateBuilder.kt | 35 +++++++++++- .../feature/swap/ui/SwapScreenContent.kt | 53 ++++++++++--------- .../feature/swap/viewmodels/SwapViewModel.kt | 3 +- 7 files changed, 69 insertions(+), 35 deletions(-) diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyStatusUseCase.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyStatusUseCase.kt index 51029ebe6e..d917a747c7 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyStatusUseCase.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/GetCryptoCurrencyStatusUseCase.kt @@ -35,6 +35,7 @@ class GetCryptoCurrencyStatusUseCase( } } + @Suppress("UnusedPrivateMember") private fun createTokenList( userWalletId: UserWalletId, tokens: List, diff --git a/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt b/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt index 35cb083d21..ce4a54b96e 100644 --- a/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt +++ b/features/swap/data/src/main/java/com/tangem/feature/swap/SwapRepositoryImpl.kt @@ -5,7 +5,6 @@ import com.tangem.blockchain.common.Approver import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.Token import com.tangem.blockchain.extensions.Result -import com.tangem.data.tokens.utils.CryptoCurrencyFactory import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.express.TangemExpressApi import com.tangem.datasource.api.express.models.request.PairsRequestBody @@ -16,11 +15,8 @@ import com.tangem.datasource.api.oneinch.errors.OneIncResponseException import com.tangem.datasource.api.tangemTech.TangemTechApi import com.tangem.datasource.config.ConfigManager import com.tangem.domain.common.extensions.fromNetworkId -import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.tokens.model.CryptoCurrency -import com.tangem.domain.tokens.model.Network import com.tangem.domain.walletmanager.WalletManagersFacade -import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.models.UserWalletId import com.tangem.feature.swap.converters.* import com.tangem.feature.swap.domain.SwapRepository @@ -32,7 +28,6 @@ import kotlinx.coroutines.async import kotlinx.coroutines.withContext import java.math.BigDecimal import javax.inject.Inject -import com.tangem.blockchain.common.Token as SdkToken import com.tangem.datasource.api.express.models.request.LeastTokenInfo as NetworkLeastTokenInfo @Suppress("LongParameterList") 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 1381d354c9..ada40cc077 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 @@ -453,6 +453,7 @@ internal class SwapInteractorImpl @Inject constructor( return toToken } + @Suppress("UnusedPrivateMember") @Deprecated("used in old swap mechanism") private fun getTokensWithBalance( tokens: List, diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt index 31688a00c0..ace9ee54d5 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/models/SwapStateHolder.kt @@ -1,6 +1,7 @@ package com.tangem.feature.swap.models import androidx.compose.ui.text.input.TextFieldValue +import com.tangem.core.ui.components.notifications.NotificationConfig import com.tangem.core.ui.components.states.Item import com.tangem.core.ui.components.states.SelectableItemsState import com.tangem.feature.swap.domain.models.ui.TxFee @@ -87,8 +88,9 @@ sealed interface TransactionCardType { } sealed interface SwapWarning { - data class PermissionNeeded(val tokenCurrency: String) : SwapWarning + data class PermissionNeeded(val notificationConfig: NotificationConfig) : SwapWarning object InsufficientFunds : SwapWarning + data class NoAvailableTokensToSwap(val notificationConfig: NotificationConfig) : SwapWarning data class GenericWarning( val message: String? = null, val type: GenericWarningType = GenericWarningType.OTHER, @@ -101,7 +103,7 @@ sealed interface SwapWarning { * * @property priceImpact in format = 10 (means 10%) */ - data class HighPriceImpact(val priceImpact: Int) : SwapWarning + data class HighPriceImpact(val priceImpact: Int, val notificationConfig: NotificationConfig) : SwapWarning } enum class GenericWarningType { diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt index 9f591cd1c8..0fc01468a0 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt @@ -3,9 +3,12 @@ package com.tangem.feature.swap.ui import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import com.tangem.common.Provider +import com.tangem.core.ui.components.notifications.NotificationConfig import com.tangem.core.ui.components.states.Item import com.tangem.core.ui.components.states.SelectableItemsState import com.tangem.core.ui.extensions.TextReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.tokens.model.CryptoCurrency import com.tangem.feature.swap.converters.TokensDataConverter import com.tangem.feature.swap.domain.models.DataError @@ -132,14 +135,23 @@ internal class StateBuilder(val actions: UiActions, val isBalanceHiddenProvider: quoteModel.preparedSwapConfigState.isFeeEnough && quoteModel.permissionState is PermissionDataState.PermissionReadyForRequest ) { - warnings.add(SwapWarning.PermissionNeeded(fromToken.symbol)) + warnings.add( + SwapWarning.PermissionNeeded( + createPermissionNotificationConfig(fromToken.symbol), + ), + ) } if (!quoteModel.preparedSwapConfigState.isBalanceEnough) { warnings.add(SwapWarning.InsufficientFunds) } if (quoteModel.priceImpact > PRICE_IMPACT_THRESHOLD) { - warnings.add(SwapWarning.HighPriceImpact((quoteModel.priceImpact * HUNDRED_PERCENTS).toInt())) + warnings.add( + SwapWarning.HighPriceImpact( + priceImpact = (quoteModel.priceImpact * HUNDRED_PERCENTS).toInt(), + notificationConfig = highPriceImpactNotificationConfig(), + ), + ) } val feeState = createFeeState(quoteModel, uiStateHolder, onFeeSetup) return uiStateHolder.copy( @@ -626,6 +638,25 @@ internal class StateBuilder(val actions: UiActions, val isBalanceHiddenProvider: } } + private fun createPermissionNotificationConfig(fromTokenSymbol: String): NotificationConfig { + return NotificationConfig( + title = resourceReference(R.string.swapping_permission_header), + subtitle = resourceReference( + id = R.string.swapping_permission_subheader, + formatArgs = wrappedList(fromTokenSymbol), + ), + iconResId = R.drawable.ic_locked_24, + ) + } + + private fun highPriceImpactNotificationConfig(): NotificationConfig { + return NotificationConfig( + title = resourceReference(R.string.swapping_high_price_impact), + subtitle = resourceReference(R.string.swapping_high_price_impact_description), + iconResId = R.drawable.ic_locked_24, + ) + } + private fun getShortAddressValue(fullAddress: String): String { check(fullAddress.length > ADDRESS_MIN_LENGTH) { "Invalid address" } val firstAddressPart = fullAddress.substring(startIndex = 0, endIndex = ADDRESS_FIRST_PART_LENGTH) diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt index b3c9b23c76..1ea66c1e90 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/SwapScreenContent.kt @@ -20,11 +20,14 @@ import androidx.constraintlayout.compose.ConstraintLayout import com.tangem.common.Strings.STARS import com.tangem.core.ui.components.* import com.tangem.core.ui.components.appbar.AppBarWithBackButton +import com.tangem.core.ui.components.notifications.Notification +import com.tangem.core.ui.components.notifications.NotificationConfig import com.tangem.core.ui.components.states.Item import com.tangem.core.ui.components.states.SelectableItemsState import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.getActiveIconRes import com.tangem.core.ui.extensions.getActiveIconResByCoinId +import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.res.TangemTheme import com.tangem.feature.swap.domain.models.ui.FeeType import com.tangem.feature.swap.domain.models.ui.TxFee @@ -280,26 +283,13 @@ private fun SwapWarnings(warnings: List) { warnings.forEach { warning -> when (warning) { is SwapWarning.HighPriceImpact -> { - WarningCard( - title = stringResource(id = R.string.swapping_high_price_impact), - description = stringResource(id = R.string.swapping_high_price_impact_description), + Notification( + config = warning.notificationConfig, ) } is SwapWarning.PermissionNeeded -> { - WarningCard( - title = stringResource(id = R.string.swapping_permission_header), - description = stringResource( - id = R.string.swapping_permission_subheader, - warning.tokenCurrency, - ), - icon = { - Icon( - painter = painterResource(id = com.tangem.core.ui.R.drawable.ic_locked_24), - contentDescription = null, - modifier = Modifier.size(TangemTheme.dimens.size20), - tint = TangemTheme.colors.icon.primary1, - ) - }, + Notification( + config = warning.notificationConfig, ) } is SwapWarning.GenericWarning -> { @@ -316,14 +306,12 @@ private fun SwapWarnings(warnings: List) { onClick = warning.onClick, ) } + is SwapWarning.NoAvailableTokensToSwap -> { + Notification( + config = warning.notificationConfig, + ) + } else -> {} - // is SwapWarning.RateExpired -> { - // RefreshableWaringCard( - // title = stringResource(id = R.string.), - // description = stringResource(id = R.string.), - // onClick = warning.onClick, - // ) - // } } SpacerH8() } @@ -446,7 +434,22 @@ private val state = SwapStateHolder( state = stateSelectable, onSelectItem = {}, ), - warnings = listOf(SwapWarning.PermissionNeeded("DAI")), + warnings = listOf( + SwapWarning.PermissionNeeded( + notificationConfig = NotificationConfig( + title = stringReference("Give Premission"), + subtitle = stringReference("To continue swapping you need to give permission to Tangem"), + iconResId = R.drawable.ic_locked_24, + ), + ), + SwapWarning.NoAvailableTokensToSwap( + notificationConfig = NotificationConfig( + title = stringReference("No tokens"), + subtitle = stringReference("Swap tokens not available"), + iconResId = R.drawable.ic_alert_24, + ), + ), + ), networkCurrency = "MATIC", swapButton = SwapButton(enabled = true, loading = false, onClick = {}), onRefresh = {}, diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt index 1da348c56c..03e7c8d26e 100644 --- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt +++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/viewmodels/SwapViewModel.kt @@ -336,7 +336,8 @@ internal class SwapViewModel @Inject constructor( approveData = requireNotNull(dataState.approveDataModel) { "dataState.approveDataModel might not be null" }, - forTokenContractAddress = (dataState.fromCryptoCurrency as? CryptoCurrency.Token)?.contractAddress + forTokenContractAddress = (dataState.fromCryptoCurrency as? CryptoCurrency.Token) + ?.contractAddress ?: "", fromToken = requireNotNull(dataState.fromCryptoCurrency) { "dataState.fromCurrency might not be null"