diff --git a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt index 6667534f25..8eed0785bc 100644 --- a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt +++ b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/AnalyticsParam.kt @@ -223,5 +223,6 @@ sealed class AnalyticsParam { const val NONCE = "Nonce" const val STANDARD = "Standard" const val NO_COLLECTION = "No collection" + const val EMULATION_STATUS = "Emulation Status" } } \ No newline at end of file diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt index af4f00d088..73dc766bbb 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/sign/WcSignUseCaseDelegate.kt @@ -41,12 +41,6 @@ internal class WcSignUseCaseDelegate( operator fun invoke(initModel: SignModel) = channelFlow { val state = MutableStateFlow(WcSignState(initModel, WcSignStep.PreSign)) - analytics.send( - WcAnalyticEvents.SignatureRequestReceived( - rawRequest = context.rawSdkRequest, - network = context.network, - ), - ) state .onEach { newState -> channel.send(newState) } diff --git a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcAnalyticEvents.kt b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcAnalyticEvents.kt index fa4b050106..d4bff77def 100644 --- a/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcAnalyticEvents.kt +++ b/domain/wallet-connect/src/main/kotlin/com/tangem/domain/walletconnect/WcAnalyticEvents.kt @@ -87,11 +87,11 @@ sealed class WcAnalyticEvents( ), ) - class SignatureRequestReceived( + class TransactionDetailsOpened( rawRequest: WcSdkSessionRequest, network: Network, ) : WcAnalyticEvents( - event = "Signature Request Received", + event = "Transaction Details Opened", params = mapOf( AnalyticsParam.Key.DAPP_NAME to rawRequest.dAppMetaData.name, AnalyticsParam.Key.DAPP_URL to rawRequest.dAppMetaData.url, @@ -100,6 +100,27 @@ sealed class WcAnalyticEvents( ), ) + class SignatureRequestReceived( + rawRequest: WcSdkSessionRequest, + network: Network, + emulationStatus: EmulationStatus, + ) : WcAnalyticEvents( + event = "Signature Request Received", + params = mapOf( + AnalyticsParam.Key.DAPP_NAME to rawRequest.dAppMetaData.name, + AnalyticsParam.Key.DAPP_URL to rawRequest.dAppMetaData.url, + AnalyticsParam.Key.METHOD_NAME to rawRequest.request.method, + AnalyticsParam.Key.BLOCKCHAIN to network.name, + AnalyticsParam.Key.EMULATION_STATUS to emulationStatus.status, + ), + ) { + enum class EmulationStatus(val status: String) { + Emulated("Emulated"), + Error("Error"), + CanNotEmulate("Can't emulate"), + } + } + class SignatureRequestHandled( rawRequest: WcSdkSessionRequest, network: Network, diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt index dc8aa4bc23..1684d836c3 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcAddNetworkModel.kt @@ -3,12 +3,14 @@ package com.tangem.features.walletconnect.transaction.model import androidx.compose.runtime.Stable import com.arkivanov.decompose.router.stack.StackNavigation import com.arkivanov.decompose.router.stack.pushNew +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.decompose.navigation.Router import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.clipboard.ClipboardManager +import com.tangem.domain.walletconnect.WcAnalyticEvents import com.tangem.domain.walletconnect.WcRequestUseCaseFactory import com.tangem.domain.walletconnect.usecase.method.WcAddNetworkUseCase import com.tangem.features.walletconnect.transaction.components.common.WcTransactionModelParams @@ -24,6 +26,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject +import kotlin.properties.Delegates @Suppress("LongParameterList") @Stable @@ -34,6 +37,7 @@ internal class WcAddNetworkModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val router: Router, private val clipboardManager: ClipboardManager, + private val analytics: AnalyticsEventHandler, private val useCaseFactory: WcRequestUseCaseFactory, private val wcAddEthereumChainUMConverter: WcAddEthereumChainUMConverter, ) : Model(), WcCommonTransactionModel { @@ -44,10 +48,11 @@ internal class WcAddNetworkModel @Inject constructor( val stackNavigation = StackNavigation() private val params = paramsContainer.require() + private var useCase by Delegates.notNull() init { modelScope.launch { - val useCase: WcAddNetworkUseCase = useCaseFactory.createUseCase(params.rawRequest) + useCase = useCaseFactory.createUseCase(params.rawRequest) .onLeft { router.push(WcHandleMethodErrorConverter.convert(it)) } .getOrNull() ?: return@launch _uiState.emit( @@ -75,6 +80,12 @@ internal class WcAddNetworkModel @Inject constructor( } fun showTransactionRequest() { + analytics.send( + WcAnalyticEvents.TransactionDetailsOpened( + rawRequest = useCase.rawSdkRequest, + network = useCase.network, + ), + ) stackNavigation.pushNew(WcTransactionRoutes.TransactionRequestInfo) } diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt index b86107b35c..1494a6161a 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSendTransactionModel.kt @@ -5,6 +5,7 @@ import arrow.core.Either import com.arkivanov.decompose.router.stack.StackNavigation import com.arkivanov.decompose.router.stack.pop import com.arkivanov.decompose.router.stack.pushNew +import com.domain.blockaid.models.transaction.SimulationResult import com.domain.blockaid.models.transaction.ValidationResult import com.tangem.blockchain.common.TransactionData import com.tangem.blockchain.common.transaction.TransactionFee @@ -27,6 +28,7 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.transaction.error.GetFeeError import com.tangem.domain.transaction.usecase.GetFeeUseCase import com.tangem.domain.walletconnect.WcAnalyticEvents +import com.tangem.domain.walletconnect.WcAnalyticEvents.SignatureRequestReceived.EmulationStatus import com.tangem.domain.walletconnect.WcRequestUseCaseFactory import com.tangem.domain.walletconnect.model.WcRequestError import com.tangem.domain.walletconnect.model.WcRequestError.Companion.message @@ -121,6 +123,8 @@ internal class WcSendTransactionModel @Inject constructor( .collectLatest { (signState, securityCheck) -> if (signingIsDone(signState, useCase)) return@collectLatest + sendSignatureReceivedAnalytics(useCase, securityCheck) + this@WcSendTransactionModel.signState = signState val isSecurityCheckContent = securityCheck is Lce.Content val isApprovalMethod = isSecurityCheckContent && @@ -257,6 +261,12 @@ internal class WcSendTransactionModel @Inject constructor( } fun showTransactionRequest() { + analytics.send( + WcAnalyticEvents.TransactionDetailsOpened( + rawRequest = useCase.rawSdkRequest, + network = useCase.network, + ), + ) stackNavigation.pushNew(WcTransactionRoutes.TransactionRequestInfo) } @@ -358,4 +368,26 @@ internal class WcSendTransactionModel @Inject constructor( private fun copyData(text: String) { clipboardManager.setText(text = text, isSensitive = true) } + + private fun sendSignatureReceivedAnalytics( + useCase: WcSignUseCase<*>, + securityCheck: Lce, + ) { + val emulationStatus = when (securityCheck) { + is Lce.Content -> when (securityCheck.content.result.simulation) { + SimulationResult.FailedToSimulate -> EmulationStatus.CanNotEmulate + is SimulationResult.Success -> EmulationStatus.Emulated + } + is Lce.Error -> EmulationStatus.Error + is Lce.Loading -> return + } + + analytics.send( + WcAnalyticEvents.SignatureRequestReceived( + rawRequest = useCase.rawSdkRequest, + network = useCase.network, + emulationStatus = emulationStatus, + ), + ) + } } \ No newline at end of file diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt index cdcb80f9f4..1283f3e84f 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/transaction/model/WcSignTransactionModel.kt @@ -4,12 +4,14 @@ import androidx.compose.runtime.Stable import com.arkivanov.decompose.router.stack.StackNavigation import com.arkivanov.decompose.router.stack.pop import com.arkivanov.decompose.router.stack.pushNew +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.decompose.navigation.Router import com.tangem.core.decompose.ui.UiMessageSender import com.tangem.core.ui.clipboard.ClipboardManager +import com.tangem.domain.walletconnect.WcAnalyticEvents import com.tangem.domain.walletconnect.WcRequestUseCaseFactory import com.tangem.domain.walletconnect.model.WcEthMethod import com.tangem.domain.walletconnect.model.WcSolanaMethod @@ -32,6 +34,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import javax.inject.Inject +import kotlin.properties.Delegates @Suppress("LongParameterList") @Stable @@ -42,6 +45,7 @@ internal class WcSignTransactionModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val router: Router, private val clipboardManager: ClipboardManager, + private val analytics: AnalyticsEventHandler, private val useCaseFactory: WcRequestUseCaseFactory, private val signTypedDataUMConverter: WcSignTypedDataUMConverter, private val signTransactionUMConverter: WcSignTransactionUMConverter, @@ -54,9 +58,11 @@ internal class WcSignTransactionModel @Inject constructor( val stackNavigation = StackNavigation() + private var useCase by Delegates.notNull() + init { modelScope.launch { - val useCase = useCaseFactory.createUseCase(params.rawRequest) + useCase = useCaseFactory.createUseCase(params.rawRequest) .onLeft { router.push(WcHandleMethodErrorConverter.convert(it)) } .getOrNull() ?: return@launch useCase.invoke() @@ -109,6 +115,12 @@ internal class WcSignTransactionModel @Inject constructor( } fun showTransactionRequest() { + analytics.send( + WcAnalyticEvents.TransactionDetailsOpened( + rawRequest = useCase.rawSdkRequest, + network = useCase.network, + ), + ) stackNavigation.pushNew(WcTransactionRoutes.TransactionRequestInfo) }