Updated on 2026-08-14
This commit is contained in:
commit
45156f05b0
1184 changed files with 47887 additions and 11982 deletions
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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) }
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue