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 fc00d6b5bc..d02be99d34 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 @@ -219,5 +219,7 @@ sealed class AnalyticsParam { const val ACTION = "Action" const val COLLECTIONS = "Collections" const val NFT = "Nft" + const val STANDARD = "Standard" + const val NO_COLLECTION = "No collection" } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/nft/converter/NFTSdkAssetIdentifierConverter.kt b/core/datasource/src/main/java/com/tangem/datasource/local/nft/converter/NFTSdkAssetIdentifierConverter.kt index bd93af8f19..b06cb3be83 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/nft/converter/NFTSdkAssetIdentifierConverter.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/nft/converter/NFTSdkAssetIdentifierConverter.kt @@ -16,7 +16,7 @@ object NFTSdkAssetIdentifierConverter : TwoWayConverter NFTAsset.Identifier.Solana( tokenAddress = value.tokenAddress, - cnft = value.cnft, + tokenStandard = value.tokenStandard, ) is SdkNFTAsset.Identifier.Unknown -> NFTAsset.Identifier.Unknown } @@ -32,7 +32,7 @@ object NFTSdkAssetIdentifierConverter : TwoWayConverter SdkNFTAsset.Identifier.Solana( tokenAddress = value.tokenAddress, - cnft = value.cnft, + tokenStandard = value.tokenStandard, ) is NFTAsset.Identifier.Unknown -> SdkNFTAsset.Identifier.Unknown } diff --git a/domain/nft/models/src/main/kotlin/com/tangem/domain/nft/models/NFTAsset.kt b/domain/nft/models/src/main/kotlin/com/tangem/domain/nft/models/NFTAsset.kt index f30b865df7..f83aec887a 100644 --- a/domain/nft/models/src/main/kotlin/com/tangem/domain/nft/models/NFTAsset.kt +++ b/domain/nft/models/src/main/kotlin/com/tangem/domain/nft/models/NFTAsset.kt @@ -68,7 +68,7 @@ data class NFTAsset( @Serializable data class Solana( val tokenAddress: String, - val cnft: Boolean, + val tokenStandard: Int?, ) : Identifier() { override val stringValue: String = tokenAddress } diff --git a/domain/nft/src/main/kotlin/com/tangem/domain/nft/analytics/NFTAnalyticsEvent.kt b/domain/nft/src/main/kotlin/com/tangem/domain/nft/analytics/NFTAnalyticsEvent.kt index 34bb1ab6f7..9ee3357e17 100644 --- a/domain/nft/src/main/kotlin/com/tangem/domain/nft/analytics/NFTAnalyticsEvent.kt +++ b/domain/nft/src/main/kotlin/com/tangem/domain/nft/analytics/NFTAnalyticsEvent.kt @@ -2,9 +2,12 @@ package com.tangem.domain.nft.analytics import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.core.analytics.models.AnalyticsParam.Key.BLOCKCHAIN +import com.tangem.core.analytics.models.AnalyticsParam.Key.STANDARD import com.tangem.core.analytics.models.AnalyticsParam.Key.COLLECTIONS import com.tangem.core.analytics.models.AnalyticsParam.Key.NFT +import com.tangem.core.analytics.models.AnalyticsParam.Key.NO_COLLECTION import com.tangem.core.analytics.models.AnalyticsParam.Key.STATE +import kotlin.collections.buildMap sealed class NFTAnalyticsEvent( event: String, @@ -17,19 +20,21 @@ sealed class NFTAnalyticsEvent( data class NFTListScreenOpened( val state: State, + val collectionsCount: Int, + val allAssetsCount: Int, + val noCollectionAssetsCount: Int, ) : NFTAnalyticsEvent( event = "NFT List Screen Opened", params = buildMap { put(STATE, state.value) - if (state is State.Full) { - put(COLLECTIONS, state.collectionsCount.toString()) - put(NFT, state.assetsCount.toString()) - } + put(COLLECTIONS, collectionsCount.toString()) + put(NFT, allAssetsCount.toString()) + put(NO_COLLECTION, noCollectionAssetsCount.toString()) }, ) { - sealed class State(val value: String) { - data object Empty : State("Empty") - data class Full(val assetsCount: Int, val collectionsCount: Int) : State("Full") + enum class State(val value: String) { + Empty("Empty"), + Full("Full"), } } @@ -52,7 +57,16 @@ sealed class NFTAnalyticsEvent( object Details { data class ScreenOpened( private val blockchain: String, - ) : NFTAnalyticsEvent(event = "NFT Details Screen Opened", params = mapOf(BLOCKCHAIN to blockchain)) + private val standard: String?, + ) : NFTAnalyticsEvent( + event = "NFT Details Screen Opened", + params = buildMap { + put(BLOCKCHAIN, blockchain) + standard?.let { + put(STANDARD, it) + } + }, + ) data object ButtonReadMore : NFTAnalyticsEvent(event = "Button - Read More") data object ButtonSeeAll : NFTAnalyticsEvent(event = "Button - See All") diff --git a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/model/NFTDetailsModel.kt b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/model/NFTDetailsModel.kt index 85bb073209..f20a708479 100644 --- a/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/model/NFTDetailsModel.kt +++ b/features/nft/impl/src/main/kotlin/com/tangem/features/nft/details/model/NFTDetailsModel.kt @@ -85,7 +85,17 @@ internal class NFTDetailsModel @Inject constructor( val bottomSheetNavigation: SlotNavigation = SlotNavigation() init { - analyticsEventHandler.send(NFTAnalyticsEvent.Details.ScreenOpened(params.nftAsset.network.name)) + analyticsEventHandler.send( + NFTAnalyticsEvent.Details.ScreenOpened( + blockchain = params.nftAsset.network.name, + standard = when (val id = params.nftAsset.id) { + is NFTAsset.Identifier.EVM -> id.contractType.name + is NFTAsset.Identifier.Solana -> id.tokenStandard?.toString() + is NFTAsset.Identifier.TON -> null + is NFTAsset.Identifier.Unknown -> null + }, + ), + ) initAppCurrency() subscribeToPriceChanges() } diff --git a/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/analytics/WalletSettingsAnalyticEvents.kt b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/analytics/WalletSettingsAnalyticEvents.kt new file mode 100644 index 0000000000..6c2fbd0ee0 --- /dev/null +++ b/features/wallet-settings/impl/src/main/kotlin/com/tangem/feature/walletsettings/analytics/WalletSettingsAnalyticEvents.kt @@ -0,0 +1,17 @@ +package com.tangem.feature.walletsettings.analytics + +import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.analytics.models.AnalyticsParam.Key.STATUS + +internal sealed class WalletSettingsAnalyticEvents( + category: String = "Settings / Wallet", + event: String, + params: Map = mapOf(), +) : AnalyticsEvent(category, event, params) { + + data class NftToggleSwitch(val enabled: AnalyticsParam.OnOffState) : WalletSettingsAnalyticEvents( + event = "NFT toggle switch", + params = mapOf(STATUS to enabled.value), + ) +} \ No newline at end of file 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 ebe302c2e7..b85bb4de06 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 @@ -6,6 +6,8 @@ import com.arkivanov.decompose.router.slot.SlotNavigation import com.arkivanov.decompose.router.slot.activate import com.tangem.common.routing.AppRoute import com.tangem.core.analytics.api.AnalyticsEventHandler +import com.tangem.core.analytics.models.AnalyticsParam.OnOffState.Off +import com.tangem.core.analytics.models.AnalyticsParam.OnOffState.On import com.tangem.core.analytics.utils.AnalyticsContextProxy import com.tangem.core.decompose.di.ModelScoped import com.tangem.core.decompose.model.Model @@ -29,6 +31,7 @@ import com.tangem.domain.wallets.models.isMultiCurrency import com.tangem.domain.wallets.models.requireColdWallet import com.tangem.domain.wallets.usecase.* import com.tangem.feature.walletsettings.analytics.Settings +import com.tangem.feature.walletsettings.analytics.WalletSettingsAnalyticEvents import com.tangem.feature.walletsettings.component.WalletSettingsComponent import com.tangem.feature.walletsettings.entity.DialogConfig import com.tangem.feature.walletsettings.entity.NetworksAvailableForNotificationBSConfig @@ -214,6 +217,11 @@ internal class WalletSettingsModel @Inject constructor( } else { disableWalletNFTUseCase.invoke(params.userWalletId) } + analyticsEventHandler.send( + WalletSettingsAnalyticEvents.NftToggleSwitch( + enabled = if (isChecked) On else Off, + ), + ) } } 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 dacede164b..f125cd626d 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 @@ -238,19 +238,31 @@ internal class WalletContentClickIntentsImplementor @Inject constructor( override fun onNFTClick(userWallet: UserWallet) { val selectedWallet = stateHolder.getSelectedWallet() as? WalletState.MultiCurrency.Content ?: return - val analyticsState = when (val nftState = selectedWallet.nftState) { - is WalletNFTItemUM.Content -> NFTAnalyticsEvent.NFTListScreenOpened.State.Full( - assetsCount = nftState.assetsCount, - collectionsCount = nftState.collectionsCount, - ) - is WalletNFTItemUM.Empty -> NFTAnalyticsEvent.NFTListScreenOpened.State.Empty + when (val state = selectedWallet.nftState) { + is WalletNFTItemUM.Content -> { + analyticsEventHandler.send( + NFTAnalyticsEvent.NFTListScreenOpened( + state = NFTAnalyticsEvent.NFTListScreenOpened.State.Full, + allAssetsCount = state.allAssetsCount, + collectionsCount = state.collectionsCount, + noCollectionAssetsCount = state.noCollectionAssetsCount, + ), + ) + } + is WalletNFTItemUM.Empty -> { + analyticsEventHandler.send( + NFTAnalyticsEvent.NFTListScreenOpened( + state = NFTAnalyticsEvent.NFTListScreenOpened.State.Empty, + allAssetsCount = 0, + collectionsCount = 0, + noCollectionAssetsCount = 0, + ), + ) + } is WalletNFTItemUM.Failed, is WalletNFTItemUM.Hidden, is WalletNFTItemUM.Loading, - -> null - } - analyticsState?.let { - analyticsEventHandler.send(NFTAnalyticsEvent.NFTListScreenOpened(analyticsState)) + -> Unit } router.openNFT(userWallet) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt index 08937391da..9a3d8d6a28 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/common/preview/WalletScreenPreviewData.kt @@ -123,7 +123,8 @@ internal object WalletScreenPreviewData { nftState = WalletNFTItemUM.Content( previews = persistentListOf(WalletNFTItemUM.Content.CollectionPreview.Image("img1")), collectionsCount = 1, - assetsCount = 3, + allAssetsCount = 3, + noCollectionAssetsCount = 0, isFlickering = false, onItemClick = { }, ), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNFTItemUM.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNFTItemUM.kt index f4406d5dc5..d6fb28e300 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNFTItemUM.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNFTItemUM.kt @@ -19,7 +19,8 @@ sealed class WalletNFTItemUM { data class Content( val previews: ImmutableList, val collectionsCount: Int, - val assetsCount: Int, + val allAssetsCount: Int, + val noCollectionAssetsCount: Int, val isFlickering: Boolean, val onItemClick: () -> Unit, ) : WalletNFTItemUM() { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetNFTCollectionsTransformer.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetNFTCollectionsTransformer.kt index b749ffccf3..7f47fb0a15 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetNFTCollectionsTransformer.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/transformers/SetNFTCollectionsTransformer.kt @@ -52,8 +52,24 @@ internal class SetNFTCollectionsTransformer( .toPersistentList() }, collectionsCount = collections.size, - assetsCount = collections - .sumOf { it.count }, + allAssetsCount = collections.sumOf { it.count }, + noCollectionAssetsCount = collections.sumOf { collection -> + when (val collectionId = collection.id) { + is NFTCollection.Identifier.Solana -> + collection + .count + .takeIf { collectionId.collectionAddress == null } + ?: 0 + is NFTCollection.Identifier.TON -> + collection + .count + .takeIf { collectionId.contractAddress == null } + ?: 0 + is NFTCollection.Identifier.EVM, + is NFTCollection.Identifier.Unknown, + -> 0 + } + }, isFlickering = false, onItemClick = onItemClick, ) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem.kt index 079f2876e1..b79c1832b5 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/WalletNFTItem.kt @@ -108,7 +108,7 @@ private fun WalletNFTItemContent(state: WalletNFTItemUM.Content, onClick: () -> Text( text = stringResourceSafe( id = R.string.nft_wallet_count, - state.assetsCount, + state.allAssetsCount, state.collectionsCount, ), style = TangemTheme.typography.caption2.applyBladeBrush( @@ -411,8 +411,9 @@ private class WalletNFTItemProvider : CollectionPreviewParameterProvider