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 8ea55f5139..9488b9c840 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 @@ -266,5 +266,6 @@ sealed class AnalyticsParam { const val CHOSEN_TOKEN = "Token Chosen" const val ENS = "ENS" const val ENS_ADDRESS = "ENS Address" + const val ACCOUNT_DERIVATION_FROM = "Account Derivation (from)" } } \ No newline at end of file diff --git a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/MainScreenAnalyticsEvent.kt b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/MainScreenAnalyticsEvent.kt index a1a2ef6911..b511dd504e 100644 --- a/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/MainScreenAnalyticsEvent.kt +++ b/core/analytics/models/src/main/java/com/tangem/core/analytics/models/event/MainScreenAnalyticsEvent.kt @@ -56,6 +56,14 @@ sealed class MainScreenAnalyticsEvent( event = "Button - Explore", ) + class AccountShowTokens : MainScreenAnalyticsEvent( + event = "Button - Account Show Tokens", + ) + + class AccountHideTokens : MainScreenAnalyticsEvent( + event = "Button - Account Hide Tokens", + ) + data class ButtonSwap(val status: AnalyticsParam.Status) : MainScreenAnalyticsEvent( event = "Button - Swap", params = mapOf(AnalyticsParam.STATUS to status.value), diff --git a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt index 6e6396e89a..f07bf2bd9d 100644 --- a/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt +++ b/data/wallet-connect/src/main/kotlin/com/tangem/data/walletconnect/pair/DefaultWcPairUseCase.kt @@ -166,7 +166,6 @@ internal class DefaultWcPairUseCase @AssistedInject constructor( } override fun approve(sessionForApprove: WcSessionApprove) { - analytics.send(WcAnalyticEvents.PairButtonConnect()) onCallTerminalAction.trySend(TerminalAction.Approve(sessionForApprove)) } diff --git a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt index 5c0c30da0d..41a0965407 100644 --- a/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt +++ b/domain/tokens/models/src/main/java/com/tangem/domain/tokens/model/analytics/TokenScreenAnalyticsEvent.kt @@ -1,6 +1,7 @@ package com.tangem.domain.tokens.model.analytics import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.core.analytics.models.AnalyticsParam.Key.ACCOUNT_DERIVATION_FROM import com.tangem.core.analytics.models.AnalyticsParam.Key.ACTION import com.tangem.core.analytics.models.AnalyticsParam.Key.BALANCE import com.tangem.core.analytics.models.AnalyticsParam.Key.BLOCKCHAIN @@ -58,12 +59,14 @@ sealed class TokenScreenAnalyticsEvent( token: String, blockchain: String, status: String?, + derivationIndex: Int? = null, ) : TokenScreenAnalyticsEvent( event = event, params = buildMap { put(TOKEN_PARAM, token) put(BLOCKCHAIN, blockchain) status?.let { put(STATUS, it) } + derivationIndex?.let { put(ACCOUNT_DERIVATION_FROM, it.toString()) } }, ) { @@ -71,11 +74,13 @@ sealed class TokenScreenAnalyticsEvent( token: String, blockchain: String, status: String?, + derivationIndex: Int? = null, ) : ButtonWithParams( event = "Button - Buy", token = token, status = status, blockchain = blockchain, + derivationIndex = derivationIndex, ) class ButtonSell( @@ -93,22 +98,26 @@ sealed class TokenScreenAnalyticsEvent( token: String, status: String, blockchain: String, + derivationIndex: Int? = null, ) : ButtonWithParams( event = "Button - Exchange", token = token, status = status, blockchain = blockchain, + derivationIndex = derivationIndex, ) class ButtonSend( token: String, status: String, blockchain: String, + derivationIndex: Int? = null, ) : ButtonWithParams( event = "Button - Send", token = token, status = status, blockchain = blockchain, + derivationIndex = derivationIndex, ) class ButtonReceive( 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 6a0ac90cb8..aba74660de 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 @@ -277,4 +277,23 @@ fun CheckDAppResult.toAnalyticVerificationStatus(): String = when (this) { SAFE -> DAppVerificationStatus.Verified UNSAFE -> DAppVerificationStatus.Risky FAILED_TO_VERIFY -> DAppVerificationStatus.Unknown -}.status \ No newline at end of file +}.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 diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/analytics/WalletSettingsAnalyticEvents.kt b/domain/wallets/src/main/java/com/tangem/domain/wallets/analytics/WalletSettingsAnalyticEvents.kt index 93d7d9b6e1..1c23c85475 100644 --- a/domain/wallets/src/main/java/com/tangem/domain/wallets/analytics/WalletSettingsAnalyticEvents.kt +++ b/domain/wallets/src/main/java/com/tangem/domain/wallets/analytics/WalletSettingsAnalyticEvents.kt @@ -16,14 +16,35 @@ sealed class WalletSettingsAnalyticEvents( params = mapOf(STATUS to enabled.value), ) - class WalletSettingsScreenOpened : WalletSettingsAnalyticEvents( + class WalletSettingsScreenOpened( + private val accountsCount: Int?, + ) : WalletSettingsAnalyticEvents( event = "Wallet Settings Screen Opened", + params = buildMap { + if (accountsCount != null) put("Accounts Count", accountsCount.toString()) + }, ) class ButtonBackup : WalletSettingsAnalyticEvents( event = "Button - Backup", ) + class ButtonAddAccount : WalletSettingsAnalyticEvents( + event = "Button - Add Account", + ) + + class ButtonOpenExistingAccount : WalletSettingsAnalyticEvents( + event = "Button - Open Existing Account", + ) + + class ButtonArchivedAccounts : WalletSettingsAnalyticEvents( + event = "Button - Archived Accounts", + ) + + class LongtapAccountsOrder : WalletSettingsAnalyticEvents( + event = "Longtap - Accounts Order", + ) + data class ButtonAccessCode( private val isCodeSet: Boolean, ) : WalletSettingsAnalyticEvents( diff --git a/features/account/api/src/main/java/com/tangem/features/account/PortfolioSelectorComponent.kt b/features/account/api/src/main/java/com/tangem/features/account/PortfolioSelectorComponent.kt index 0b98d6b218..50c01a8d05 100644 --- a/features/account/api/src/main/java/com/tangem/features/account/PortfolioSelectorComponent.kt +++ b/features/account/api/src/main/java/com/tangem/features/account/PortfolioSelectorComponent.kt @@ -57,6 +57,7 @@ interface PortfolioSelectorController { * combine and update with your Feature data and [PortfolioFetcher.data] */ val isEnabled: MutableStateFlow<(UserWallet, AccountStatus) -> Boolean> + suspend fun isAccountModeSync(): Boolean fun selectAccount(accountId: AccountId?) fun selectedAccountWithData(portfolioFetcher: PortfolioFetcher): Flow?> diff --git a/features/account/impl/src/main/java/com/tangem/features/account/analytics/AccountSettingsAnalyticEvents.kt b/features/account/impl/src/main/java/com/tangem/features/account/analytics/AccountSettingsAnalyticEvents.kt new file mode 100644 index 0000000000..dc8afe9786 --- /dev/null +++ b/features/account/impl/src/main/java/com/tangem/features/account/analytics/AccountSettingsAnalyticEvents.kt @@ -0,0 +1,100 @@ +package com.tangem.features.account.analytics + +import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.domain.models.account.AccountName +import com.tangem.domain.models.account.CryptoPortfolioIcon +import com.tangem.features.account.AccountCreateEditComponent + +sealed class AccountSettingsAnalyticEvents( + category: String = "Settings / Account", + event: String, + params: Map = emptyMap(), +) : AnalyticsEvent(category, event, params) { + + class AccountSettingsScreenOpened : AccountSettingsAnalyticEvents( + event = "Account Settings Screen Opened", + ) + + class ButtonManageTokens : AccountSettingsAnalyticEvents( + event = "Button - Manage Tokens", + ) + + class ButtonArchiveAccount : AccountSettingsAnalyticEvents( + event = "Button - Archive Account", + ) + + class ButtonArchiveAccountConfirmation : AccountSettingsAnalyticEvents( + event = "Button - Archive Account Confirmation", + ) + + class ButtonCancelAccountArchivation : AccountSettingsAnalyticEvents( + event = "Button - Cancel Account Archivation", + ) + + class AccountArchived : AccountSettingsAnalyticEvents( + event = "Account Archived", + ) + + class ButtonEdit : AccountSettingsAnalyticEvents( + event = "Button - Edit", + ) + + class AccountEditScreenOpened : AccountSettingsAnalyticEvents( + event = "Account Edit Screen Opened", + ) + + class ButtonSave( + val name: AccountName, + val icon: CryptoPortfolioIcon, + ) : AccountSettingsAnalyticEvents( + event = "Button - Save", + params = buildMap { + val accountName = when (name) { + is AccountName.Custom -> name.value + AccountName.DefaultMain -> "DefaultMain" + } + put("Name", accountName) + put("Color", icon.color.name) + put("Icon", icon.value.name) + }, + ) + + class ButtonAddNewAccount( + val name: AccountName, + val icon: CryptoPortfolioIcon, + val derivationIndex: Int, + ) : AccountSettingsAnalyticEvents( + event = "Button - Add New Account", + params = buildMap { + val accountName = when (name) { + is AccountName.Custom -> name.value + AccountName.DefaultMain -> "DefaultMain" + } + put("Name", accountName) + put("Color", icon.color.name) + put("Icon", icon.value.name) + put("Derivation", derivationIndex.toString()) + }, + ) + + class AccountError( + val source: Source, + val error: String, + ) : AccountSettingsAnalyticEvents( + event = "Account Error", + params = buildMap { + put("Error", error) + }, + ) + + enum class Source(val value: String) { + NEW_ACCOUNT("New Account"), EDIT("Edit"), ARCHIVE("Archive") + } + + companion object { + fun AccountCreateEditComponent.Params.toAnalyticSource() = when (this) { + is AccountCreateEditComponent.Params.Create -> Source.NEW_ACCOUNT + is AccountCreateEditComponent.Params.Edit -> Source.EDIT + } + } +} \ No newline at end of file diff --git a/features/account/impl/src/main/java/com/tangem/features/account/analytics/WalletSettingsAccountAnalyticEvents.kt b/features/account/impl/src/main/java/com/tangem/features/account/analytics/WalletSettingsAccountAnalyticEvents.kt new file mode 100644 index 0000000000..165fe01945 --- /dev/null +++ b/features/account/impl/src/main/java/com/tangem/features/account/analytics/WalletSettingsAccountAnalyticEvents.kt @@ -0,0 +1,26 @@ +package com.tangem.features.account.analytics + +import com.tangem.core.analytics.models.AnalyticsEvent + +sealed class WalletSettingsAccountAnalyticEvents( + category: String = "Settings / Wallet Settings", + event: String, + params: Map = emptyMap(), +) : AnalyticsEvent(category, event, params) { + + class AccountCreated : WalletSettingsAccountAnalyticEvents( + event = "Account Created", + ) + + class AccountRecovered : WalletSettingsAccountAnalyticEvents( + event = "Account Recovered", + ) + + class ArchivedAccountsScreenOpened : WalletSettingsAccountAnalyticEvents( + event = "Archived Accounts Screen Opened", + ) + + class ButtonRecoverAccount : WalletSettingsAccountAnalyticEvents( + event = "Button - Recover Account", + ) +} \ No newline at end of file diff --git a/features/account/impl/src/main/java/com/tangem/features/account/archived/ArchivedAccountListModel.kt b/features/account/impl/src/main/java/com/tangem/features/account/archived/ArchivedAccountListModel.kt index c515c6eafd..13a3acdaf9 100644 --- a/features/account/impl/src/main/java/com/tangem/features/account/archived/ArchivedAccountListModel.kt +++ b/features/account/impl/src/main/java/com/tangem/features/account/archived/ArchivedAccountListModel.kt @@ -1,5 +1,6 @@ package com.tangem.features.account.archived +import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.api.AnalyticsExceptionHandler import com.tangem.core.analytics.models.ExceptionAnalyticsEvent import com.tangem.core.decompose.model.Model @@ -18,6 +19,7 @@ import com.tangem.domain.account.status.usecase.RecoverCryptoPortfolioUseCase import com.tangem.domain.account.usecase.GetArchivedAccountsUseCase import com.tangem.domain.models.account.AccountId import com.tangem.features.account.ArchivedAccountListComponent +import com.tangem.features.account.analytics.WalletSettingsAccountAnalyticEvents import com.tangem.features.account.archived.entity.AccountArchivedUM import com.tangem.features.account.archived.entity.AccountArchivedUMBuilder import com.tangem.features.account.archived.entity.AccountArchivedUMBuilder.Companion.toggleProgress @@ -40,6 +42,7 @@ internal class ArchivedAccountListModel @Inject constructor( private val recoverCryptoPortfolioUseCase: RecoverCryptoPortfolioUseCase, private val getArchivedAccountsUseCase: GetArchivedAccountsUseCase, private val umBuilder: AccountArchivedUMBuilder, + private val analyticsEventHandler: AnalyticsEventHandler, private val analyticsExceptionHandler: AnalyticsExceptionHandler, ) : Model() { @@ -52,6 +55,7 @@ internal class ArchivedAccountListModel @Inject constructor( private val getArchivedAccountsJob = JobHolder() init { + analyticsEventHandler.send(WalletSettingsAccountAnalyticEvents.ArchivedAccountsScreenOpened()) getArchivedAccounts() } @@ -96,6 +100,7 @@ internal class ArchivedAccountListModel @Inject constructor( } private fun recoverCryptoPortfolio(accountId: AccountId) = modelScope.launch { + analyticsEventHandler.send(WalletSettingsAccountAnalyticEvents.ButtonRecoverAccount()) uiState.update { it.toggleProgress(accountId, isLoading = true) } val result = withContext(dispatchers.default) { recoverCryptoPortfolioUseCase(accountId) @@ -148,6 +153,7 @@ internal class ArchivedAccountListModel @Inject constructor( } private fun showSuccessRecoverMessage() { + analyticsEventHandler.send(WalletSettingsAccountAnalyticEvents.AccountRecovered()) val message = resourceReference(R.string.account_recover_success_message) messageSender.send(ToastMessage(message = message)) } diff --git a/features/account/impl/src/main/java/com/tangem/features/account/createedit/AccountCreateEditModel.kt b/features/account/impl/src/main/java/com/tangem/features/account/createedit/AccountCreateEditModel.kt index 6387e99fc8..8720ae4650 100644 --- a/features/account/impl/src/main/java/com/tangem/features/account/createedit/AccountCreateEditModel.kt +++ b/features/account/impl/src/main/java/com/tangem/features/account/createedit/AccountCreateEditModel.kt @@ -4,6 +4,7 @@ import androidx.annotation.StringRes import com.tangem.common.ui.account.AccountNameUM import com.tangem.common.ui.account.toDomain import com.tangem.common.ui.account.toUM +import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.api.AnalyticsExceptionHandler import com.tangem.core.analytics.models.ExceptionAnalyticsEvent import com.tangem.core.decompose.di.ModelScoped @@ -25,6 +26,9 @@ import com.tangem.domain.models.account.CryptoPortfolioIcon import com.tangem.domain.models.account.DerivationIndex import com.tangem.domain.models.wallet.UserWalletId import com.tangem.features.account.AccountCreateEditComponent +import com.tangem.features.account.analytics.AccountSettingsAnalyticEvents +import com.tangem.features.account.analytics.AccountSettingsAnalyticEvents.Companion.toAnalyticSource +import com.tangem.features.account.analytics.WalletSettingsAccountAnalyticEvents import com.tangem.features.account.createedit.entity.AccountCreateEditUM import com.tangem.features.account.createedit.entity.AccountCreateEditUMBuilder import com.tangem.features.account.createedit.entity.AccountCreateEditUMBuilder.Companion.portfolioIcon @@ -54,6 +58,7 @@ internal class AccountCreateEditModel @Inject constructor( private val addCryptoPortfolioUseCase: AddCryptoPortfolioUseCase, private val getUnoccupiedAccountIndexUseCase: GetUnoccupiedAccountIndexUseCase, private val analyticsExceptionHandler: AnalyticsExceptionHandler, + private val analyticsEventHandler: AnalyticsEventHandler, ) : Model() { private val params = paramsContainer.require() @@ -65,6 +70,8 @@ internal class AccountCreateEditModel @Inject constructor( init { if (params is AccountCreateEditComponent.Params.Create) { updateDerivationInfo(userWalletId = params.userWalletId) + } else { + analyticsEventHandler.send(AccountSettingsAnalyticEvents.AccountEditScreenOpened()) } } @@ -105,6 +112,12 @@ internal class AccountCreateEditModel @Inject constructor( val icon = state.account.portfolioIcon.toDomain() val index = state.account.derivationInfo.index ?: return val derivationIndex = DerivationIndex(value = index).getOrNull() ?: return + val event = AccountSettingsAnalyticEvents.ButtonAddNewAccount( + name = name, + icon = icon, + derivationIndex = derivationIndex.value, + ) + analyticsEventHandler.send(event) uiState.value = uiState.value.toggleProgress(showProgress = true) val result = addCryptoPortfolioUseCase( @@ -118,12 +131,22 @@ internal class AccountCreateEditModel @Inject constructor( result .onLeft(::handleAddAccountError) .onRight { + analyticsEventHandler.send(WalletSettingsAccountAnalyticEvents.AccountCreated()) showMessage(R.string.account_create_success_message) router.pop() } } private fun handleAddAccountError(error: AddCryptoPortfolioUseCase.Error) { + val event = AccountSettingsAnalyticEvents.AccountError( + source = params.toAnalyticSource(), + error = when (error) { + is AddCryptoPortfolioUseCase.Error.AccountListRequirementsNotMet -> error.cause.tag + is AddCryptoPortfolioUseCase.Error.DataOperationFailed -> error.cause.message.orEmpty() + }, + ) + analyticsEventHandler.send(event) + val isDuplicateAccountNamesError = (error as? AddCryptoPortfolioUseCase.Error.AccountListRequirementsNotMet) ?.cause is AccountList.Error.DuplicateAccountNames when { @@ -141,6 +164,7 @@ internal class AccountCreateEditModel @Inject constructor( val icon = state.account.portfolioIcon.toDomain() val isNewName = name != params.account.accountName val isNewIcon = icon != params.account.portfolioIcon + analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonSave(name, icon)) uiState.value = uiState.value.toggleProgress(showProgress = true) val result = updateCryptoPortfolioUseCase( @@ -159,6 +183,15 @@ internal class AccountCreateEditModel @Inject constructor( } private fun handleEditAccountError(error: UpdateCryptoPortfolioUseCase.Error) { + val event = AccountSettingsAnalyticEvents.AccountError( + source = params.toAnalyticSource(), + error = when (error) { + is UpdateCryptoPortfolioUseCase.Error.AccountListRequirementsNotMet -> error.cause.tag + is UpdateCryptoPortfolioUseCase.Error.DataOperationFailed -> error.cause.message.orEmpty() + UpdateCryptoPortfolioUseCase.Error.NothingToUpdate -> error::class.simpleName.orEmpty() + }, + ) + analyticsEventHandler.send(event) val isDuplicateAccountNamesError = (error as? UpdateCryptoPortfolioUseCase.Error.AccountListRequirementsNotMet) ?.cause is AccountList.Error.DuplicateAccountNames when { diff --git a/features/account/impl/src/main/java/com/tangem/features/account/details/AccountDetailsModel.kt b/features/account/impl/src/main/java/com/tangem/features/account/details/AccountDetailsModel.kt index 4be0bb85f1..c1bdf53342 100644 --- a/features/account/impl/src/main/java/com/tangem/features/account/details/AccountDetailsModel.kt +++ b/features/account/impl/src/main/java/com/tangem/features/account/details/AccountDetailsModel.kt @@ -2,6 +2,7 @@ package com.tangem.features.account.details import com.tangem.common.routing.AppRoute import com.tangem.common.ui.account.toUM +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 @@ -20,6 +21,7 @@ import com.tangem.domain.models.account.Account import com.tangem.domain.models.wallet.isMultiCurrency import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.account.AccountDetailsComponent +import com.tangem.features.account.analytics.AccountSettingsAnalyticEvents import com.tangem.features.account.createedit.entity.AccountCreateEditUMBuilder.Companion.portfolioIcon import com.tangem.features.account.details.entity.AccountDetailsUM import com.tangem.features.account.details.entity.AccountDetailsUM.ArchiveMode @@ -37,6 +39,7 @@ internal class AccountDetailsModel @Inject constructor( override val dispatchers: CoroutineDispatcherProvider, private val archiveCryptoPortfolioUseCase: ArchiveCryptoPortfolioUseCase, singleAccountSupplier: SingleAccountSupplier, + private val analyticsEventHandler: AnalyticsEventHandler, private val getUserWalletUseCase: GetUserWalletUseCase, ) : Model() { @@ -48,12 +51,14 @@ internal class AccountDetailsModel @Inject constructor( private val accountId = params.account.accountId init { + analyticsEventHandler.send(AccountSettingsAnalyticEvents.AccountSettingsScreenOpened()) singleAccountSupplier(SingleAccountProducer.Params(accountId)) .onEach { account -> uiState.update { buildUI(account) } } .launchIn(modelScope) } private fun onEditAccountClick(account: Account) { + analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonEdit()) router.push(AppRoute.EditAccount(account)) } @@ -62,17 +67,21 @@ internal class AccountDetailsModel @Inject constructor( source = AppRoute.ManageTokens.Source.SETTINGS, portfolioId = PortfolioId(account.accountId), ) + analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonManageTokens()) router.push(route) } private fun onArchiveAccountClick() { + analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonArchiveAccount()) confirmArchiveDialog() } private fun confirmArchiveDialog() { val secondAction = EventMessageAction( title = resourceReference(R.string.common_cancel), - onClick = {}, + onClick = { + analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonCancelAccountArchivation()) + }, ) val firstAction = EventMessageAction( title = resourceReference(R.string.account_details_archive_action), @@ -90,6 +99,7 @@ internal class AccountDetailsModel @Inject constructor( } private fun archiveCryptoPortfolio() = modelScope.launch { + analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonArchiveAccountConfirmation()) uiState.update { it.toggleProgress(true) } archiveCryptoPortfolioUseCase(accountId) .onLeft { error -> @@ -97,6 +107,7 @@ internal class AccountDetailsModel @Inject constructor( uiState.update { it.toggleProgress(false) } } .onRight { + analyticsEventHandler.send(AccountSettingsAnalyticEvents.AccountArchived()) val message = resourceReference(R.string.account_archive_success_message) messageSender.send(ToastMessage(message = message)) router.pop() @@ -104,6 +115,11 @@ internal class AccountDetailsModel @Inject constructor( } private fun failedArchiveDialog(error: ArchiveCryptoPortfolioUseCase.Error) { + val event = AccountSettingsAnalyticEvents.AccountError( + source = AccountSettingsAnalyticEvents.Source.ARCHIVE, + error = error.tag, + ) + analyticsEventHandler.send(event) val titleRes = R.string.common_something_went_wrong val messageRes = when (error) { is ArchiveCryptoPortfolioUseCase.Error.CriticalTechError.AccountListRequirementsNotMet, diff --git a/features/account/impl/src/main/java/com/tangem/features/account/selector/DefaultPortfolioSelectorController.kt b/features/account/impl/src/main/java/com/tangem/features/account/selector/DefaultPortfolioSelectorController.kt index 00b2a52f71..fe9a055c3f 100644 --- a/features/account/impl/src/main/java/com/tangem/features/account/selector/DefaultPortfolioSelectorController.kt +++ b/features/account/impl/src/main/java/com/tangem/features/account/selector/DefaultPortfolioSelectorController.kt @@ -29,6 +29,8 @@ internal class DefaultPortfolioSelectorController @Inject constructor( override val isEnabled: MutableStateFlow<(UserWallet, AccountStatus) -> Boolean> = MutableStateFlow { _, _ -> true } + override suspend fun isAccountModeSync(): Boolean = isAccountsModeEnabledUseCase.invokeSync() + override fun selectAccount(accountId: AccountId?) { _selectedAccount.tryEmit(accountId) } 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 a2c559ac76..c3a41d047c 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 @@ -31,6 +31,19 @@ internal sealed class CustomTokenAnalyticsEvent( ), ) + class AddTokenToAnotherAccount( + currencySymbol: String, + derivationPath: String, + source: ManageTokensSource, + ) : CustomTokenAnalyticsEvent( + event = "Button - Add Token To Another Account", + params = mapOf( + AnalyticsParam.Key.TOKEN_PARAM to currencySymbol, + AnalyticsParam.Key.DERIVATION to derivationPath, + AnalyticsParam.Key.SOURCE to source.analyticsName, + ), + ) + class NetworkSelected(networkName: String, source: ManageTokensSource) : CustomTokenAnalyticsEvent( event = "Custom Token Network Selected", params = mapOf( diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/CustomTokenFormComponent.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/CustomTokenFormComponent.kt index 2baf3f982f..3fd1eb6250 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/CustomTokenFormComponent.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/CustomTokenFormComponent.kt @@ -2,6 +2,7 @@ package com.tangem.features.managetokens.component import com.tangem.core.decompose.factory.ComponentFactory import com.tangem.core.ui.decompose.ComposableContentComponent +import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.features.managetokens.entity.customtoken.CustomTokenFormValues import com.tangem.features.managetokens.entity.customtoken.SelectedDerivationPath import com.tangem.features.managetokens.entity.customtoken.SelectedNetwork @@ -16,7 +17,7 @@ internal interface CustomTokenFormComponent : ComposableContentComponent { val source: ManageTokensSource, val onSelectNetworkClick: (CustomTokenFormValues) -> Unit, val onSelectDerivationPathClick: (CustomTokenFormValues) -> Unit, - val onCurrencyAdded: () -> Unit, + val onCurrencyAdded: (currency: CryptoCurrency) -> Unit, ) interface Factory : ComponentFactory diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/impl/DefaultAddCustomTokenComponent.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/impl/DefaultAddCustomTokenComponent.kt index 8e270519a8..b49478560f 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/impl/DefaultAddCustomTokenComponent.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/component/impl/DefaultAddCustomTokenComponent.kt @@ -15,6 +15,7 @@ import com.tangem.core.decompose.context.childByContext import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig import com.tangem.core.ui.decompose.ComposableContentComponent import com.tangem.domain.models.account.Account +import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.network.Network import com.tangem.features.managetokens.analytics.CustomTokenAnalyticsEvent import com.tangem.features.managetokens.component.AddCustomTokenComponent @@ -232,7 +233,16 @@ internal class DefaultAddCustomTokenComponent @AssistedInject constructor( } } - private fun dismissAndNotify() { + private fun dismissAndNotify(currency: CryptoCurrency) { + val account = addedToAccount + if (account is Account.CryptoPortfolio && !account.isMainAccount) { + val event = CustomTokenAnalyticsEvent.AddTokenToAnotherAccount( + currencySymbol = currency.symbol, + derivationPath = currency.network.derivationPath.value.orEmpty(), + source = params.source, + ) + analyticsEventHandler.send(event) + } params.onCurrencyAdded(addedToAccount) dismiss() } diff --git a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt index 60b26282fb..ff7a6c3c36 100644 --- a/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt +++ b/features/manage-tokens/impl/src/main/kotlin/com/tangem/features/managetokens/model/CustomTokenFormModel.kt @@ -364,7 +364,7 @@ internal class CustomTokenFormModel @Inject constructor( return@resource } - params.onCurrencyAdded() + params.onCurrencyAdded(currency) } private fun selectNetwork() { diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddToPortfolioModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddToPortfolioModel.kt index f165c1bb40..40c339c730 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddToPortfolioModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddToPortfolioModel.kt @@ -4,6 +4,7 @@ import com.arkivanov.decompose.router.stack.StackNavigation import com.arkivanov.decompose.router.stack.popToFirst import com.arkivanov.decompose.router.stack.pushNew import com.arkivanov.decompose.router.stack.replaceAll +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 @@ -47,6 +48,7 @@ internal class AddToPortfolioModel @Inject constructor( private val getCryptoCurrencyActionsUseCase: GetCryptoCurrencyActionsUseCaseV2, private val getTokenMarketCryptoCurrency: GetTokenMarketCryptoCurrency, private val messageSender: UiMessageSender, + private val analyticsEventHandler: AnalyticsEventHandler, val portfolioSelectorController: PortfolioSelectorController, ) : Model(), ChooseNetworkComponent.Callbacks by callbackDelegate, @@ -93,6 +95,7 @@ internal class AddToPortfolioModel @Inject constructor( .map { it.availableToAddData } .distinctUntilChanged() .stateIn(this) + val isAccountMode = portfolioSelectorController.isAccountModeSync() // use snapshot data, looks like we don’t need to remap at runtime val data = featureDataFlow.value @@ -117,6 +120,7 @@ internal class AddToPortfolioModel @Inject constructor( // force select a portfolio, triggers [selectedPortfolio] portfolioSelectorController.selectAccount(accountId) } else { + logAccountSelector(isAccountMode) navigation.replaceAll(AddToPortfolioRoutes.PortfolioSelector) } @@ -165,6 +169,7 @@ internal class AddToPortfolioModel @Inject constructor( .onEach { middleNavigationJob?.cancel() middleNavigationJob = changePortfolioNavigationFlow(data).launchIn(this) + logAccountSelector(isAccountMode) navigation.pushNew(AddToPortfolioRoutes.PortfolioSelector) } .launchIn(this) @@ -194,6 +199,12 @@ internal class AddToPortfolioModel @Inject constructor( .launchIn(modelScope) } + private fun logAccountSelector(isAccountMode: Boolean) { + if (isAccountMode) { + analyticsEventHandler.send(eventBuilder.popupToChooseAccount()) + } + } + private fun changeNetworkNavigationFlow(): Flow { return setupNetworkFlow(selectedPortfolio) .onEach { newNetwork -> @@ -260,6 +271,7 @@ internal class AddToPortfolioModel @Inject constructor( data.availableToAddWallets[selectedAccountId.userWalletId] ?: return@combine null val availableToAddAccount = availableToAddWallets.availableToAddAccounts[selectedAccountId] ?: return@combine null + if (!isAccountMode) analyticsEventHandler.send(eventBuilder.addToPortfolioWalletChanged()) SelectedPortfolio( isAccountMode = isAccountMode, userWallet = availableToAddWallets.userWallet, diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddTokenModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddTokenModel.kt index 8a4ec65436..b0f322b6f5 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddTokenModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/AddTokenModel.kt @@ -1,5 +1,6 @@ package com.tangem.features.markets.portfolio.add.impl.model +import com.tangem.common.ui.addtoken.AddTokenUM import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model @@ -10,13 +11,13 @@ import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.message.ToastMessage import com.tangem.domain.account.status.usecase.GetAccountCurrencyStatusUseCase import com.tangem.domain.account.status.usecase.ManageCryptoCurrenciesUseCase +import com.tangem.domain.models.account.Account import com.tangem.domain.wallets.usecase.ColdWalletAndHasMissedDerivationsUseCase import com.tangem.features.markets.impl.R import com.tangem.features.markets.portfolio.add.api.SelectedNetwork import com.tangem.features.markets.portfolio.add.api.SelectedPortfolio import com.tangem.features.markets.portfolio.add.impl.AddTokenComponent import com.tangem.features.markets.portfolio.add.impl.model.AddTokenUiBuilder.Companion.toggleProgress -import com.tangem.common.ui.addtoken.AddTokenUM import com.tangem.lib.crypto.BlockchainUtils import com.tangem.utils.coroutines.CoroutineDispatcherProvider import com.tangem.utils.coroutines.JobHolder @@ -74,7 +75,8 @@ internal class AddTokenModel @Inject constructor( analyticsEventHandler.send(analyticsEventBuilder.addToPortfolioContinue(blockchainNames)) val cryptoCurrency = selectedNetwork.cryptoCurrency - val accountId = selectedPortfolio.account.account.account.accountId + val account = selectedPortfolio.account.account.account + val accountId = account.accountId manageCryptoCurrenciesUseCase(accountId = accountId, add = cryptoCurrency) .onLeft { processError(error = it) @@ -90,6 +92,11 @@ internal class AddTokenModel @Inject constructor( if (status == null) { processError(error = null) } else { + when (account) { + is Account.CryptoPortfolio -> if (!account.isMainAccount) { + analyticsEventHandler.send(analyticsEventBuilder.addToNotMainAccount()) + } + } params.callbacks.onTokenAdded(status.status) } uiState.value = um.toggleProgress(false) diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/TokenActionsModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/TokenActionsModel.kt index a2d0ceeba2..d3dd8d929b 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/TokenActionsModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/TokenActionsModel.kt @@ -62,10 +62,7 @@ internal class TokenActionsModel @Inject constructor( ) private fun handledQuickAction(handledAction: HandledQuickAction) { - val event = analyticsEventBuilder.quickActionClick( - actionUM = handledAction.action, - blockchainName = handledAction.cryptoCurrencyData.status.currency.network.name, - ) + val event = analyticsEventBuilder.getTokenActionClick(actionUM = handledAction.action) analyticsEventHandler.send(event) val isReceive = handledAction.action == TokenActionsBSContentUM.Action.Receive if (!isReceive) return diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/TokenActionsUiBuilder.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/TokenActionsUiBuilder.kt index be2f06ccdf..6a1dcb993e 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/TokenActionsUiBuilder.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/add/impl/model/TokenActionsUiBuilder.kt @@ -1,5 +1,6 @@ package com.tangem.features.markets.portfolio.add.impl.model +import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter @@ -15,6 +16,7 @@ import javax.inject.Inject @ModelScoped internal class TokenActionsUiBuilder @Inject constructor( paramsContainer: ParamsContainer, + private val analyticsEventHandler: AnalyticsEventHandler, ) { private val params = paramsContainer.require() @@ -32,7 +34,10 @@ internal class TokenActionsUiBuilder @Inject constructor( ) return TokenActionsUM( token = tokenUM, - onLaterClick = { params.callbacks.onLaterClick() }, + onLaterClick = { + analyticsEventHandler.send(params.eventBuilder.getTokenLater()) + params.callbacks.onLaterClick() + }, quickActions = PortfolioTokenUMConverter.quickActions(data, tokenActionsHandler), ) } diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/analytics/PortfolioAnalyticsEvent.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/analytics/PortfolioAnalyticsEvent.kt index 9e02ec98a2..772d83f651 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/analytics/PortfolioAnalyticsEvent.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/analytics/PortfolioAnalyticsEvent.kt @@ -21,6 +21,14 @@ internal class PortfolioAnalyticsEvent( ), ) + fun popupToChooseAccount() = PortfolioAnalyticsEvent( + event = "Popup to choose account", + ) + + fun addToNotMainAccount() = PortfolioAnalyticsEvent( + event = "Button - Add (token not to main Account)", + ) + fun addToPortfolioWalletChanged() = PortfolioAnalyticsEvent(event = "Wallet Selected") fun addToPortfolioContinue(blockchainNames: List) = PortfolioAnalyticsEvent( @@ -47,5 +55,19 @@ internal class PortfolioAnalyticsEvent( put("blockchain", blockchainName) }, ) + + fun getTokenActionClick(actionUM: TokenActionsBSContentUM.Action) = PortfolioAnalyticsEvent( + event = when (actionUM) { + TokenActionsBSContentUM.Action.Buy -> "Popup Get token - Button Buy" + TokenActionsBSContentUM.Action.Receive -> "Popup Get token - Button Receive" + TokenActionsBSContentUM.Action.Exchange -> "Popup Get token - Button Exchange" + TokenActionsBSContentUM.Action.Stake -> "Popup Get token - Button Stake" + else -> "error" + }, + ) + + fun getTokenLater() = PortfolioAnalyticsEvent( + event = "Popup Get token - Button Later", + ) } } \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt index d5e434ad2a..a314e9a0e1 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/model/MarketsPortfolioModel.kt @@ -193,7 +193,10 @@ internal class MarketsPortfolioModel @Inject constructor( NewAddToPortfolioManager.State.NothingToAdd -> AddButtonState.Unavailable } }, - onAddClick = { bottomSheetNavigation.activate(MarketsPortfolioRoute.AddToPortfolio) }, + onAddClick = { + analyticsEventHandler.send(analyticsEventBuilder.addToPortfolioClicked()) + bottomSheetNavigation.activate(MarketsPortfolioRoute.AddToPortfolio) + }, ) newMarketsPortfolioDelegate.combineData() .onEach { _state.value = it } diff --git a/features/referral/impl/src/main/java/com/tangem/feature/referral/analytics/ReferralEvents.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/analytics/ReferralEvents.kt index f92ffd3549..364b76ce0f 100644 --- a/features/referral/impl/src/main/java/com/tangem/feature/referral/analytics/ReferralEvents.kt +++ b/features/referral/impl/src/main/java/com/tangem/feature/referral/analytics/ReferralEvents.kt @@ -12,4 +12,10 @@ sealed class ReferralEvents(event: String) : AnalyticsEvent(REFERRAL_PROGRAM_CAT class ParticipateSuccessful : ReferralEvents(event = "Participate Successful") } -private const val REFERRAL_PROGRAM_CATEGORY = "Referral Program" \ No newline at end of file +sealed class ReferralEventsAccounts(event: String) : AnalyticsEvent(REFERRAL_PROGRAM_ACCOUNT_CATEGORY, event) { + + class ListChooseAccount : ReferralEventsAccounts(event = "List - choose account") +} + +private const val REFERRAL_PROGRAM_CATEGORY = "Referral Program" +private const val REFERRAL_PROGRAM_ACCOUNT_CATEGORY = "Referral program - Account" \ No newline at end of file diff --git a/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt b/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt index ac7b852a3a..46ce302791 100644 --- a/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt +++ b/features/referral/impl/src/main/java/com/tangem/feature/referral/model/ReferralModel.kt @@ -30,6 +30,7 @@ import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.feature.referral.analytics.ReferralEvents +import com.tangem.feature.referral.analytics.ReferralEventsAccounts import com.tangem.feature.referral.api.ReferralComponent import com.tangem.feature.referral.domain.ReferralInteractor import com.tangem.feature.referral.domain.errors.ReferralError @@ -116,6 +117,7 @@ internal class ReferralModel @Inject constructor( private fun combineAccountUI(referralData: ReferralData): Flow = combine( flow = portfolioSelectorController.selectedAccountWithData(portfolioFetcher) + .onEach { analyticsEventHandler.send(ReferralEventsAccounts.ListChooseAccount()) } .onEach { bottomSheetNavigation.dismiss() }, flow2 = getBalanceHidingSettingsUseCase.isBalanceHidden(), flow3 = getSelectedAppCurrencyUseCase.invokeOrDefault(), diff --git a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/analytics/CommonSendAnalyticEvents.kt b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/analytics/CommonSendAnalyticEvents.kt index cb58f30134..82527c66bf 100644 --- a/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/analytics/CommonSendAnalyticEvents.kt +++ b/features/send-v2/api/src/main/java/com/tangem/features/send/v2/api/analytics/CommonSendAnalyticEvents.kt @@ -51,16 +51,29 @@ sealed class CommonSendAnalyticEvents( ), ) + @Suppress("NullableToStringCall") /** Confirmation screen opened */ data class ConfirmationScreenOpened( val categoryName: String, val source: CommonSendSource, + val fromDerivationIndex: Int?, + val toDerivationIndex: Int?, + val sendBlockchain: String, + val sendToken: String, ) : CommonSendAnalyticEvents( category = categoryName, event = "Confirm Screen Opened", - params = mapOf( - SOURCE to source.analyticsName, - ), + params = buildMap { + put(SOURCE, source.analyticsName) + put("Token", sendToken) + put("Blockchain", sendBlockchain) + if (fromDerivationIndex != null || toDerivationIndex != null) { + put( + "Account Derivation From or To (optional)", + "$fromDerivationIndex, $toDerivationIndex", + ) + } + }, ) /** If transaction delays notification is present */ diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt index 858747f091..d6e89cd52c 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/DefaultSendComponent.kt @@ -88,10 +88,17 @@ internal class DefaultSendComponent @AssistedInject constructor( componentScope.launch { when (val activeComponent = stack.active.instance) { is SendConfirmComponent -> { + val fromCurrency = params.currency + val fromDerivationIndex = model.accountFlow.value?.derivationIndex?.value + .takeIf { model.isAccountModeFlow.value } analyticsEventHandler.send( CommonSendAnalyticEvents.ConfirmationScreenOpened( categoryName = model.analyticCategoryName, source = model.analyticsSendSource, + sendBlockchain = fromCurrency.network.name, + sendToken = fromCurrency.symbol, + fromDerivationIndex = fromDerivationIndex, + toDerivationIndex = null, ), ) if (model.currentRoute.value.isEditMode) { diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/analytics/SendAnalyticEvents.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/analytics/SendAnalyticEvents.kt index bf26de5704..d8ccef5d07 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/analytics/SendAnalyticEvents.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/analytics/SendAnalyticEvents.kt @@ -2,6 +2,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.ACCOUNT_DERIVATION_FROM 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 @@ -25,18 +26,21 @@ internal sealed class SendAnalyticEvents( val blockchain: String, val isNonceNotEmpty: Boolean, private val ensStatus: AnalyticsParam.EmptyFull, + val derivationIndex: Int?, ) : SendAnalyticEvents( event = "Transaction Sent Screen Opened", - params = mapOf( - TOKEN_PARAM to token, - FEE_TYPE to feeType.value, - BLOCKCHAIN to blockchain, - NONCE to isNonceNotEmpty.toString().capitalize(), - ENS_ADDRESS to when (ensStatus) { + params = buildMap { + put(TOKEN_PARAM, token) + put(FEE_TYPE, feeType.value) + put(BLOCKCHAIN, blockchain) + if (derivationIndex != null) put(ACCOUNT_DERIVATION_FROM, derivationIndex.toString()) + put(NONCE, isNonceNotEmpty.toString().capitalize()) + val ensAddress = when (ensStatus) { AnalyticsParam.EmptyFull.Empty -> false.toString().capitalize() AnalyticsParam.EmptyFull.Full -> true.toString().capitalize() - }, - ), + } + put(ENS_ADDRESS, ensAddress) + }, ) data class ConvertTokenButtonClicked( diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/analytics/SendAnalyticHelper.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/analytics/SendAnalyticHelper.kt index 4d56a5075f..e65f75d699 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/analytics/SendAnalyticHelper.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/analytics/SendAnalyticHelper.kt @@ -4,6 +4,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.core.analytics.models.Basic import com.tangem.core.decompose.di.ModelScoped +import com.tangem.domain.models.account.Account import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.features.send.v2.api.entity.FeeNonce import com.tangem.features.send.v2.api.entity.FeeSelectorUM @@ -17,10 +18,12 @@ internal class SendAnalyticHelper @Inject constructor( private val analyticsEventHandler: AnalyticsEventHandler, ) { - fun sendSuccessAnalytics(cryptoCurrency: CryptoCurrency, sendUM: SendUM) { + fun sendSuccessAnalytics(cryptoCurrency: CryptoCurrency, sendUM: SendUM, account: Account.CryptoPortfolio?) { val destinationUM = sendUM.destinationUM as? DestinationUM.Content val feeSelectorUM = sendUM.feeSelectorUM as? FeeSelectorUM.Content ?: return val feeType = feeSelectorUM.toAnalyticType() + val isNotMainAccount = account != null && !account.isMainAccount + val derivationIndex = if (isNotMainAccount) account.derivationIndex.value else null analyticsEventHandler.send( SendAnalyticEvents.TransactionScreenOpened( token = cryptoCurrency.symbol, @@ -28,6 +31,7 @@ internal class SendAnalyticHelper @Inject constructor( blockchain = cryptoCurrency.network.name, isNonceNotEmpty = feeSelectorUM.feeNonce is FeeNonce.Nonce, ensStatus = getEnsStatus(sendUM), + derivationIndex = derivationIndex, ), ) analyticsEventHandler.send( diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt index d36c18e827..6fcd04be67 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/send/confirm/model/SendConfirmModel.kt @@ -416,7 +416,11 @@ internal class SendConfirmModel @Inject constructor( updateTransactionStatus(txData) addTokenToWalletIfNeeded() sendBalanceUpdater.scheduleUpdates() - sendAnalyticHelper.sendSuccessAnalytics(cryptoCurrency, uiState.value) + sendAnalyticHelper.sendSuccessAnalytics( + cryptoCurrency = cryptoCurrency, + sendUM = uiState.value, + account = params.accountFlow.value, + ) params.callback.onResult(uiState.value) params.onSendTransaction() }, diff --git a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt index c8992e8ca4..250a2adb28 100644 --- a/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt +++ b/features/send-v2/impl/src/main/java/com/tangem/features/send/v2/sendnft/DefaultNFTSendComponent.kt @@ -79,10 +79,17 @@ internal class DefaultNFTSendComponent @AssistedInject constructor( componentScope.launch { when (val activeComponent = stack.active.instance) { is NFTSendConfirmComponent -> { + val fromCurrency = model.cryptoCurrency + val fromDerivationIndex = model.account?.derivationIndex?.value + .takeIf { model.isAccountsMode } analyticsEventHandler.send( CommonSendAnalyticEvents.ConfirmationScreenOpened( categoryName = analyticsCategoryName, source = analyticsSendSource, + sendBlockchain = fromCurrency.network.name, + sendToken = fromCurrency.symbol, + fromDerivationIndex = fromDerivationIndex, + toDerivationIndex = null, ), ) if (model.currentRouteFlow.value.isEditMode) { diff --git a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt index 2006967f4f..300dd949eb 100644 --- a/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt +++ b/features/swap-v2/impl/src/main/java/com/tangem/features/swap/v2/impl/sendviaswap/DefaultSendWithSwapComponent.kt @@ -109,10 +109,17 @@ internal class DefaultSendWithSwapComponent @AssistedInject constructor( activeComponent.updateState(model.uiState.value.destinationUM) } is SendWithSwapConfirmComponent -> { + val fromCurrency = params.currency + val fromDerivationIndex = model.accountFlow.value?.derivationIndex?.value + .takeIf { model.isAccountModeFlow.value } analyticsEventHandler.send( CommonSendAnalyticEvents.ConfirmationScreenOpened( categoryName = model.analyticCategoryName, source = model.analyticsSendSource, + sendBlockchain = fromCurrency.network.name, + sendToken = fromCurrency.symbol, + fromDerivationIndex = fromDerivationIndex, + toDerivationIndex = null, ), ) if (model.currentRoute.value.isEditMode) { 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 f9f65022bc..c1ee5ff99d 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 @@ -62,6 +62,7 @@ sealed class SwapEvents( class ButtonSwipeClicked : SwapEvents(event = "Button - Swipe") + @Suppress("NullableToStringCall") data class SwapInProgressScreen( val provider: SwapProvider, val commission: FeeType, // Market / Fast @@ -69,6 +70,8 @@ sealed class SwapEvents( val receiveBlockchain: String, val sendToken: String, val receiveToken: String, + val fromDerivationIndex: Int?, + val toDerivationIndex: Int?, ) : SwapEvents( event = "Swap in Progress Screen Opened", params = mapOf( @@ -78,6 +81,7 @@ sealed class SwapEvents( "Receive Token" to receiveToken, "Send Blockchain" to sendBlockchain, "Receive Blockchain" to receiveBlockchain, + "Account Derivation From or To (optional)" to "$fromDerivationIndex, $toDerivationIndex", ), ) diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt index b9ed696598..15900bd318 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt @@ -847,6 +847,8 @@ internal class SwapModel @Inject constructor( val fee = dataState.selectedFee?.feeType ?: return val fromCurrency = dataState.fromCryptoCurrency?.currency ?: return val toCurrency = dataState.toCryptoCurrency?.currency ?: return + val fromDerivationIndex = dataState.fromAccount?.derivationIndex?.value + val toDerivationIndex = dataState.toAccount?.derivationIndex?.value analyticsEventHandler.send( SwapEvents.SwapInProgressScreen( @@ -856,6 +858,8 @@ internal class SwapModel @Inject constructor( receiveBlockchain = toCurrency.network.name, sendToken = fromCurrency.symbol, receiveToken = toCurrency.symbol, + fromDerivationIndex = fromDerivationIndex, + toDerivationIndex = toDerivationIndex, ), ) } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt index 1ec6d138b7..2cbe54658a 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt @@ -532,6 +532,7 @@ internal class TokenDetailsModel @Inject constructor( token = cryptoCurrency.symbol, blockchain = cryptoCurrency.network.name, status = unavailabilityReason.toReasonAnalyticsText(), + derivationIndex = getAccountIndexOrNull(), ), ) @@ -557,6 +558,7 @@ internal class TokenDetailsModel @Inject constructor( token = cryptoCurrency.symbol, blockchain = cryptoCurrency.network.name, status = null, + derivationIndex = getAccountIndexOrNull(), ), ) router.openTokenDetails(userWalletId = userWalletId, currency = cryptoCurrency) @@ -578,6 +580,7 @@ internal class TokenDetailsModel @Inject constructor( token = cryptoCurrency.symbol, blockchain = cryptoCurrency.network.name, status = unavailabilityReason.toReasonAnalyticsText(), + derivationIndex = getAccountIndexOrNull(), ), ) @@ -698,6 +701,7 @@ internal class TokenDetailsModel @Inject constructor( token = cryptoCurrency.symbol, blockchain = cryptoCurrency.network.name, status = unavailabilityReason.toReasonAnalyticsText(), + derivationIndex = getAccountIndexOrNull(), ), ) @@ -766,6 +770,12 @@ internal class TokenDetailsModel @Inject constructor( showErrorIfDemoModeOrElse(action = ::openExplorer) } + private fun getAccountIndexOrNull(): Int? { + val account = account + val isNotMainAccount = account != null && !account.isMainAccount + return if (isNotMainAccount) account.derivationIndex.value else null + } + private fun openExplorer() { val currencyStatus = cryptoCurrencyStatus ?: return diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt index 6d95c6fa82..b5ba400298 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/model/WalletSettingsModel.kt @@ -25,6 +25,8 @@ import com.tangem.core.ui.message.EventMessageAction import com.tangem.core.ui.message.SnackbarMessage import com.tangem.core.ui.message.bottomSheetMessage import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles +import com.tangem.domain.account.supplier.SingleAccountListSupplier +import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.card.common.util.cardTypesResolver import com.tangem.domain.demo.IsDemoCardUseCase import com.tangem.domain.models.PortfolioId @@ -88,6 +90,8 @@ internal class WalletSettingsModel @Inject constructor( private val dismissUpgradeWalletNotificationUseCase: DismissUpgradeWalletNotificationUseCase, private val unlockHotWalletContextualUseCase: UnlockHotWalletContextualUseCase, private val accountsFeatureToggles: AccountsFeatureToggles, + private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase, + private val singleAccountListSupplier: SingleAccountListSupplier, private val accountListSortingSaver: AccountListSortingSaver, ) : Model() { @@ -115,7 +119,18 @@ internal class WalletSettingsModel @Inject constructor( init { getUserWalletUseCase.invoke(params.userWalletId).onRight { wallet -> trackingContextProxy.addContext(wallet) - analyticsEventHandler.send(WalletSettingsAnalyticEvents.WalletSettingsScreenOpened()) + modelScope.launch { + val accountsCount = if (isAccountsModeEnabledUseCase.invokeSync()) { + singleAccountListSupplier(wallet.walletId) + .first() + .accounts + .size + } else { + null + } + val event = WalletSettingsAnalyticEvents.WalletSettingsScreenOpened(accountsCount) + analyticsEventHandler.send(event) + } } fun combineUI(wallet: UserWallet) = combine( diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountItemsDelegate.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountItemsDelegate.kt index c9458a072e..0d40442830 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountItemsDelegate.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountItemsDelegate.kt @@ -2,6 +2,7 @@ package com.tangem.feature.walletsettings.utils import com.tangem.common.routing.AppRoute import com.tangem.common.ui.account.AccountPortfolioItemUMConverter +import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.ParamsContainer import com.tangem.core.decompose.navigation.Router @@ -24,6 +25,7 @@ import com.tangem.domain.models.account.AccountId import com.tangem.domain.models.account.AccountStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId +import com.tangem.domain.wallets.analytics.WalletSettingsAnalyticEvents import com.tangem.domain.wallets.extension.isAccountsSupported import com.tangem.feature.walletsettings.component.WalletSettingsComponent import com.tangem.feature.walletsettings.entity.WalletSettingsAccountsUM @@ -46,6 +48,7 @@ internal class AccountItemsDelegate @Inject constructor( private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase, private val accountListSortingSaver: AccountListSortingSaver, private val accountsFeatureToggles: AccountsFeatureToggles, + private val analyticsEventHandler: AnalyticsEventHandler, ) { private val userWalletId = paramsContainer.require().userWalletId @@ -72,7 +75,10 @@ internal class AccountItemsDelegate @Inject constructor( ): List = buildList { fun AccountStatus.CryptoPortfolio.mapCryptoPortfolio(): WalletSettingsAccountsUM { val accountItemUM = AccountPortfolioItemUMConverter( - onClick = { openAccountDetails(this.account) }, + onClick = { + analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonOpenExistingAccount()) + openAccountDetails(this.account) + }, appCurrency = appCurrency, accountBalance = this.tokenList.totalFiatBalance, isBalanceHidden = isBalanceHidden, @@ -107,14 +113,22 @@ internal class AccountItemsDelegate @Inject constructor( title = resourceReference(R.string.account_form_title_create), isAddAccountEnabled = isAddAccountEnabled, onAddAccountClick = { - if (isAddAccountEnabled) openAddAccount(userWalletId) else canNotAddAccountDialog() + if (isAddAccountEnabled) { + analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonAddAccount()) + openAddAccount(userWalletId) + } else { + canNotAddAccountDialog() + } }, ), archivedAccounts = if (isArchivedAccountsEnabled) { BlockUM( text = resourceReference(R.string.account_archived_accounts), iconRes = R.drawable.ic_archive_24, - onClick = { openArchivedAccounts(userWalletId) }, + onClick = { + analyticsEventHandler.send(WalletSettingsAnalyticEvents.ButtonArchivedAccounts()) + openArchivedAccounts(userWalletId) + }, ) } else { null diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountListSortingSaver.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountListSortingSaver.kt index 1f86f48958..52d5a6dbfc 100644 --- a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountListSortingSaver.kt +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/utils/AccountListSortingSaver.kt @@ -1,7 +1,9 @@ package com.tangem.feature.walletsettings.utils +import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.domain.account.usecase.ApplyAccountListSortingUseCase import com.tangem.domain.models.account.AccountId +import com.tangem.domain.wallets.analytics.WalletSettingsAnalyticEvents import com.tangem.utils.coroutines.CoroutineDispatcherProvider import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.FlowPreview @@ -24,6 +26,7 @@ import kotlin.time.Duration.Companion.seconds @OptIn(FlowPreview::class) internal class AccountListSortingSaver @Inject constructor( private val applyAccountListSortingUseCase: ApplyAccountListSortingUseCase, + private val analyticsEventHandler: AnalyticsEventHandler, dispatchers: CoroutineDispatcherProvider, ) { @@ -41,6 +44,9 @@ internal class AccountListSortingSaver @Inject constructor( applyAccountListSortingUseCase.invoke(accountIds).onLeft { Timber.e("Error while saving account list sorting: $it") } + .onRight { + analyticsEventHandler.send(WalletSettingsAnalyticEvents.LongtapAccountsOrder()) + } } .launchIn(coroutineScope) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt index 38cf4e0ca2..bf812afdd1 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/WalletModel.kt @@ -11,6 +11,8 @@ import com.tangem.core.analytics.utils.TrackingContextProxy import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model import com.tangem.domain.account.featuretoggle.AccountsFeatureToggles +import com.tangem.domain.account.supplier.SingleAccountListSupplier +import com.tangem.domain.account.usecase.IsAccountsModeEnabledUseCase import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase import com.tangem.domain.common.wallets.UserWalletsListRepository import com.tangem.domain.models.wallet.UserWallet @@ -99,6 +101,8 @@ internal class WalletModel @Inject constructor( private val accountsFeatureToggles: AccountsFeatureToggles, private val tangemPayMainScreenCustomerInfoUseCase: TangemPayMainScreenCustomerInfoUseCase, private val trackingContextProxy: TrackingContextProxy, + private val singleAccountListSupplier: SingleAccountListSupplier, + private val isAccountsModeEnabledUseCase: IsAccountsModeEnabledUseCase, private val feedFeatureToggle: FeedFeatureToggle, val screenLifecycleProvider: ScreenLifecycleProvider, val innerWalletRouter: InnerWalletRouter, @@ -293,8 +297,19 @@ internal class WalletModel @Inject constructor( modelScope.launch { val hasMobileWallet = userWalletsListRepository.userWalletsSync() .any { it is UserWallet.Hot } + val accountsCount = if (isAccountsModeEnabledUseCase.invokeSync()) { + singleAccountListSupplier(selectedWallet.walletId) + .first() + .accounts + .size + } else { + null + } analyticsEventsHandler.send( - WalletScreenAnalyticsEvent.MainScreen.ScreenOpened(hasMobileWallet), + WalletScreenAnalyticsEvent.MainScreen.ScreenOpened( + hasMobileWallet = hasMobileWallet, + accountsCount = accountsCount, + ), ) } } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt index ca2353b273..747e1364f5 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/child/wallet/model/intents/WalletContentClickIntents.kt @@ -196,11 +196,13 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( override fun onAccountExpandClick(account: Account) { val userWalletId = stateHolder.getSelectedWalletId() + analyticsEventHandler.send(MainScreenAnalyticsEvent.AccountShowTokens()) accountDependencies.expandedAccountsHolder.expandAccount(userWalletId, account.accountId) } override fun onAccountCollapseClick(account: Account) { val userWalletId = stateHolder.getSelectedWalletId() + analyticsEventHandler.send(MainScreenAnalyticsEvent.AccountHideTokens()) accountDependencies.expandedAccountsHolder.collapseAccount(userWalletId, account.accountId) } diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt index 5d679b0b59..317c4582c9 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt @@ -57,9 +57,13 @@ sealed class WalletScreenAnalyticsEvent { data class ScreenOpened( private val hasMobileWallet: Boolean, + private val accountsCount: Int?, ) : MainScreen( event = "Screen opened", - params = mapOf("Mobile Wallet" to if (hasMobileWallet) "Yes" else "No"), + params = buildMap { + put("Mobile Wallet", if (hasMobileWallet) "Yes" else "No") + if (accountsCount != null) put("Accounts Count", accountsCount.toString()) + }, ) data class NoticeFinishActivation( 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 76072cedae..e0a0182370 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 @@ -31,6 +31,7 @@ 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 @@ -319,6 +320,17 @@ internal class WcPairModel @Inject constructor( val selectedPortfolio = selectedPortfolio.replayCache.firstOrNull() val wallet = selectedPortfolio?.first ?: selectedUserWalletFlow.value val account = selectedPortfolio?.second?.account + + modelScope.launch { + if (selectorController.isAccountModeSync() && account != null) { + val derivationIndex = when (account) { + is Account.CryptoPortfolio -> account.derivationIndex.value + } + analytics.send(WcAnalyticAccountEvents.PairButtonConnect(derivationIndex)) + } else { + analytics.send(WcAnalyticEvents.PairButtonConnect()) + } + } wcPairUseCase.approve( WcSessionApprove( wallet = wallet,