Updated on 2026-08-14
This commit is contained in:
parent
b8f3d5315f
commit
54e094abac
8 changed files with 145 additions and 4 deletions
|
|
@ -187,6 +187,10 @@ sealed class AnalyticsParam {
|
|||
Pending(value = "Pending"),
|
||||
}
|
||||
|
||||
enum class EnsStatus(val value: String) {
|
||||
EMPTY("Empty"), FULL("Full")
|
||||
}
|
||||
|
||||
companion object Key {
|
||||
const val BLOCKCHAIN = "Blockchain"
|
||||
const val TOKEN_PARAM = "Token"
|
||||
|
|
@ -235,5 +239,7 @@ sealed class AnalyticsParam {
|
|||
const val SEND_BLOCKCHAIN = "Send Blockchain"
|
||||
const val RECEIVE_BLOCKCHAIN = "Receive Blockchain"
|
||||
const val CHOSEN_TOKEN = "Token Chosen"
|
||||
const val ENS = "ENS"
|
||||
const val ENS_ADDRESS = "ENS Address"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package com.tangem.domain.tokens.model.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.ENS
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
|
||||
|
||||
sealed class TokenReceiveNewAnalyticsEvent(
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
) : AnalyticsEvent("Token / Receive", event, params) {
|
||||
|
||||
class ReceiveScreenOpened(
|
||||
token: String,
|
||||
blockchainName: String,
|
||||
ensStatus: AnalyticsParam.EnsStatus,
|
||||
) : TokenReceiveNewAnalyticsEvent(
|
||||
event = "Receive Screen Opened",
|
||||
params = mapOf(
|
||||
TOKEN_PARAM to token,
|
||||
BLOCKCHAIN to blockchainName,
|
||||
ENS to ensStatus.value,
|
||||
),
|
||||
)
|
||||
|
||||
class ButtonCopyAddress(
|
||||
token: String,
|
||||
blockchainName: String,
|
||||
) : TokenReceiveNewAnalyticsEvent(
|
||||
event = "Button - Copy Address",
|
||||
params = mapOf(
|
||||
TOKEN_PARAM to token,
|
||||
BLOCKCHAIN to blockchainName,
|
||||
),
|
||||
)
|
||||
|
||||
class ButtonCopyEns(
|
||||
token: String,
|
||||
blockchainName: String,
|
||||
) : TokenReceiveNewAnalyticsEvent(
|
||||
event = "Button - ENS",
|
||||
params = mapOf(
|
||||
TOKEN_PARAM to token,
|
||||
BLOCKCHAIN to blockchainName,
|
||||
),
|
||||
)
|
||||
|
||||
class QrScreenOpened(
|
||||
token: String,
|
||||
blockchainName: String,
|
||||
) : TokenReceiveNewAnalyticsEvent(
|
||||
event = "QR Screen Opened",
|
||||
params = mapOf(
|
||||
TOKEN_PARAM to token,
|
||||
BLOCKCHAIN to blockchainName,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.send.v2.send.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.ENS_ADDRESS
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.FEE_TYPE
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.NONCE
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
|
||||
|
|
@ -23,6 +24,7 @@ internal sealed class SendAnalyticEvents(
|
|||
val feeType: AnalyticsParam.FeeType,
|
||||
val blockchain: String,
|
||||
val nonceNotEmpty: Boolean,
|
||||
private val ensStatus: AnalyticsParam.EnsStatus,
|
||||
) : SendAnalyticEvents(
|
||||
event = "Transaction Sent Screen Opened",
|
||||
params = mapOf(
|
||||
|
|
@ -30,6 +32,10 @@ internal sealed class SendAnalyticEvents(
|
|||
FEE_TYPE to feeType.value,
|
||||
BLOCKCHAIN to blockchain,
|
||||
NONCE to nonceNotEmpty.toString().capitalize(),
|
||||
ENS_ADDRESS to when (ensStatus) {
|
||||
AnalyticsParam.EnsStatus.EMPTY -> false.toString()
|
||||
AnalyticsParam.EnsStatus.FULL -> true.toString()
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ internal class SendAnalyticHelper @Inject constructor(
|
|||
feeType = feeType,
|
||||
blockchain = cryptoCurrency.network.name,
|
||||
nonceNotEmpty = feeSelectorUM.nonce != null,
|
||||
ensStatus = getEnsStatus(sendUM),
|
||||
),
|
||||
)
|
||||
analyticsEventHandler.send(
|
||||
|
|
@ -52,4 +53,14 @@ internal class SendAnalyticHelper @Inject constructor(
|
|||
else -> Basic.TransactionSent.MemoType.Null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getEnsStatus(sendUM: SendUM): AnalyticsParam.EnsStatus {
|
||||
val blockchainAddressForEns =
|
||||
(sendUM.destinationUM as? DestinationUM.Content)?.addressTextField?.blockchainAddress
|
||||
return if (blockchainAddressForEns != null) {
|
||||
AnalyticsParam.EnsStatus.FULL
|
||||
} else {
|
||||
AnalyticsParam.EnsStatus.EMPTY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -93,6 +93,7 @@ internal class DefaultTokenReceiveComponent @AssistedInject constructor(
|
|||
notificationConfigs = model.state.value.notificationConfigs,
|
||||
showMemoDisclaimer = model.params.config.showMemoDisclaimer,
|
||||
fullName = model.params.config.cryptoCurrency.network.name,
|
||||
tokenName = model.getTokenName(),
|
||||
),
|
||||
)
|
||||
TokenReceiveRoutes.Warning -> TokenReceiveWarningComponent(
|
||||
|
|
|
|||
|
|
@ -39,5 +39,6 @@ internal class TokenReceiveAssetsComponent(
|
|||
val onDismiss: () -> Unit,
|
||||
val showMemoDisclaimer: Boolean,
|
||||
val fullName: String,
|
||||
val tokenName: String,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,10 +1,14 @@
|
|||
package com.tangem.features.tokenreceive.model
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
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.tokens.model.analytics.TokenReceiveNewAnalyticsEvent
|
||||
import com.tangem.features.tokenreceive.component.TokenReceiveAssetsComponent
|
||||
import com.tangem.features.tokenreceive.entity.ReceiveAddress
|
||||
import com.tangem.features.tokenreceive.ui.state.ReceiveAssetsUM
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -16,10 +20,21 @@ import javax.inject.Inject
|
|||
internal class TokenReceiveAssetsModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
analyticsEventHandler: AnalyticsEventHandler,
|
||||
) : Model() {
|
||||
|
||||
private val params = paramsContainer.require<TokenReceiveAssetsComponent.TokenReceiveAssetsParams>()
|
||||
|
||||
init {
|
||||
analyticsEventHandler.send(
|
||||
TokenReceiveNewAnalyticsEvent.ReceiveScreenOpened(
|
||||
token = params.tokenName,
|
||||
blockchainName = params.fullName,
|
||||
ensStatus = configureEnsStatus(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
internal val state: StateFlow<ReceiveAssetsUM>
|
||||
field = MutableStateFlow<ReceiveAssetsUM>(
|
||||
ReceiveAssetsUM(
|
||||
|
|
@ -32,4 +47,13 @@ internal class TokenReceiveAssetsModel @Inject constructor(
|
|||
fullName = params.fullName,
|
||||
),
|
||||
)
|
||||
|
||||
private fun configureEnsStatus(): AnalyticsParam.EnsStatus {
|
||||
val hasEnsAddress = params.addresses.values.any { it.type == ReceiveAddress.Type.Ens }
|
||||
return if (hasEnsAddress) {
|
||||
AnalyticsParam.EnsStatus.FULL
|
||||
} else {
|
||||
AnalyticsParam.EnsStatus.EMPTY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.tokenreceive.model
|
|||
import com.arkivanov.decompose.router.stack.StackNavigation
|
||||
import com.arkivanov.decompose.router.stack.push
|
||||
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.models.ReceiveAddressModel
|
|||
import com.tangem.domain.models.ens.EnsAddress
|
||||
import com.tangem.domain.models.network.Network
|
||||
import com.tangem.domain.tokens.SaveViewedTokenReceiveWarningUseCase
|
||||
import com.tangem.domain.tokens.model.analytics.TokenReceiveNewAnalyticsEvent
|
||||
import com.tangem.domain.transaction.usecase.GetReverseResolvedEnsAddressUseCase
|
||||
import com.tangem.features.tokenreceive.TokenReceiveComponent
|
||||
import com.tangem.features.tokenreceive.component.TokenReceiveModelCallback
|
||||
|
|
@ -35,6 +37,7 @@ import kotlinx.coroutines.launch
|
|||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@ModelScoped
|
||||
internal class TokenReceiveModel @Inject constructor(
|
||||
private val clipboardManager: ClipboardManager,
|
||||
|
|
@ -43,6 +46,7 @@ internal class TokenReceiveModel @Inject constructor(
|
|||
private val saveViewedTokenReceiveWarningUseCase: SaveViewedTokenReceiveWarningUseCase,
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
) : Model(), TokenReceiveModelCallback {
|
||||
|
||||
private val iconStateConverter by lazy(::CryptoCurrencyToIconStateConverter)
|
||||
|
|
@ -61,11 +65,18 @@ internal class TokenReceiveModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onQrCodeClick(id: Int) {
|
||||
analyticsEventHandler.send(
|
||||
TokenReceiveNewAnalyticsEvent.QrScreenOpened(
|
||||
token = getTokenName(),
|
||||
blockchainName = params.config.cryptoCurrency.network.name,
|
||||
),
|
||||
)
|
||||
stackNavigation.push(configuration = TokenReceiveRoutes.QrCode(addressId = id))
|
||||
}
|
||||
|
||||
override fun onCopyClick(id: Int) {
|
||||
val addressToCopy = state.value.addresses[id] ?: return
|
||||
sendCopyActionAnalytic(addressToCopy)
|
||||
clipboardManager.setText(text = addressToCopy.value, isSensitive = true)
|
||||
}
|
||||
|
||||
|
|
@ -85,6 +96,13 @@ internal class TokenReceiveModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
internal fun getTokenName(): String {
|
||||
return when (val asset = params.config.asset) {
|
||||
Asset.Currency -> params.config.cryptoCurrency.symbol
|
||||
Asset.NFT -> asset.name
|
||||
}
|
||||
}
|
||||
|
||||
private fun mapAddresses(addresses: List<ReceiveAddressModel>): ImmutableMap<Int, ReceiveAddress> {
|
||||
return buildMap {
|
||||
addresses.mapIndexed { index, model ->
|
||||
|
|
@ -151,10 +169,7 @@ internal class TokenReceiveModel @Inject constructor(
|
|||
title = resourceReference(
|
||||
R.string.receive_bottom_sheet_warning_title,
|
||||
wrappedList(
|
||||
when (val asset = params.config.asset) {
|
||||
Asset.Currency -> params.config.cryptoCurrency.symbol
|
||||
Asset.NFT -> asset.name
|
||||
},
|
||||
getTokenName(),
|
||||
params.config.cryptoCurrency.network.name,
|
||||
),
|
||||
),
|
||||
|
|
@ -183,4 +198,22 @@ internal class TokenReceiveModel @Inject constructor(
|
|||
notificationConfigs = getNotifications().toImmutableList(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun sendCopyActionAnalytic(receiveAddress: ReceiveAddress) {
|
||||
val event = when (receiveAddress.type) {
|
||||
is ReceiveAddress.Type.Default -> {
|
||||
TokenReceiveNewAnalyticsEvent.ButtonCopyAddress(
|
||||
token = getTokenName(),
|
||||
blockchainName = params.config.cryptoCurrency.network.name,
|
||||
)
|
||||
}
|
||||
ReceiveAddress.Type.Ens -> {
|
||||
TokenReceiveNewAnalyticsEvent.ButtonCopyEns(
|
||||
token = getTokenName(),
|
||||
blockchainName = params.config.cryptoCurrency.network.name,
|
||||
)
|
||||
}
|
||||
}
|
||||
analyticsEventHandler.send(event)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue