Updated on 2026-08-14

This commit is contained in:
Tangem 2026-01-27 15:55:18 +03:00
parent c77fcafdc2
commit b4b35916d9
7 changed files with 55 additions and 12 deletions

View file

@ -314,12 +314,14 @@ object NotificationsFactory {
}
}
@Suppress("LongParameterList")
fun MutableList<NotificationUM>.addExceedsBalanceNotification(
cryptoCurrencyWarning: CryptoCurrencyWarning?,
cryptoCurrencyStatus: CryptoCurrencyStatus,
shouldMergeFeeNetworkName: Boolean,
onClick: (CryptoCurrency) -> Unit,
onAnalyticsEvent: (CryptoCurrency) -> Unit,
onResetAnalyticsEvent: (CryptoCurrency) -> Unit,
) {
when (cryptoCurrencyWarning) {
is CryptoCurrencyWarning.BalanceNotEnoughForFee -> {
@ -357,7 +359,7 @@ object NotificationsFactory {
)
onAnalyticsEvent(cryptoCurrencyWarning.currency)
}
else -> Unit
else -> onResetAnalyticsEvent(cryptoCurrencyStatus.currency)
}
}

View file

@ -0,0 +1,19 @@
package com.tangem.core.analytics.api
import com.tangem.core.analytics.models.AnalyticsEvent
import java.util.concurrent.ConcurrentHashMap
class ResettableOneTimeEventSender(val analyticsEventHandler: AnalyticsEventHandler) {
private val sentEvents = ConcurrentHashMap<String, AnalyticsEvent>()
fun sendEventOnce(key: String, event: AnalyticsEvent) {
if (sentEvents[key] != null) return
analyticsEventHandler.send(event)
sentEvents[key] = event
}
fun reset(key: String) {
sentEvents.remove(key)
}
}

View file

@ -40,7 +40,7 @@ class GetBalanceNotEnoughForFeeWarningUseCase(
val feePaidCurrency = currenciesRepository.getFeePaidCurrency(userWalletId, tokenStatus.currency.network)
val feeTokenBalance = feeStatus.value.amount ?: BigDecimal.ZERO
val isFeePaidByCoin = tokenStatus.currency is CryptoCurrency.Token
val isSendingCurrencyToken = tokenStatus.currency is CryptoCurrency.Token
val isFeePaidByToken =
feePaidCurrency is FeePaidCurrency.Token && tokenStatus.currency.id != feePaidCurrency.tokenId
@ -49,10 +49,15 @@ class GetBalanceNotEnoughForFeeWarningUseCase(
feeStatus.currency is CryptoCurrency.Token
val warning = when {
isFeePaidByGaslessToken && feeTokenBalance == BigDecimal.ZERO -> {
CryptoCurrencyWarning.BalanceNotEnoughForFee(
tokenCurrency = tokenStatus.currency,
coinCurrency = feeStatus.currency,
)
}
feePaidCurrency is FeePaidCurrency.Coin &&
isFeePaidByCoin &&
fee > feeTokenBalance &&
!isFeePaidByGaslessToken -> {
isSendingCurrencyToken &&
fee > feeTokenBalance -> {
CryptoCurrencyWarning.BalanceNotEnoughForFee(
tokenCurrency = tokenStatus.currency,
coinCurrency = feeStatus.currency,

View file

@ -2,6 +2,7 @@ package com.tangem.features.send.v2.api.subcomponents.feeSelector.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.AnalyticsParam.Key.BLOCKCHAIN
import com.tangem.core.analytics.models.AnalyticsParam.Key.FEE_TOKEN
import com.tangem.core.analytics.models.AnalyticsParam.Key.FEE_TYPE
import com.tangem.core.analytics.models.AnalyticsParam.Key.SOURCE
@ -21,6 +22,7 @@ sealed class CommonSendFeeAnalyticEvents(
val feeType: AnalyticsParam.FeeType,
val source: CommonSendSource,
val feeToken: String,
val blockchain: String,
) : CommonSendFeeAnalyticEvents(
category = categoryName,
event = "Fee Selected",
@ -28,15 +30,20 @@ sealed class CommonSendFeeAnalyticEvents(
FEE_TYPE to feeType.value,
SOURCE to source.analyticsName,
FEE_TOKEN to feeToken,
BLOCKCHAIN to blockchain,
),
)
/** Custom fee selected */
data class CustomFeeButtonClicked(
override val categoryName: String,
val blockchain: String,
) : CommonSendFeeAnalyticEvents(
category = categoryName,
event = "Custom Fee Clicked",
params = mapOf(
BLOCKCHAIN to blockchain,
),
)
/** Custom fee edited */

View file

@ -20,6 +20,7 @@ import com.tangem.common.ui.notifications.NotificationsFactory.addReserveAmountE
import com.tangem.common.ui.notifications.NotificationsFactory.addTransactionLimitErrorNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addValidateTransactionNotifications
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.api.ResettableOneTimeEventSender
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -82,6 +83,7 @@ internal class NotificationsModel @Inject constructor(
private val feeCryptoCurrencyStatus = params.notificationData.feeCryptoCurrencyStatus
private val currency = cryptoCurrencyStatus.currency
private val appCurrency = params.appCurrency
private val resettableOneTimeEventSender = ResettableOneTimeEventSender(analyticsEventHandler)
private var notificationData = params.notificationData
@ -250,13 +252,18 @@ internal class NotificationsModel @Inject constructor(
shouldMergeFeeNetworkName = BlockchainUtils.isArbitrum(currency.network.backendId),
onClick = ::showTokenDetails,
onAnalyticsEvent = {
analyticsEventHandler.send(
NotificationsAnalyticEvents.NoticeNotEnoughFee(
categoryName = analyticsCategoryName,
token = cryptoCurrencyStatus.currency.symbol,
blockchain = cryptoCurrencyStatus.currency.network.name,
),
val event = NotificationsAnalyticEvents.NoticeNotEnoughFee(
categoryName = analyticsCategoryName,
token = cryptoCurrencyStatus.currency.symbol,
blockchain = cryptoCurrencyStatus.currency.network.name,
)
resettableOneTimeEventSender.sendEventOnce(
key = EXCEEDS_BALANCE_EVENT,
event = event,
)
},
onResetAnalyticsEvent = {
resettableOneTimeEventSender.reset(EXCEEDS_BALANCE_EVENT)
},
)
if (!BlockchainUtils.isCardano(currency.network.rawId)) {
@ -389,5 +396,6 @@ internal class NotificationsModel @Inject constructor(
companion object {
const val TRON_FEE_NOTIFICATION_MAX_SHOW_COUNT = 3
private const val EXCEEDS_BALANCE_EVENT = "EXCEED_BALANCE_EVENT"
}
}

View file

@ -235,6 +235,7 @@ internal class AddStakingNotificationsTransformer(
shouldMergeFeeNetworkName = BlockchainUtils.isArbitrum(network.backendId),
onClick = prevState.clickIntents::openTokenDetails,
onAnalyticsEvent = { prevState.clickIntents.onNotEnoughFeeNotificationShow() },
onResetAnalyticsEvent = { /*no-op*/ },
)
if (!BlockchainUtils.isCardano(network.rawId)) {
addDustWarningNotification(

View file

@ -64,7 +64,8 @@ internal class YieldSupplyNotificationsModel @Inject constructor(
blockchainId = cryptoCurrencyStatus.currency.network.backendId,
),
onClick = ::openTokenDetails,
onAnalyticsEvent = { },
onAnalyticsEvent = { /*no-op*/ },
onResetAnalyticsEvent = { /*no-op*/ },
)
addFeeUnreachableNotification(