From 2938fda36e7989478863f28ab732ab8acb138b43 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 4 Feb 2026 12:09:36 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../core/analytics/models/AnalyticsParam.kt | 1 + .../sign/WcSignUseCaseDelegate.kt | 2 + .../tangem/domain/models/account/Account.kt | 8 ++- .../domain/walletconnect/WcAnalyticEvents.kt | 70 +++++++++---------- .../analytics/CustomTokenAnalyticsEvent.kt | 2 +- .../analytics/SendWithSwapAnalyticEvents.kt | 18 ++--- .../confirm/model/SendWithSwapConfirmModel.kt | 2 + .../feature/swap/analytics/SwapEvents.kt | 21 +++--- .../connections/model/WcPairModel.kt | 17 ++--- .../transaction/model/WcAddNetworkModel.kt | 3 +- .../model/WcSendTransactionModel.kt | 3 + .../model/WcSignTransactionModel.kt | 3 + 12 files changed, 83 insertions(+), 67 deletions(-) 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 8fead6f8ae..986d808190 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 @@ -285,5 +285,6 @@ sealed class AnalyticsParam { const val ENS_ADDRESS = "ENS Address" const val ACCOUNT_DERIVATION_FROM = "Account Derivation (from)" const val FEE_TOKEN = "Fee Token" + const val ACCOUNT_DERIVATION = "Account Derivation" } } \ 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 c360f8af34..346ba94376 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 @@ -5,6 +5,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.data.walletconnect.sign.SignStateConverter.toPreSign import com.tangem.data.walletconnect.sign.SignStateConverter.toResult import com.tangem.data.walletconnect.sign.SignStateConverter.toSigning +import com.tangem.domain.models.account.derivationIndex import com.tangem.domain.walletconnect.WcAnalyticEvents import com.tangem.domain.walletconnect.model.WcRequestError import com.tangem.domain.walletconnect.model.WcRequestError.Companion.code @@ -71,6 +72,7 @@ internal class WcSignUseCaseDelegate( network = context.network, errorCode = error.code(), errorMessage = errorMessage, + accountDerivation = context.session.account?.derivationIndex?.value, ) analytics.send(event) } diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/account/Account.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/account/Account.kt index af4f1fd430..851c25e463 100644 --- a/domain/models/src/main/kotlin/com/tangem/domain/models/account/Account.kt +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/account/Account.kt @@ -185,4 +185,10 @@ sealed interface Account { error("Not yet implemented") } } -} \ No newline at end of file +} + +val Account.derivationIndex: DerivationIndex? + get() = when (this) { + is Account.CryptoPortfolio -> derivationIndex + is Account.Payment -> TODO("[REDACTED_JIRA]") + } \ No newline at end of file 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 0824032547..d9f540cefb 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 @@ -34,8 +34,17 @@ sealed class WcAnalyticEvents( ), ) - class PairButtonConnect : WcAnalyticEvents( + class PairButtonConnect( + dAppName: String, + accountDerivation: Int?, + ) : WcAnalyticEvents( event = "Button - Connect", + params = buildMap { + put(AnalyticsParam.DAPP_NAME, dAppName) + accountDerivation?.let { + put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) + } + }, ) class PairRequested( @@ -114,6 +123,7 @@ sealed class WcAnalyticEvents( rawRequest: WcSdkSessionRequest, network: Network, emulationStatus: EmulationStatus?, + accountDerivation: Int?, securityStatus: CheckDAppResult, ) : WcAnalyticEvents( event = "Signature Request Received", @@ -124,6 +134,7 @@ sealed class WcAnalyticEvents( AnalyticsParam.BLOCKCHAIN to network.name, AnalyticsParam.EMULATION_STATUS to emulationStatus?.status, AnalyticsParam.TYPE to securityStatus.toAnalyticVerificationStatus(), + AnalyticsParam.ACCOUNT_DERIVATION to accountDerivation?.toString(), ).mapNotNullValues { it.value }, ) { enum class EmulationStatus(val status: String) { @@ -137,15 +148,19 @@ sealed class WcAnalyticEvents( rawRequest: WcSdkSessionRequest, network: Network, securityStatus: CheckDAppResult, + accountDerivation: Int?, ) : WcAnalyticEvents( event = "Signature Request Handled", - params = mapOf( - AnalyticsParam.DAPP_NAME to rawRequest.dAppMetaData.name, - AnalyticsParam.DAPP_URL to rawRequest.dAppMetaData.url, - AnalyticsParam.METHOD_NAME to rawRequest.request.method, - AnalyticsParam.BLOCKCHAIN to network.name, - AnalyticsParam.TYPE to securityStatus.toAnalyticVerificationStatus(), - ), + params = buildMap { + put(AnalyticsParam.DAPP_NAME, rawRequest.dAppMetaData.name) + put(AnalyticsParam.DAPP_URL, rawRequest.dAppMetaData.url) + put(AnalyticsParam.METHOD_NAME, rawRequest.request.method) + put(AnalyticsParam.BLOCKCHAIN, network.name) + put(AnalyticsParam.TYPE, securityStatus.toAnalyticVerificationStatus()) + accountDerivation?.let { + put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) + } + }, ), AppsFlyerIncludedEvent class SignatureRequestFailed( @@ -153,16 +168,18 @@ sealed class WcAnalyticEvents( network: Network, errorCode: String, errorMessage: String, + accountDerivation: Int?, ) : WcAnalyticEvents( event = "Signature Request Failed", - params = mapOf( - AnalyticsParam.DAPP_NAME to rawRequest.dAppMetaData.name, - AnalyticsParam.DAPP_URL to rawRequest.dAppMetaData.url, - AnalyticsParam.METHOD_NAME to rawRequest.request.method, - AnalyticsParam.BLOCKCHAIN to network.name, - AnalyticsParam.ERROR_CODE to errorCode, - AnalyticsParam.ERROR_DESCRIPTION to errorMessage, - ), + params = buildMap { + put(AnalyticsParam.DAPP_NAME, rawRequest.dAppMetaData.name) + put(AnalyticsParam.DAPP_URL, rawRequest.dAppMetaData.url) + put(AnalyticsParam.METHOD_NAME, rawRequest.request.method) + put(AnalyticsParam.BLOCKCHAIN, network.name) + put(AnalyticsParam.ERROR_CODE, errorCode) + put(AnalyticsParam.ERROR_DESCRIPTION, errorMessage) + accountDerivation?.let { put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) } + }, ) class SignatureRequestReceivedFailed( @@ -279,23 +296,4 @@ fun CheckDAppResult.toAnalyticVerificationStatus(): String = when (this) { SAFE -> DAppVerificationStatus.Verified UNSAFE -> DAppVerificationStatus.Risky FAILED_TO_VERIFY -> DAppVerificationStatus.Unknown -}.status - -sealed class WcAnalyticAccountEvents( - event: String, - params: Map = emptyMap(), -) : AnalyticsEvent(category = WC_CATEGORY_ACCOUNT_NAME, event = event, params = params) { - - data class PairButtonConnect( - private val accountDerivation: Int, - ) : WcAnalyticAccountEvents( - event = "Button - Connect", - params = mapOf( - "Account Derivation" to accountDerivation.toString(), - ), - ) - - companion object { - const val WC_CATEGORY_ACCOUNT_NAME = "WalletConnect / Account" - } -} \ No newline at end of file +}.status \ No newline at end of file diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/analytics/CustomTokenAnalyticsEvent.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/analytics/CustomTokenAnalyticsEvent.kt index c3a41d047c..03cab5fb6d 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/analytics/CustomTokenAnalyticsEvent.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/analytics/CustomTokenAnalyticsEvent.kt @@ -8,7 +8,7 @@ internal sealed class CustomTokenAnalyticsEvent( event: String, params: Map = mapOf(), ) : AnalyticsEvent( - category = "Manage Tokens / Custom", + category = "Manage Tokens / Custom Token", event = event, params = params, ) { diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/analytics/SendWithSwapAnalyticEvents.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/analytics/SendWithSwapAnalyticEvents.kt index 8f48f4568b..8aca31698c 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/analytics/SendWithSwapAnalyticEvents.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/analytics/SendWithSwapAnalyticEvents.kt @@ -22,16 +22,18 @@ internal sealed class SendWithSwapAnalyticEvents( val feeType: AnalyticsParam.FeeType, val fromToken: CryptoCurrency, val toToken: CryptoCurrency, + val fromDerivationIndex: Int?, ) : SendWithSwapAnalyticEvents( event = "Send With Swap In Progress Screen Opened", - params = mapOf( - PROVIDER to providerName, - FEE_TYPE to if (feeType is AnalyticsParam.FeeType.Normal) "Market" else "Fast", - SEND_TOKEN to fromToken.symbol, - RECEIVE_TOKEN to toToken.symbol, - SEND_BLOCKCHAIN to fromToken.network.name, - RECEIVE_BLOCKCHAIN to toToken.network.name, - ), + params = buildMap { + put(PROVIDER, providerName) + put(FEE_TYPE, if (feeType is AnalyticsParam.FeeType.Normal) "Market" else "Fast") + put(SEND_TOKEN, fromToken.symbol) + put(RECEIVE_TOKEN, toToken.symbol) + put(SEND_BLOCKCHAIN, fromToken.network.name) + put(RECEIVE_BLOCKCHAIN, toToken.network.name) + if (fromDerivationIndex != null) put("Account Derivation (from)", fromDerivationIndex.toString()) + }, ), AppsFlyerIncludedEvent data class NoticeCanNotSwapToken( diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt index 97a3d13b93..2923283a79 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/confirm/model/SendWithSwapConfirmModel.kt @@ -448,6 +448,7 @@ internal class SendWithSwapConfirmModel @Inject constructor( val toCurrency = confirmData.toCryptoCurrencyStatus?.currency ?: return val feeSelectorUM = uiState.value.feeSelectorUM as? FeeSelectorUM.Content ?: return val feeType = feeSelectorUM.toAnalyticType() + val fromDerivationIndex = confirmData.fromAccount?.derivationIndex?.value analyticsEventHandler.send( SendWithSwapAnalyticEvents.TransactionScreenOpened( @@ -455,6 +456,7 @@ internal class SendWithSwapConfirmModel @Inject constructor( feeType = feeType, fromToken = fromCurrency, toToken = toCurrency, + fromDerivationIndex = fromDerivationIndex, ), ) analyticsEventHandler.send( diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/SwapEvents.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/SwapEvents.kt index a2b2f3ea67..408988e88e 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/SwapEvents.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/analytics/SwapEvents.kt @@ -98,16 +98,17 @@ sealed class SwapEvents( val toDerivationIndex: Int?, ) : SwapEvents( event = "Swap in Progress Screen Opened", - params = mapOf( - "Provider" to provider.name, - "Commission" to if (commission == FeeType.NORMAL) "Market" else "Fast", - "Send Token" to sendToken, - "Receive Token" to receiveToken, - "Send Blockchain" to sendBlockchain, - "Receive Blockchain" to receiveBlockchain, - "Account Derivation From or To (optional)" to "$fromDerivationIndex, $toDerivationIndex", - FEE_TOKEN to feeToken, - ), + params = buildMap { + put("Provider", provider.name) + put("Commission", if (commission == FeeType.NORMAL) "Market" else "Fast") + put("Send Token", sendToken) + put("Receive Token", receiveToken) + put("Send Blockchain", sendBlockchain) + put("Receive Blockchain", receiveBlockchain) + if (fromDerivationIndex != null) put("Account Derivation (from)", fromDerivationIndex.toString()) + if (toDerivationIndex != null) put("Account Derivation (to)", toDerivationIndex.toString()) + put(FEE_TOKEN, feeToken) + }, ), AppsFlyerIncludedEvent class ProviderClicked : SwapEvents("Provider Clicked") diff --git a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt index 285229cc87..f9fefde39c 100644 --- a/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt +++ b/features/walletconnect/impl/src/main/kotlin/com/tangem/features/walletconnect/connections/model/WcPairModel.kt @@ -27,12 +27,12 @@ import com.tangem.domain.account.supplier.SingleAccountListSupplier import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.models.account.Account import com.tangem.domain.models.account.AccountStatus +import com.tangem.domain.models.account.derivationIndex import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.models.wallet.isLocked import com.tangem.domain.models.wallet.isMultiCurrency -import com.tangem.domain.walletconnect.WcAnalyticAccountEvents import com.tangem.domain.walletconnect.WcAnalyticEvents import com.tangem.domain.walletconnect.model.WcPairError import com.tangem.domain.walletconnect.model.WcPairError.Unknown @@ -324,15 +324,12 @@ internal class WcPairModel @Inject constructor( val account = selectedPortfolio?.second?.account modelScope.launch { - if (selectorController.isAccountModeSync() && account != null) { - val derivationIndex = when (account) { - is Account.CryptoPortfolio -> account.derivationIndex.value - is Account.Payment -> TODO("[REDACTED_JIRA]") - } - analytics.send(WcAnalyticAccountEvents.PairButtonConnect(derivationIndex)) - } else { - analytics.send(WcAnalyticEvents.PairButtonConnect()) - } + analytics.send( + WcAnalyticEvents.PairButtonConnect( + dAppName = sessionProposal.dAppMetaData.name, + accountDerivation = account?.derivationIndex?.value, + ), + ) } wcPairUseCase.approve( WcSessionApprove( 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 8ed61a1b5d..7f74dc7dca 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 @@ -11,6 +11,7 @@ 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.models.account.derivationIndex import com.tangem.domain.walletconnect.WcAnalyticEvents import com.tangem.domain.walletconnect.WcRequestUseCaseFactory import com.tangem.domain.walletconnect.usecase.method.WcAddNetworkUseCase @@ -131,13 +132,13 @@ internal class WcAddNetworkModel @Inject constructor( private fun sendSignatureReceivedAnalytics(useCase: WcAddNetworkUseCase) { if (signatureReceivedAnalyticsSendState.value) return - analytics.send( WcAnalyticEvents.SignatureRequestReceived( rawRequest = useCase.rawSdkRequest, network = useCase.network, emulationStatus = null, securityStatus = CheckDAppResult.FAILED_TO_VERIFY, + accountDerivation = useCase.session.account?.derivationIndex?.value, ), ) 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 f02eb11f51..9eaceb4978 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 @@ -23,6 +23,7 @@ import com.tangem.core.ui.components.bottomsheets.message.MessageBottomSheetUMV2 import com.tangem.core.ui.extensions.resourceReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.domain.core.lce.Lce +import com.tangem.domain.models.account.derivationIndex import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.network.Network import com.tangem.domain.models.wallet.UserWallet @@ -426,6 +427,7 @@ internal class WcSendTransactionModel @Inject constructor( rawRequest = useCase.rawSdkRequest, network = useCase.network, securityStatus = securityStatusState.value.toCheckDAppResult(), + accountDerivation = useCase.session.account?.derivationIndex?.value, ) analytics.send(event) showSuccessSignMessage() @@ -465,6 +467,7 @@ internal class WcSendTransactionModel @Inject constructor( network = useCase.network, emulationStatus = emulationStatus, securityStatus = securityCheck.toCheckDAppResult(), + accountDerivation = useCase.session.account?.derivationIndex?.value, ), ) 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 88852cdbbc..1e97be37f4 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 @@ -12,6 +12,7 @@ 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.models.account.derivationIndex import com.tangem.domain.walletconnect.WcAnalyticEvents import com.tangem.domain.walletconnect.WcRequestUseCaseFactory import com.tangem.domain.walletconnect.model.WcEthMethod @@ -143,6 +144,7 @@ internal class WcSignTransactionModel @Inject constructor( rawRequest = useCase.rawSdkRequest, network = useCase.network, securityStatus = CheckDAppResult.FAILED_TO_VERIFY, + accountDerivation = useCase.session.account?.derivationIndex?.value, ) analytics.send(event) showSuccessSignMessage() @@ -171,6 +173,7 @@ internal class WcSignTransactionModel @Inject constructor( network = useCase.network, emulationStatus = null, securityStatus = CheckDAppResult.FAILED_TO_VERIFY, + accountDerivation = useCase.session.account?.derivationIndex?.value, ), )