Updated on 2026-08-14
This commit is contained in:
parent
6fba280ec3
commit
b2291e9864
7 changed files with 69 additions and 35 deletions
|
|
@ -35,6 +35,7 @@ class GetCryptoCurrencyStatusUseCase(
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
private fun createTokenList(
|
||||
userWalletId: UserWalletId,
|
||||
tokens: List<CryptoCurrencyStatus>,
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 = {},
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue