Updated on 2026-08-14

This commit is contained in:
Tangem 2026-02-02 14:11:30 +03:00
commit 45156f05b0
1184 changed files with 47887 additions and 11982 deletions

View file

@ -1,5 +1,7 @@
package com.tangem.core.analytics.models
const val IS_NOT_HTTP_ERROR = "Is not http error"
sealed class AnalyticsParam {
sealed class CardBalanceState(val value: String) {
@ -77,7 +79,9 @@ sealed class AnalyticsParam {
data object Backup : ScreensSources("Backup")
data object Onboarding : ScreensSources("Onboarding")
data object LongTap : ScreensSources("Long Tap")
data object Market : ScreensSources("Market")
data object Markets : ScreensSources("Markets")
data object MarketPulse : ScreensSources("Market Pulse")
data object TangemPay : ScreensSources("Tangem Pay")
data object WalletSettings : ScreensSources("Wallet Settings")
data object Upgrade : ScreensSources("Upgrade")
@ -87,6 +91,9 @@ sealed class AnalyticsParam {
data object AddNewWallet : ScreensSources("Add New Wallet")
data object AddNew : ScreensSources("Add New")
data object CreateWallet : ScreensSources("Create Wallet")
data object NewsList : ScreensSources("News List")
data object NewsLink : ScreensSources("News Link")
data object NewsPage : ScreensSources("News Page")
}
sealed class TxSentFrom(val value: String) {
@ -94,24 +101,28 @@ sealed class AnalyticsParam {
override val blockchain: String,
override val token: String,
override val feeType: FeeType,
override val feeToken: String,
) : TxSentFrom("Send"), TxData
data class Swap(
override val blockchain: String,
override val token: String,
override val feeType: FeeType,
override val feeToken: String,
) : TxSentFrom("Swap"), TxData
data class Staking(
override val blockchain: String,
override val token: String,
override val feeType: FeeType,
override val feeToken: String,
) : TxSentFrom("Staking"), TxData
data class Approve(
override val blockchain: String,
override val token: String,
override val feeType: FeeType,
override val feeToken: String,
val permissionType: String,
) : TxSentFrom("Approve"), TxData
@ -119,6 +130,7 @@ sealed class AnalyticsParam {
override val blockchain: String,
override val token: String,
override val feeType: FeeType?,
override val feeToken: String,
) : TxSentFrom("WalletConnect"), TxData
data object Sell : TxSentFrom("Sell")
@ -127,24 +139,28 @@ sealed class AnalyticsParam {
override val blockchain: String,
override val token: String,
override val feeType: FeeType,
override val feeToken: String,
) : TxSentFrom("NFT"), TxData
data class SendWithSwap(
override val blockchain: String,
override val token: String,
override val feeType: FeeType,
override val feeToken: String,
) : TxSentFrom("Send&Swap"), TxData
data class Earning(
override val blockchain: String,
override val token: String,
override val feeType: FeeType,
override val feeToken: String,
) : TxSentFrom("Earning"), TxData
}
sealed interface TxData {
val blockchain: String
val token: String
val feeToken: String
val feeType: FeeType?
}
@ -268,5 +284,6 @@ sealed class AnalyticsParam {
const val ENS = "ENS"
const val ENS_ADDRESS = "ENS Address"
const val ACCOUNT_DERIVATION_FROM = "Account Derivation (from)"
const val FEE_TOKEN = "Fee Token"
}
}

View file

@ -87,6 +87,7 @@ sealed class Basic(
sentFrom.feeType?.value?.let {
this[AnalyticsParam.Key.FEE_TYPE] = it
}
this[AnalyticsParam.Key.FEE_TOKEN] = sentFrom.feeToken
}
if (sentFrom is AnalyticsParam.TxSentFrom.Approve) {
this[AnalyticsParam.Key.PERMISSION_TYPE] = sentFrom.permissionType

View file

@ -0,0 +1,22 @@
package com.tangem.core.analytics.models
/**
* Marker interface for analytics events that should be sent only once per session.
*
* Events implementing this interface will be tracked by their [oneTimeEventId] to ensure
* they are not sent multiple times during the same application session. Once an event
* with a specific [oneTimeEventId] has been sent, subsequent attempts to send an event
* with the same ID will be ignored.
*
* @see Analytics.send
*/
interface OneTimePerSessionEvent {
/**
* Unique identifier for the one-time event.
*
* This ID is used to track whether the event has already been sent in the current session.
* Events with the same [oneTimeEventId] will only be sent once, even if they are
* different instances of the same event class.
*/
val oneTimeEventId: String
}

View file

@ -6,6 +6,7 @@ import com.tangem.common.extensions.toHexString
import com.tangem.core.analytics.api.*
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.ExceptionAnalyticsEvent
import com.tangem.core.analytics.models.OneTimePerSessionEvent
import com.tangem.utils.coroutines.FeatureCoroutineExceptionHandler
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
@ -31,6 +32,7 @@ object Analytics : GlobalAnalyticsEventHandler {
private val handlers = mutableMapOf<String, AnalyticsHandler>()
private val paramsInterceptors = ConcurrentHashMap<String, ParamsInterceptor>()
private val oneEventsPerSession = ConcurrentHashMap<String, Boolean>()
private val analyticsFilters = mutableSetOf<AnalyticsEventFilter>()
private val analyticsMutex = Mutex()
@ -85,6 +87,11 @@ object Analytics : GlobalAnalyticsEventHandler {
override fun send(event: AnalyticsEvent) {
analyticsScope.launch {
if (event is OneTimePerSessionEvent &&
oneEventsPerSession.putIfAbsent(event.oneTimeEventId, true) != null
) {
return@launch
}
event.params = applyParamsInterceptors(event)
val eventFilter = analyticsFilters.firstOrNull { it.canBeAppliedTo(event) }

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(private val analyticsEventHandler: AnalyticsEventHandler) {
private val sentEvents = ConcurrentHashMap<String, AnalyticsEvent>()
fun sendEventOnce(key: String, event: AnalyticsEvent) {
if (sentEvents.putIfAbsent(key, event) == null) {
analyticsEventHandler.send(event)
}
}
fun reset(key: String) {
sentEvents.remove(key)
}
}