Updated on 2026-08-14

This commit is contained in:
Tangem 2026-05-08 20:52:21 +02:00
parent b01ede005a
commit 03ae5e3331
6 changed files with 29 additions and 20 deletions

View file

@ -11,6 +11,9 @@ object TangemSiteUrlBuilder {
const val NOTE_MIGRATION_URL = "https://tangem.com/en/?promocode=Note10"
const val HELP_CENTER_SWAP_URL =
"https://tangem.com/en/help-center/tangem-wallet-core-functionality/how-to-swap-coins-and-tokens/"
suspend fun getUtmTags(campaign: String?): String {
val langCode = Locale.getDefault().language
val utmCampaignPart = campaign?.let { "&utm_campaign=$it-$langCode" }.orEmpty()

View file

@ -1,5 +1,6 @@
package com.tangem.feature.swap.model
import com.tangem.common.TangemSiteUrlBuilder
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.common.ui.notifications.NotificationsFactory.addDustWarningNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addExistentialWarningNotification
@ -104,14 +105,13 @@ internal class SwapNotificationsFactory(
quoteModel: SwapState.QuotesLoadedState,
feeCryptoCurrencyStatus: CryptoCurrencyStatus?,
selectedFeeType: FeeType,
providerName: String,
hideFee: Boolean,
): ImmutableList<NotificationUM> {
val warnings = buildList {
maybeAddRentExemptionError(quoteModel)
maybeAddDomainWarnings(quoteModel, feeCryptoCurrencyStatus, selectedFeeType)
maybeAddNeedReserveToCreateAccountWarning(quoteModel)
maybeAddPermissionNeededWarning(quoteModel, providerName)
maybeAddPermissionNeededWarning(quoteModel)
maybeAddNetworkFeeCoverageWarning(quoteModel, selectedFeeType)
maybeAddUnableCoverFeeWarning(quoteModel, feeCryptoCurrencyStatus, hideFee)
maybeAddTransactionInProgressWarning(quoteModel)
@ -253,16 +253,12 @@ internal class SwapNotificationsFactory(
}
}
private fun MutableList<NotificationUM>.maybeAddPermissionNeededWarning(
quoteModel: SwapState.QuotesLoadedState,
providerName: String,
) {
private fun MutableList<NotificationUM>.maybeAddPermissionNeededWarning(quoteModel: SwapState.QuotesLoadedState) {
if (quoteModel.permissionState is PermissionDataState.PermissionRequired) {
add(
SwapNotificationUM.Info.PermissionNeeded(
providerName = providerName,
fromTokenSymbol = quoteModel.fromTokenInfo.swapCurrencyStatus.currency.symbol,
onApproveClick = actions.openPermissionBottomSheet,
onLearnMoreClick = { actions.onLinkClick(TangemSiteUrlBuilder.HELP_CENTER_SWAP_URL) },
),
)
}

View file

@ -5,8 +5,11 @@ import com.tangem.common.ui.extensions.networkIconResId
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.ui.components.notifications.NotificationConfig
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.combinedReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.styledResourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.core.ui.res.TangemTheme
import com.tangem.domain.express.models.ExpressError
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.feature.swap.utils.getExpressErrorMessage
@ -217,14 +220,25 @@ internal object SwapNotificationUM {
iconResId = iconResId,
) {
data class PermissionNeeded(
val providerName: String,
val fromTokenSymbol: String,
val onApproveClick: () -> Unit,
val onLearnMoreClick: () -> Unit,
) : Info(
title = resourceReference(R.string.express_provider_permission_needed),
subtitle = resourceReference(
id = R.string.give_permission_swap_subtitle,
formatArgs = wrappedList(providerName, fromTokenSymbol),
subtitle = combinedReference(
resourceReference(
id = R.string.give_permission_swap_subtitle_v2,
// Arg is only used in iOS
formatArgs = wrappedList(""),
),
styledResourceReference(
id = R.string.common_learn_more,
spanStyleReference = {
TangemTheme.typography.caption2
.copy(color = TangemTheme.colors.text.accent)
.toSpanStyle()
},
onClick = onLearnMoreClick,
),
),
iconResId = R.drawable.ic_locked_24,
buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig(

View file

@ -462,7 +462,6 @@ internal class StateBuilder(
quoteModel = quoteModel,
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
selectedFeeType = selectedFeeType,
providerName = swapProvider.name,
hideFee = hideFee,
)

View file

@ -384,9 +384,8 @@ private val state = SwapStateHolder(
),
notifications = persistentListOf(
SwapNotificationUM.Info.PermissionNeeded(
providerName = "Provider",
fromTokenSymbol = "POL",
onApproveClick = {},
onLearnMoreClick = {},
),
SwapNotificationUM.Warning.NoAvailableTokensToSwap("POLYGON"),
),

View file

@ -132,9 +132,8 @@ internal class StateBuilderSwapDataTest {
@Test
fun `GIVEN notifications with PermissionNeeded WHEN called THEN PermissionNeeded is removed`() {
val permissionNeeded = SwapNotificationUM.Info.PermissionNeeded(
providerName = "TestProvider",
fromTokenSymbol = "ETH",
onApproveClick = {},
onLearnMoreClick = {},
)
val otherNotification = SwapNotificationUM.Warning.SwapNotSupported
val baseState = buildReadyState(coldWallet).copy(
@ -357,9 +356,8 @@ internal class StateBuilderSwapDataTest {
@Test
fun `GIVEN notifications with PermissionNeeded WHEN called THEN PermissionNeeded is replaced by ApprovalInProgressWarning`() {
val permissionNeeded = SwapNotificationUM.Info.PermissionNeeded(
providerName = "TestProvider",
fromTokenSymbol = "ETH",
onApproveClick = {},
onLearnMoreClick = {},
)
val baseState = buildReadyState(coldWallet).copy(
notifications = persistentListOf(permissionNeeded),