Updated on 2026-08-14

This commit is contained in:
Tangem 2023-11-16 15:50:21 +03:00
parent 6fba280ec3
commit b2291e9864
7 changed files with 69 additions and 35 deletions

View file

@ -35,6 +35,7 @@ class GetCryptoCurrencyStatusUseCase(
}
}
@Suppress("UnusedPrivateMember")
private fun createTokenList(
userWalletId: UserWalletId,
tokens: List<CryptoCurrencyStatus>,

View file

@ -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")

View file

@ -453,6 +453,7 @@ internal class SwapInteractorImpl @Inject constructor(
return toToken
}
@Suppress("UnusedPrivateMember")
@Deprecated("used in old swap mechanism")
private fun getTokensWithBalance(
tokens: List<Currency>,

View file

@ -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 {

View file

@ -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)

View file

@ -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<SwapWarning>) {
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<SwapWarning>) {
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 = {},

View file

@ -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"