Updated on 2026-08-14

This commit is contained in:
Tangem 2025-10-14 20:27:43 +05:00
parent aaf4419ebe
commit 9850ac2858
12 changed files with 342 additions and 5 deletions

View file

@ -88,6 +88,7 @@ import com.tangem.features.tokenreceive.TokenReceiveFeatureToggle
import com.tangem.features.txhistory.entity.TxHistoryContentUpdateEmitter
import com.tangem.features.yield.supply.api.YieldSupplyDepositedWarningComponent
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.utils.Provider
import com.tangem.utils.coroutines.*
import com.tangem.utils.extensions.isZero
@ -1053,6 +1054,12 @@ internal class TokenDetailsModel @Inject constructor(
}
override fun onYieldInfoClick() {
analyticsEventsHandler.send(
YieldSupplyAnalytics.EarnedFundsInfo(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
),
)
bottomSheetNavigation.activate(
configuration = TokenDetailsBottomSheetConfig.YieldSupplyWarning(
cryptoCurrency = cryptoCurrency,

View file

@ -12,6 +12,8 @@ dependencies {
/** Core */
implementation(projects.core.decompose)
implementation(projects.core.ui)
implementation(projects.core.analytics)
implementation(projects.core.analytics.models)
/** Domain */
implementation(projects.domain.models)

View file

@ -0,0 +1,203 @@
package com.tangem.features.yield.supply.api.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam.Key.ACTION
import com.tangem.core.analytics.models.AnalyticsParam.Key.BLOCKCHAIN
import com.tangem.core.analytics.models.AnalyticsParam.Key.ERROR_DESCRIPTION
import com.tangem.core.analytics.models.AnalyticsParam.Key.STATUS
import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
sealed class YieldSupplyAnalytics(
event: String,
params: Map<String, String> = mapOf(),
) : AnalyticsEvent(category = "Earning", event = event, params = params) {
data class EarningScreenInfoOpened(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Earning Screen Info Opened",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data class StartEarningScreen(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Start Earning Screen",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data class ButtonStartEarning(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Button - Start Earning",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data class ButtonStopEarning(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Button - Stop Earning",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data object ButtonFeePolicy : YieldSupplyAnalytics(
event = "Button - Fee Policy",
)
data object EarnInProgressScreen : YieldSupplyAnalytics(
event = "Earn In Progress Screen",
)
data object FundsEarned : YieldSupplyAnalytics(
event = "Funds Earned",
)
data class FundsWithdrawn(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Funds Withdrawn",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data class EarnedFundsInfo(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Earned Funds Info",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data class NoticeNotEnoughFee(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Notice - Not Enough Fee",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data class NoticeApproveNeeded(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Notice - Approve Needed",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data class ApprovalAction(
val token: String,
val blockchain: String,
val action: Action,
) : YieldSupplyAnalytics(
event = "Approval Action",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
ACTION to action.value,
),
)
data class NoticeHighNetworkFee(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Notice - High Network Fee",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data class EarnErrors(
val action: Action,
val errorDescription: String?,
) : YieldSupplyAnalytics(
event = "Earn Errors",
params = buildMap {
ACTION to action
ERROR_DESCRIPTION to errorDescription.orEmpty()
},
)
data class AssetStatusLoaded(
val status: AssetStatus,
) : YieldSupplyAnalytics(
event = "Asset Status Loaded",
params = mapOf(
STATUS to status.value,
),
)
data class ActionBlockedByStatus(
val status: AssetStatus,
) : YieldSupplyAnalytics(
event = "Action Blocked by Status",
params = mapOf(
STATUS to status.value,
),
)
data object ApyChartViewed : YieldSupplyAnalytics(
event = "APY Chart",
)
data class NoticeCommissionTooHigh(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Notice - Commission Is Too High",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
data class NoticeNotEnoughMinAmount(
val token: String,
val blockchain: String,
) : YieldSupplyAnalytics(
event = "Notice - Not Enough Min Amount",
params = mapOf(
TOKEN_PARAM to token,
BLOCKCHAIN to blockchain,
),
)
enum class Action(val value: String) {
Approve("Approve"),
Stop("Stop"),
}
enum class AssetStatus(val value: String) {
Active("ACTIVE"),
Inactive("Inactive"),
}
}

View file

@ -21,6 +21,8 @@ dependencies {
implementation(projects.core.decompose)
implementation(projects.core.ui)
implementation(projects.core.navigation)
implementation(projects.core.analytics)
implementation(projects.core.analytics.models)
/** Compose */
implementation(tangemDeps.vico.core)

View file

@ -4,6 +4,7 @@ import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
import com.tangem.common.routing.AppRoute.YieldSupplyPromo
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -25,6 +26,7 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyIsAvailableUseCase
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.api.YieldSupplyComponent
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.main.entity.YieldSupplyUM
import com.tangem.features.yield.supply.impl.main.model.transformers.YieldSupplyTokenStatusSuccessTransformer
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -43,6 +45,7 @@ import kotlin.properties.Delegates
internal class YieldSupplyModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
private val analyticsEventsHandler: AnalyticsEventHandler,
private val appRouter: AppRouter,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
@ -188,6 +191,14 @@ internal class YieldSupplyModel @Inject constructor(
}
yieldSupplyStatus?.isActive == true -> {
val cryptoCurrencyToken = cryptoCurrency as? CryptoCurrency.Token ?: return
if (!yieldSupplyStatus.isAllowedToSpend) {
analyticsEventsHandler.send(
YieldSupplyAnalytics.NoticeApproveNeeded(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
),
)
}
modelScope.launch(dispatchers.default) {
yieldSupplyGetTokenStatusUseCase(cryptoCurrencyToken)
.onRight { tokenStatus ->

View file

@ -3,12 +3,16 @@ package com.tangem.features.yield.supply.impl.promo.model
import com.arkivanov.decompose.router.slot.SlotNavigation
import com.arkivanov.decompose.router.slot.activate
import com.tangem.common.routing.AppRouter
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.navigation.url.UrlOpener
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.features.yield.supply.api.YieldSupplyPromoComponent
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.promo.YieldSupplyPromoConfig
import com.tangem.features.yield.supply.impl.promo.entity.YieldSupplyPromoUM
import com.tangem.utils.TangemBlogUrlBuilder.YIELD_SUPPLY_HOW_IT_WORKS_URL
@ -18,16 +22,29 @@ import javax.inject.Inject
@ModelScoped
internal class YieldSupplyPromoModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
paramsContainer: ParamsContainer,
private val analytics: AnalyticsEventHandler,
private val urlOpener: UrlOpener,
private val appRouter: AppRouter,
) : Model(), YieldSupplyPromoClickIntents {
val params: YieldSupplyPromoComponent.Params = paramsContainer.require()
val uiState: YieldSupplyPromoUM = YieldSupplyPromoUM(
tosLink = "https://tangem.com/terms-of-service/", // TODO replace with real link
policyLink = "https://tangem.com/privacy-policy/", // TODO replace with real link
title = resourceReference(R.string.yield_module_promo_screen_title, wrappedList("5.3")),
)
init {
analytics.send(
YieldSupplyAnalytics.EarningScreenInfoOpened(
token = params.currency.symbol,
blockchain = params.currency.network.name,
),
)
}
val bottomSheetNavigation: SlotNavigation<YieldSupplyPromoConfig> = SlotNavigation()
override fun onBackClick() {
@ -35,6 +52,7 @@ internal class YieldSupplyPromoModel @Inject constructor(
}
override fun onApyInfoClick() {
analytics.send(YieldSupplyAnalytics.ApyChartViewed)
bottomSheetNavigation.activate(YieldSupplyPromoConfig.Apy)
}

View file

@ -2,6 +2,7 @@ package com.tangem.features.yield.supply.impl.subcomponents.active.model
import arrow.core.getOrElse
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -19,6 +20,7 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyGetProtocolBalanceUseCa
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyMinAmountUseCase
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.common.formatter.YieldSupplyMinAmountFormatter
import com.tangem.features.yield.supply.impl.subcomponents.active.YieldSupplyActiveComponent
import com.tangem.features.yield.supply.impl.subcomponents.active.entity.YieldSupplyActiveContentUM
@ -29,10 +31,12 @@ import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@Suppress("LongParameterList")
@ModelScoped
internal class YieldSupplyActiveModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
analyticsHandler: AnalyticsEventHandler,
private val yieldSupplyGetProtocolBalanceUseCase: YieldSupplyGetProtocolBalanceUseCase,
private val yieldSupplyGetTokenStatusUseCase: YieldSupplyGetTokenStatusUseCase,
private val yieldSupplyMinAmountUseCase: YieldSupplyMinAmountUseCase,
@ -62,6 +66,12 @@ internal class YieldSupplyActiveModel @Inject constructor(
)
init {
analyticsHandler.send(
YieldSupplyAnalytics.EarningScreenInfoOpened(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
),
)
subscribeOnCurrencyUpdates()
modelScope.launch(dispatchers.default) {

View file

@ -3,6 +3,7 @@ package com.tangem.features.yield.supply.impl.subcomponents.approve.model
import arrow.core.getOrElse
import com.tangem.blockchain.common.TransactionData
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -21,6 +22,7 @@ import com.tangem.domain.transaction.usecase.CreateApprovalTransactionUseCase
import com.tangem.domain.transaction.usecase.GetFeeUseCase
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetContractAddressUseCase
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.impl.common.YieldSupplyAlertFactory
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM
@ -46,6 +48,7 @@ import javax.inject.Inject
internal class YieldSupplyApproveModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
paramsContainer: ParamsContainer,
private val analyticsEventHandler: AnalyticsEventHandler,
private val urlOpener: UrlOpener,
private val yieldSupplyNotificationsUpdateTrigger: YieldSupplyNotificationsUpdateTrigger,
private val createApprovalTransactionUseCase: CreateApprovalTransactionUseCase,
@ -140,6 +143,11 @@ internal class YieldSupplyApproveModel @Inject constructor(
)
},
ifRight = {
analyticsEventHandler.send(YieldSupplyAnalytics.ApprovalAction(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
action = YieldSupplyAnalytics.Action.Approve,
))
params.callback.onTransactionSent()
},
)

View file

@ -5,11 +5,13 @@ import com.tangem.common.routing.AppRouter
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.common.ui.notifications.NotificationsFactory.addExceedsBalanceNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addFeeUnreachableNotification
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.domain.models.currency.CryptoCurrency
import com.tangem.domain.tokens.GetBalanceNotEnoughForFeeWarningUseCase
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsComponent
import com.tangem.features.yield.supply.impl.subcomponents.notifications.YieldSupplyNotificationsUpdateListener
import com.tangem.lib.crypto.BlockchainUtils
@ -25,6 +27,7 @@ import javax.inject.Inject
internal class YieldSupplyNotificationsModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
private val analyticsEventHandler: AnalyticsEventHandler,
private val appRouter: AppRouter,
private val getBalanceNotEnoughForFeeWarningUseCase: GetBalanceNotEnoughForFeeWarningUseCase,
private val yieldSupplyNotificationsUpdateListener: YieldSupplyNotificationsUpdateListener,
@ -72,6 +75,15 @@ internal class YieldSupplyNotificationsModel @Inject constructor(
)
}
if (notifications.any { it is NotificationUM.Error.TokenExceedsBalance }) {
analyticsEventHandler.send(
YieldSupplyAnalytics.NoticeNotEnoughFee(
token = cryptoCurrencyStatus.currency.symbol,
blockchain = cryptoCurrencyStatus.currency.network.name,
),
)
}
uiState.update { notifications.toPersistentList() }
yieldSupplyNotificationsUpdateListener.callbackHasError(notifications.any())

View file

@ -1,5 +1,6 @@
package com.tangem.features.yield.supply.impl.subcomponents.startearning.model
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -8,6 +9,7 @@ import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIco
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.wrappedList
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM
import com.tangem.features.yield.supply.impl.subcomponents.feepolicy.YieldSupplyFeePolicyComponent
@ -24,6 +26,7 @@ import javax.inject.Inject
internal class YieldSupplyStartEarningEntryModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
private val router: Router,
private val analyticsEventHandler: AnalyticsEventHandler,
paramsContainer: ParamsContainer,
) : Model(), YieldSupplyStartEarningComponent.ModelCallback, YieldSupplyFeePolicyComponent.ModelCallback {
@ -55,6 +58,9 @@ internal class YieldSupplyStartEarningEntryModel @Inject constructor(
}
override fun onFeePolicyClick() {
analyticsEventHandler.send(
YieldSupplyAnalytics.ButtonFeePolicy,
)
router.push(YieldSupplyStartEarningRoute.FeePolicy)
}

View file

@ -2,6 +2,7 @@ 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.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -17,6 +18,7 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
import com.tangem.domain.tokens.GetFeePaidCryptoCurrencyStatusSyncUseCase
import com.tangem.domain.tokens.GetSingleCryptoCurrencyStatusUseCase
import com.tangem.domain.transaction.error.GetFeeError
import com.tangem.domain.transaction.usecase.SendTransactionUseCase
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyActivateUseCase
@ -25,6 +27,7 @@ import com.tangem.domain.yield.supply.usecase.YieldSupplyGetTokenStatusUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyMinAmountUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyStartEarningUseCase
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.common.YieldSupplyAlertFactory
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM
@ -38,6 +41,7 @@ import com.tangem.features.yield.supply.impl.subcomponents.startearning.model.tr
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.extensions.orZero
import com.tangem.utils.transformer.update
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
@ -50,6 +54,7 @@ import kotlin.properties.Delegates
internal class YieldSupplyStartEarningModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
paramsContainer: ParamsContainer,
private val analytics: AnalyticsEventHandler,
private val getUserWalletUseCase: GetUserWalletUseCase,
private val getSingleCryptoCurrencyStatusUseCase: GetSingleCryptoCurrencyStatusUseCase,
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
@ -108,6 +113,12 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
private var appCurrency = AppCurrency.Default
init {
analytics.send(
YieldSupplyAnalytics.StartEarningScreen(
token = params.cryptoCurrency.symbol,
blockchain = params.cryptoCurrency.network.name,
),
)
modelScope.launch {
appCurrency = getSelectedAppCurrencyUseCase.invokeSync().getOrElse { AppCurrency.Default }
subscribeOnCurrencyStatusUpdates()
@ -133,6 +144,10 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
private suspend fun onLoadFee() {
if (cryptoCurrencyStatus.value is CryptoCurrencyStatus.Loading || uiState.value.isTransactionSending) return
uiState.update {
it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading)
}
val maxFee = if (uiState.value.maxFee == BigDecimal.ZERO) {
getMaxFee()
} else {
@ -143,10 +158,19 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
userWalletId = userWallet.walletId,
cryptoCurrencyStatus = cryptoCurrencyStatus,
maxNetworkFee = maxFee,
).getOrNull() ?: return
).getOrNull()
uiState.update {
it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Loading)
if (transactionListData == null) {
uiState.update {
it.copy(yieldSupplyFeeUM = YieldSupplyFeeUM.Error)
}
yieldSupplyNotificationsUpdateTrigger.triggerUpdate(
data = YieldSupplyNotificationData(
feeValue = null,
feeError = GetFeeError.UnknownError,
),
)
return
}
yieldSupplyEstimateEnterFeeUseCase.invoke(
@ -192,6 +216,12 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
fun onClick() {
val yieldSupplyFeeUM = uiState.value.yieldSupplyFeeUM as? YieldSupplyFeeUM.Content ?: return
analytics.send(
YieldSupplyAnalytics.ButtonStartEarning(
token = params.cryptoCurrency.symbol,
blockchain = params.cryptoCurrency.network.name,
),
)
uiState.update(YieldSupplyTransactionInProgressTransformer)
modelScope.launch(dispatchers.default) {
@ -204,6 +234,10 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
ifLeft = { error ->
Timber.e(error.toString())
uiState.update(YieldSupplyTransactionReadyTransformer)
analytics.send(YieldSupplyAnalytics.EarnErrors(
action = YieldSupplyAnalytics.Action.Approve,
errorDescription = error.getAnalyticsDescription(),
))
yieldSupplyAlertFactory.getSendTransactionErrorState(
error = error,
popBack = params.callback::onBackClick,
@ -219,8 +253,14 @@ internal class YieldSupplyStartEarningModel @Inject constructor(
)
},
ifRight = {
fetchCurrencyStatusUseCase(userWalletId = userWallet.walletId, cryptoCurrency.id)
yieldSupplyActivateUseCase(cryptoCurrency)
modelScope.launch(NonCancellable) {
fetchCurrencyStatusUseCase(
userWalletId = userWallet.walletId,
cryptoCurrency.id,
)
}
analytics.send(YieldSupplyAnalytics.FundsEarned)
modelScope.launch {
params.callback.onTransactionSent()
}

View file

@ -1,6 +1,7 @@
package com.tangem.features.yield.supply.impl.subcomponents.stopearning.model
import arrow.core.getOrElse
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -19,6 +20,7 @@ import com.tangem.domain.transaction.usecase.SendTransactionUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyDeactivateUseCase
import com.tangem.domain.yield.supply.usecase.YieldSupplyStopEarningUseCase
import com.tangem.features.yield.supply.impl.R
import com.tangem.features.yield.supply.api.analytics.YieldSupplyAnalytics
import com.tangem.features.yield.supply.impl.common.YieldSupplyAlertFactory
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyActionUM
import com.tangem.features.yield.supply.impl.common.entity.YieldSupplyFeeUM
@ -33,6 +35,7 @@ import com.tangem.utils.TangemBlogUrlBuilder
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.extensions.orZero
import com.tangem.utils.transformer.update
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import timber.log.Timber
@ -43,6 +46,7 @@ import javax.inject.Inject
internal class YieldSupplyStopEarningModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
paramsContainer: ParamsContainer,
private val analytics: AnalyticsEventHandler,
private val getFeeUseCase: GetFeeUseCase,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
private val getFeePaidCryptoCurrencyStatusSyncUseCase: GetFeePaidCryptoCurrencyStatusSyncUseCase,
@ -112,6 +116,12 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
fun onClick() {
val yieldSupplyFeeUM = uiState.value.yieldSupplyFeeUM as? YieldSupplyFeeUM.Content ?: return
analytics.send(
YieldSupplyAnalytics.ButtonStopEarning(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
),
)
uiState.update(YieldSupplyTransactionInProgressTransformer)
modelScope.launch(dispatchers.default) {
@ -138,8 +148,16 @@ internal class YieldSupplyStopEarningModel @Inject constructor(
)
},
ifRight = {
fetchCurrencyStatusUseCase(userWalletId = userWallet.walletId, cryptoCurrency.id)
analytics.send(
YieldSupplyAnalytics.FundsWithdrawn(
token = cryptoCurrency.symbol,
blockchain = cryptoCurrency.network.name,
),
)
yieldSupplyDeactivateUseCase(cryptoCurrency)
modelScope.launch(NonCancellable) {
fetchCurrencyStatusUseCase(userWalletId = userWallet.walletId, cryptoCurrency.id)
}
params.callback.onTransactionSent()
},
)