diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt index cb500685e1..95d4585b71 100644 --- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt +++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt @@ -147,6 +147,7 @@ internal class ChildFactory @Inject constructor( val source = when (route.source) { AppRoute.ManageTokens.Source.SETTINGS -> ManageTokensSource.SETTINGS AppRoute.ManageTokens.Source.STORIES -> ManageTokensSource.STORIES + AppRoute.ManageTokens.Source.ACCOUNT -> ManageTokensSource.ACCOUNT } val mode = when (val portfolio = route.portfolioId) { diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt index 4b9bd5496d..a514a89100 100644 --- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt +++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt @@ -138,6 +138,7 @@ sealed class AppRoute(val path: String) : Route { enum class Source { STORIES, SETTINGS, + ACCOUNT, } } 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 986d808190..70e26afdb7 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 @@ -284,6 +284,7 @@ sealed class AnalyticsParam { const val ENS = "ENS" const val ENS_ADDRESS = "ENS Address" const val ACCOUNT_DERIVATION_FROM = "Account Derivation (from)" + const val ACCOUNT_DERIVATION_TO = "Account Derivation (to)" const val FEE_TOKEN = "Fee Token" const val ACCOUNT_DERIVATION = "Account Derivation" } 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 index 02d6dd5ae5..a1873a0097 100644 --- 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 @@ -1,6 +1,7 @@ package com.tangem.features.account.analytics import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.core.analytics.models.AnalyticsParam import com.tangem.domain.models.account.AccountName import com.tangem.domain.models.account.CryptoPortfolioIcon import com.tangem.features.account.AccountCreateEditComponent @@ -15,20 +16,48 @@ sealed class AccountSettingsAnalyticEvents( event = "Account Settings Screen Opened", ) - class ButtonManageTokens : AccountSettingsAnalyticEvents( + class ButtonManageTokens( + accountDerivation: Int?, + ) : AccountSettingsAnalyticEvents( event = "Button - Manage Tokens", + params = buildMap { + accountDerivation?.let { + put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) + } + }, ) - class ButtonArchiveAccount : AccountSettingsAnalyticEvents( + class ButtonArchiveAccount( + accountDerivation: Int?, + ) : AccountSettingsAnalyticEvents( event = "Button - Archive Account", + params = buildMap { + accountDerivation?.let { + put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) + } + }, ) - class ButtonArchiveAccountConfirmation : AccountSettingsAnalyticEvents( + class ButtonArchiveAccountConfirmation( + accountDerivation: Int?, + ) : AccountSettingsAnalyticEvents( event = "Button - Archive Account Confirmation", + params = buildMap { + accountDerivation?.let { + put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) + } + }, ) - class ButtonCancelAccountArchivation : AccountSettingsAnalyticEvents( + class ButtonCancelAccountArchivation( + accountDerivation: Int?, + ) : AccountSettingsAnalyticEvents( event = "Button - Cancel Account Archivation", + params = buildMap { + accountDerivation?.let { + put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) + } + }, ) class AccountArchived : AccountSettingsAnalyticEvents( @@ -39,13 +68,21 @@ sealed class AccountSettingsAnalyticEvents( event = "Button - Edit", ) - class AccountEditScreenOpened : AccountSettingsAnalyticEvents( + class AccountEditScreenOpened( + accountDerivation: Int?, + ) : AccountSettingsAnalyticEvents( event = "Account Edit Screen Opened", + params = buildMap { + accountDerivation?.let { + put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) + } + }, ) class ButtonSave( val name: AccountName, val icon: CryptoPortfolioIcon, + accountDerivation: Int?, ) : AccountSettingsAnalyticEvents( event = "Button - Save", params = buildMap { @@ -56,13 +93,16 @@ sealed class AccountSettingsAnalyticEvents( put("Name", accountName) put("Color", icon.color.name) put("Icon", icon.value.name) + accountDerivation?.let { + put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) + } }, ) class ButtonAddNewAccount( val name: AccountName, val icon: CryptoPortfolioIcon, - val derivationIndex: Int, + accountDerivation: Int?, ) : AccountSettingsAnalyticEvents( event = "Button - Add New Account", params = buildMap { @@ -73,18 +113,24 @@ sealed class AccountSettingsAnalyticEvents( put("Name", accountName) put("Color", icon.color.name) put("Icon", icon.value.name) - put("Derivation", derivationIndex.toString()) + accountDerivation?.let { + put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) + } }, ) class AccountError( val source: Source, val error: String, + accountDerivation: Int?, ) : AccountSettingsAnalyticEvents( event = "Account Error", params = buildMap { put("Error", error) put("Source", source.value) + accountDerivation?.let { + put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) + } }, ) 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 index 165fe01945..a2d4460b74 100644 --- 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 @@ -1,6 +1,7 @@ package com.tangem.features.account.analytics import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.core.analytics.models.AnalyticsParam sealed class WalletSettingsAccountAnalyticEvents( category: String = "Settings / Wallet Settings", @@ -16,11 +17,23 @@ sealed class WalletSettingsAccountAnalyticEvents( event = "Account Recovered", ) - class ArchivedAccountsScreenOpened : WalletSettingsAccountAnalyticEvents( + class ArchivedAccountsScreenOpened( + private val accountsCount: Int, + ) : WalletSettingsAccountAnalyticEvents( event = "Archived Accounts Screen Opened", + params = buildMap { + put("Accounts Count", accountsCount.toString()) + }, ) - class ButtonRecoverAccount : WalletSettingsAccountAnalyticEvents( + class ButtonRecoverAccount( + accountDerivation: Int?, + ) : WalletSettingsAccountAnalyticEvents( event = "Button - Recover Account", + params = buildMap { + accountDerivation?.let { + put(AnalyticsParam.ACCOUNT_DERIVATION, it.toString()) + } + }, ) } \ 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 6b888f2693..cde8aabbcb 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 @@ -13,9 +13,9 @@ import com.tangem.core.ui.message.DialogMessage import com.tangem.core.ui.message.EventMessageAction import com.tangem.core.ui.message.ToastMessage import com.tangem.domain.account.models.AccountList +import com.tangem.domain.account.models.ArchivedAccount 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 @@ -53,7 +53,6 @@ internal class ArchivedAccountListModel @Inject constructor( private val getArchivedAccountsJob = JobHolder() init { - analyticsEventHandler.send(WalletSettingsAccountAnalyticEvents.ArchivedAccountsScreenOpened()) getArchivedAccounts() } @@ -69,14 +68,16 @@ internal class ArchivedAccountListModel @Inject constructor( umBuilder.mapContent( accounts = content, onCloseClick = onCloseClick, - onRecoverClick = { recoverCryptoPortfolio(accountId = it.accountId) }, + onRecoverClick = { recoverCryptoPortfolio(account = it) }, ) }, ifContent = { content -> + val event = WalletSettingsAccountAnalyticEvents.ArchivedAccountsScreenOpened(content.size) + analyticsEventHandler.send(event) umBuilder.mapContent( accounts = content, onCloseClick = onCloseClick, - onRecoverClick = { recoverCryptoPortfolio(accountId = it.accountId) }, + onRecoverClick = { recoverCryptoPortfolio(account = it) }, ) }, ifError = { error -> @@ -97,13 +98,15 @@ internal class ArchivedAccountListModel @Inject constructor( .saveIn(getArchivedAccountsJob) } - private fun recoverCryptoPortfolio(accountId: AccountId) = modelScope.launch { - analyticsEventHandler.send(WalletSettingsAccountAnalyticEvents.ButtonRecoverAccount()) - uiState.update { it.toggleProgress(accountId, isLoading = true) } + private fun recoverCryptoPortfolio(account: ArchivedAccount) = modelScope.launch { + analyticsEventHandler.send( + WalletSettingsAccountAnalyticEvents.ButtonRecoverAccount(account.derivationIndex.value), + ) + uiState.update { it.toggleProgress(account.accountId, isLoading = true) } val result = withContext(dispatchers.default) { - recoverCryptoPortfolioUseCase(accountId) + recoverCryptoPortfolioUseCase(account.accountId) } - uiState.update { it.toggleProgress(accountId, isLoading = false) } + uiState.update { it.toggleProgress(account.accountId, isLoading = false) } result .onLeft(::handleRecoverError) .onRight { 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 ebb0f334f3..d100998aca 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 @@ -25,6 +25,7 @@ import com.tangem.domain.account.usecase.GetUnoccupiedAccountIndexUseCase import com.tangem.domain.account.usecase.UpdateCryptoPortfolioUseCase import com.tangem.domain.models.account.CryptoPortfolioIcon import com.tangem.domain.models.account.DerivationIndex +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 @@ -69,10 +70,13 @@ internal class AccountCreateEditModel @Inject constructor( field = MutableStateFlow(value = getInitialState()) init { - if (params is AccountCreateEditComponent.Params.Create) { - updateDerivationInfo(userWalletId = params.userWalletId) - } else { - analyticsEventHandler.send(AccountSettingsAnalyticEvents.AccountEditScreenOpened()) + when (params) { + is AccountCreateEditComponent.Params.Create -> updateDerivationInfo(userWalletId = params.userWalletId) + is AccountCreateEditComponent.Params.Edit -> { + val derivationIndex = params.account.derivationIndex?.value + val event = AccountSettingsAnalyticEvents.AccountEditScreenOpened(derivationIndex) + analyticsEventHandler.send(event) + } } } @@ -116,7 +120,7 @@ internal class AccountCreateEditModel @Inject constructor( val event = AccountSettingsAnalyticEvents.ButtonAddNewAccount( name = name, icon = icon, - derivationIndex = derivationIndex.value, + accountDerivation = derivationIndex.value, ) analyticsEventHandler.send(event) @@ -130,7 +134,7 @@ internal class AccountCreateEditModel @Inject constructor( uiState.value = uiState.value.toggleProgress(showProgress = false) result - .onLeft(::handleAddAccountError) + .onLeft { error -> handleAddAccountError(error, derivationIndex.value) } .onRight { analyticsEventHandler.send(WalletSettingsAccountAnalyticEvents.AccountCreated()) showMessage(R.string.account_create_success_message) @@ -138,9 +142,10 @@ internal class AccountCreateEditModel @Inject constructor( } } - private fun handleAddAccountError(error: AddCryptoPortfolioUseCase.Error) { + private fun handleAddAccountError(error: AddCryptoPortfolioUseCase.Error, derivationIndex: Int) { val event = AccountSettingsAnalyticEvents.AccountError( source = params.toAnalyticSource(), + accountDerivation = derivationIndex, error = when (error) { is AddCryptoPortfolioUseCase.Error.AccountListRequirementsNotMet -> error.cause.tag is AddCryptoPortfolioUseCase.Error.DataOperationFailed -> error.cause.message.orEmpty() @@ -165,7 +170,8 @@ internal class AccountCreateEditModel @Inject constructor( val icon = CryptoPortfolioIconConverter.convertBack(state.account.portfolioIcon) val isNewName = name != params.account.accountName val isNewIcon = icon != params.account.portfolioIcon - analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonSave(name, icon)) + val derivationIndex = params.account.derivationIndex?.value + analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonSave(name, icon, derivationIndex)) uiState.value = uiState.value.toggleProgress(showProgress = true) val result = updateCryptoPortfolioUseCase( @@ -176,16 +182,17 @@ internal class AccountCreateEditModel @Inject constructor( uiState.value = uiState.value.toggleProgress(showProgress = false) result - .onLeft(::handleEditAccountError) + .onLeft { error -> handleEditAccountError(error, params.account.derivationIndex?.value) } .onRight { showMessage(R.string.account_edit_success_message) router.pop() } } - private fun handleEditAccountError(error: UpdateCryptoPortfolioUseCase.Error) { + private fun handleEditAccountError(error: UpdateCryptoPortfolioUseCase.Error, derivationIndex: Int?) { val event = AccountSettingsAnalyticEvents.AccountError( source = params.toAnalyticSource(), + accountDerivation = derivationIndex, error = when (error) { is UpdateCryptoPortfolioUseCase.Error.AccountListRequirementsNotMet -> error.cause.tag is UpdateCryptoPortfolioUseCase.Error.DataOperationFailed -> error.cause.message.orEmpty() 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 c4b4297c35..47b06df25c 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 @@ -19,6 +19,7 @@ import com.tangem.domain.account.status.usecase.ArchiveCryptoPortfolioUseCase import com.tangem.domain.account.supplier.SingleAccountSupplier import com.tangem.domain.models.PortfolioId import com.tangem.domain.models.account.Account +import com.tangem.domain.models.account.derivationIndex import com.tangem.domain.models.wallet.isMultiCurrency import com.tangem.domain.wallets.usecase.GetUserWalletUseCase import com.tangem.features.account.AccountDetailsComponent @@ -65,15 +66,19 @@ internal class AccountDetailsModel @Inject constructor( private fun onManageTokensClick(account: Account) { val route = AppRoute.ManageTokens( - source = AppRoute.ManageTokens.Source.SETTINGS, + source = AppRoute.ManageTokens.Source.ACCOUNT, portfolioId = PortfolioId(account.accountId), ) - analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonManageTokens()) + analyticsEventHandler.send( + AccountSettingsAnalyticEvents.ButtonManageTokens(account.derivationIndex?.value), + ) router.push(route) } private fun onArchiveAccountClick() { - analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonArchiveAccount()) + val accountDerivation = params.account.derivationIndex?.value + val event = AccountSettingsAnalyticEvents.ButtonArchiveAccount(accountDerivation) + analyticsEventHandler.send(event) confirmArchiveDialog() } @@ -81,7 +86,9 @@ internal class AccountDetailsModel @Inject constructor( val secondAction = EventMessageAction( title = resourceReference(R.string.common_cancel), onClick = { - analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonCancelAccountArchivation()) + val accountDerivation = params.account.derivationIndex?.value + val event = AccountSettingsAnalyticEvents.ButtonCancelAccountArchivation(accountDerivation) + analyticsEventHandler.send(event) }, ) val firstAction = EventMessageAction( @@ -100,7 +107,9 @@ internal class AccountDetailsModel @Inject constructor( } private fun archiveCryptoPortfolio() = modelScope.launch { - analyticsEventHandler.send(AccountSettingsAnalyticEvents.ButtonArchiveAccountConfirmation()) + val accountDerivation = params.account.derivationIndex?.value + val event = AccountSettingsAnalyticEvents.ButtonArchiveAccountConfirmation(accountDerivation) + analyticsEventHandler.send(event) uiState.update { it.toggleProgress(true) } archiveCryptoPortfolioUseCase(accountId) .onLeft { error -> @@ -119,6 +128,7 @@ internal class AccountDetailsModel @Inject constructor( val event = AccountSettingsAnalyticEvents.AccountError( source = AccountSettingsAnalyticEvents.Source.ARCHIVE, error = error.tag, + accountDerivation = params.account.derivationIndex?.value, ) analyticsEventHandler.send(event) val titleRes: Int diff --git a/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/component/ManageTokensSource.kt b/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/component/ManageTokensSource.kt index 3c5fa79e29..ca4d8956b2 100644 --- a/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/component/ManageTokensSource.kt +++ b/features/manage-tokens/api/src/main/kotlin/com/tangem/features/managetokens/component/ManageTokensSource.kt @@ -6,7 +6,8 @@ import com.tangem.domain.models.wallet.UserWalletId enum class ManageTokensSource(val analyticsName: String) { STORIES(analyticsName = "Stories"), ONBOARDING(analyticsName = "Onboarding"), - SETTINGS(analyticsName = "Settings"), + SETTINGS(analyticsName = "Wallet Settings"), + ACCOUNT(analyticsName = "Account"), SEND_VIA_SWAP(analyticsName = "SendViaSwap"), } 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 8aca31698c..213c7d7b63 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 @@ -2,6 +2,7 @@ package com.tangem.features.swap.v2.impl.sendviaswap.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.FEE_TYPE import com.tangem.core.analytics.models.AnalyticsParam.Key.PROVIDER import com.tangem.core.analytics.models.AnalyticsParam.Key.RECEIVE_BLOCKCHAIN @@ -32,7 +33,7 @@ internal sealed class SendWithSwapAnalyticEvents( 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()) + if (fromDerivationIndex != null) put(ACCOUNT_DERIVATION_FROM, fromDerivationIndex.toString()) }, ), AppsFlyerIncludedEvent 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 408988e88e..ebcb1465a8 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 @@ -2,6 +2,8 @@ package com.tangem.feature.swap.analytics import com.tangem.common.ui.bottomsheet.permission.state.ApproveType 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.ACCOUNT_DERIVATION_TO import com.tangem.core.analytics.models.AnalyticsParam.Key.BLOCKCHAIN import com.tangem.core.analytics.models.AnalyticsParam.Key.ERROR_CODE import com.tangem.core.analytics.models.AnalyticsParam.Key.ERROR_MESSAGE @@ -105,8 +107,8 @@ sealed class SwapEvents( 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()) + if (fromDerivationIndex != null) put(ACCOUNT_DERIVATION_FROM, fromDerivationIndex.toString()) + if (toDerivationIndex != null) put(ACCOUNT_DERIVATION_TO, toDerivationIndex.toString()) put(FEE_TOKEN, feeToken) }, ), AppsFlyerIncludedEvent