Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-31 10:06:00 +04:00
parent 8c5711166f
commit 5a4b35a90e
8 changed files with 74 additions and 10 deletions

View file

@ -131,6 +131,12 @@ sealed class AnalyticsParam {
override val token: String,
override val feeType: FeeType,
) : TxSentFrom("Send&Swap"), TxData
data class Earning(
override val blockchain: String,
override val token: String,
override val feeType: FeeType,
) : TxSentFrom("Earning"), TxData
}
sealed interface TxData {

View file

@ -184,6 +184,7 @@ sealed class TokenScreenAnalyticsEvent(
private const val LOADING = "Loading"
private const val ASSET_REQUIREMENT = "AssetRequirement"
private const val TRUSTLINE_REQUIREMENT = "TrustlineRequirement"
private const val APPROVAL_REQUIRED = "Approval Required"
@Suppress("CyclomaticComplexMethod")
fun ScenarioUnavailabilityReason.toReasonAnalyticsText(): String {
@ -192,8 +193,8 @@ sealed class TokenScreenAnalyticsEvent(
is ScenarioUnavailabilityReason.NotExchangeable,
is ScenarioUnavailabilityReason.NotSupportedBySellService,
is ScenarioUnavailabilityReason.StakingUnavailable,
ScenarioUnavailabilityReason.YieldSupplyApprovalRequired,
-> UNAVAILABLE
is ScenarioUnavailabilityReason.YieldSupplyApprovalRequired -> APPROVAL_REQUIRED
ScenarioUnavailabilityReason.UnassociatedAsset -> ASSET_REQUIREMENT
ScenarioUnavailabilityReason.TrustlineRequired -> TRUSTLINE_REQUIREMENT
is ScenarioUnavailabilityReason.EmptyBalance -> EMPTY

View file

@ -77,12 +77,26 @@ sealed class YieldSupplyAnalytics(
),
)
data object ButtonFeePolicy : YieldSupplyAnalytics(
data class ButtonFeePolicy(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Button - Fee Policy",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data object EarnInProgressScreen : YieldSupplyAnalytics(
data class EarnInProgressScreen(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Earn In Progress Screen",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data object FundsEarned : YieldSupplyAnalytics(
@ -162,10 +176,10 @@ sealed class YieldSupplyAnalytics(
val errorDescription: String?,
) : YieldSupplyAnalytics(
event = "Earn Errors",
params = buildMap {
ACTION to action
ERROR_DESCRIPTION to errorDescription.orEmpty()
},
params = mapOf(
ACTION to action.value,
ERROR_DESCRIPTION to errorDescription.orEmpty(),
),
)
data object ApyChartViewed : YieldSupplyAnalytics(

View file

@ -45,7 +45,7 @@ import javax.inject.Inject
internal class YieldSupplyActiveModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
analyticsHandler: AnalyticsEventHandler,
private val analyticsHandler: AnalyticsEventHandler,
private val yieldSupplyGetProtocolBalanceUseCase: YieldSupplyGetProtocolBalanceUseCase,
private val yieldSupplyGetTokenStatusUseCase: YieldSupplyGetTokenStatusUseCase,
private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase,
@ -82,7 +82,7 @@ internal class YieldSupplyActiveModel @Inject constructor(
init {
analyticsHandler.send(
YieldSupplyAnalytics.EarningScreenInfoOpened(
YieldSupplyAnalytics.EarnInProgressScreen(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
),
@ -189,6 +189,12 @@ internal class YieldSupplyActiveModel @Inject constructor(
return if (notDepositedAmount > BigDecimal.ZERO) {
val formattedAmount =
notDepositedAmount.format { crypto(symbol = "", decimals = cryptoCurrencyStatus.currency.decimals) }
analyticsHandler.send(
YieldSupplyAnalytics.NoticeAmountNotDeposited(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
),
)
NotificationUM.Warning.YieldSupplyNotAllAmountSupplied(
formattedAmount = formattedAmount,
symbol = cryptoCurrency.symbol,
@ -243,6 +249,7 @@ internal class YieldSupplyActiveModel @Inject constructor(
appCurrency = appCurrency,
feeValue = currentFee,
maxNetworkFee = maxFee,
analyticsHandler = analyticsHandler,
),
)
} else {

View file

@ -1,5 +1,6 @@
package com.tangem.features.yield.supply.impl.subcomponents.active.model.transformers
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
import com.tangem.core.ui.extensions.wrappedList
@ -9,6 +10,7 @@ import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.core.ui.extensions.TextReference
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.models.currency.CryptoCurrencyStatus
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM
import com.tangem.utils.transformer.Transformer
@ -22,6 +24,7 @@ internal class YieldSupplyActiveFeeContentTransformer(
private val appCurrency: AppCurrency,
private val feeValue: BigDecimal,
private val maxNetworkFee: BigDecimal,
private val analyticsHandler: AnalyticsEventHandler,
) : Transformer<YieldSupplyActiveContentUM> {
override fun transform(prevState: YieldSupplyActiveContentUM): YieldSupplyActiveContentUM {
@ -48,6 +51,15 @@ internal class YieldSupplyActiveFeeContentTransformer(
val isHighFee = feeValue > maxNetworkFee
if (isHighFee) {
analyticsHandler.send(
YieldSupplyAnalytics.NoticeHighNetworkFee(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
),
)
}
return prevState.copy(
currentFee = stringReference(tokenFiatFeeValueText),
feeDescription = feeNoteValue,

View file

@ -132,6 +132,12 @@ internal class YieldSupplyApproveModel @Inject constructor(
ifLeft = { error ->
Timber.e(error.toString())
uiState.update(YieldSupplyTransactionReadyTransformer)
analyticsEventHandler.send(
YieldSupplyAnalytics.EarnErrors(
action = YieldSupplyAnalytics.Action.Approve,
errorDescription = error.getAnalyticsDescription(),
),
)
yieldSupplyAlertFactory.getSendTransactionErrorState(
error = error,
popBack = params.callback::onBackClick,

View file

@ -59,7 +59,10 @@ internal class YieldSupplyStartEarningEntryModel @Inject constructor(
override fun onFeePolicyClick() {
analyticsEventHandler.send(
YieldSupplyAnalytics.ButtonFeePolicy,
YieldSupplyAnalytics.ButtonFeePolicy(
token = params.cryptoCurrency.symbol,
blockchain = params.cryptoCurrency.network.name,
),
)
router.push(YieldSupplyStartEarningRoute.FeePolicy)
}

View file

@ -3,6 +3,8 @@ package com.tangem.features.yield.supply.impl.subcomponents.startearning.model
import arrow.core.getOrElse
import com.tangem.blockchain.common.TransactionSender
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.core.analytics.models.Basic
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -252,7 +254,20 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
},
ifRight = {
yieldSupplyRepository.saveTokenProtocolStatus(cryptoCurrency, YieldSupplyEnterStatus.Enter)
val event = AnalyticsParam.TxSentFrom.Earning(
blockchain = cryptoCurrency.network.name,
token = cryptoCurrency.symbol,
feeType = AnalyticsParam.FeeType.Normal,
)
analytics.send(YieldSupplyAnalytics.FundsEarned)
yieldSupplyFeeUM.transactionDataList.forEach {
analytics.send(
Basic.TransactionSent(
sentFrom = event,
memoType = Basic.TransactionSent.MemoType.Null,
),
)
}
val address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
if (address != null) {