diff --git a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt index 4905038b88..b8b0a9e92e 100644 --- a/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt +++ b/app/src/main/java/com/tangem/tap/ApplicationEntryPoint.kt @@ -7,6 +7,7 @@ import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.common.routing.AppRouter import com.tangem.core.abtests.manager.ABTestsManager import com.tangem.core.analytics.filter.OneTimeEventFilter +import com.tangem.core.analytics.paramsinterceptor.SendTransactionSignerInfoInterceptor import com.tangem.core.analytics.utils.TrackingContextProxy import com.tangem.core.configtoggle.blockchain.ExcludedBlockchainsManager import com.tangem.core.configtoggle.feature.FeatureTogglesManager @@ -151,4 +152,6 @@ interface ApplicationEntryPoint { fun getAppsFlyerClientFactory(): AppsFlyerClient.Factory fun getScanFailsRequester(): ScanFailsRequester + + fun getSendTransactionSignerInfoInterceptor(): SendTransactionSignerInfoInterceptor } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/TangemApplication.kt b/app/src/main/java/com/tangem/tap/TangemApplication.kt index 39c1f273db..46f0aff6cb 100644 --- a/app/src/main/java/com/tangem/tap/TangemApplication.kt +++ b/app/src/main/java/com/tangem/tap/TangemApplication.kt @@ -18,13 +18,8 @@ import com.tangem.blockchainsdk.utils.ExcludedBlockchains import com.tangem.common.routing.AppRouter import com.tangem.core.abtests.manager.ABTestsManager import com.tangem.core.analytics.Analytics -import com.tangem.core.analytics.api.ParamsInterceptor import com.tangem.core.analytics.filter.AppsFlyerEventFilter import com.tangem.core.analytics.filter.OneTimeEventFilter -import com.tangem.core.analytics.models.AnalyticsEvent -import com.tangem.core.analytics.models.AnalyticsParam -import com.tangem.core.analytics.models.Basic -import com.tangem.core.analytics.models.Basic.TransactionSent.WalletForm import com.tangem.core.configtoggle.blockchain.ExcludedBlockchainsManager import com.tangem.core.configtoggle.feature.FeatureTogglesManager import com.tangem.core.decompose.ui.UiMessageSender @@ -238,6 +233,9 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration. private val scanFailsRequester get() = entryPoint.getScanFailsRequester() + private val sendTransactionSignerInfoInterceptor + get() = entryPoint.getSendTransactionSignerInfoInterceptor() + // endregion private val appScope = MainScope() @@ -424,23 +422,7 @@ open class TangemApplication : Application(), ImageLoaderFactory, Configuration. jsonConverter = MoshiConverter.sdkMoshiConverter, ) - Analytics.addParamsInterceptor( - interceptor = object : ParamsInterceptor { - override fun id(): String = "SendTransactionSignerInfoInterceptor" - - override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = event is Basic.TransactionSent - - override fun intercept(params: MutableMap) { - val isLastSignWithRing = store.state.globalState.isLastSignWithRing - - params[AnalyticsParam.WALLET_FORM] = if (isLastSignWithRing) { - WalletForm.Ring.name - } else { - WalletForm.Card.name - } - } - }, - ) + Analytics.addParamsInterceptor(interceptor = sendTransactionSignerInfoInterceptor) factory.build(Analytics, buildData) } diff --git a/app/src/main/java/com/tangem/tap/common/libs/blockchainsdk/DefaultTransactionSignerFactory.kt b/app/src/main/java/com/tangem/tap/common/libs/blockchainsdk/DefaultTransactionSignerFactory.kt index e31c519069..fced2e9ee9 100644 --- a/app/src/main/java/com/tangem/tap/common/libs/blockchainsdk/DefaultTransactionSignerFactory.kt +++ b/app/src/main/java/com/tangem/tap/common/libs/blockchainsdk/DefaultTransactionSignerFactory.kt @@ -3,13 +3,15 @@ package com.tangem.tap.common.libs.blockchainsdk import com.tangem.Message import com.tangem.TangemSdk import com.tangem.blockchain.common.TransactionSigner +import com.tangem.core.analytics.models.Basic.TransactionSent.WalletForm +import com.tangem.core.analytics.store.LastSignedWalletFormStore import com.tangem.data.card.TransactionSignerFactory import com.tangem.domain.card.models.TwinKey -import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.domain.TangemSigner -import com.tangem.tap.store -internal class DefaultTransactionSignerFactory : TransactionSignerFactory { +internal class DefaultTransactionSignerFactory( + private val lastSignedWalletFormStore: LastSignedWalletFormStore, +) : TransactionSignerFactory { override fun createTransactionSigner(cardId: String?, sdk: TangemSdk, twinKey: TwinKey?): TransactionSigner { return TangemSigner( @@ -18,7 +20,9 @@ internal class DefaultTransactionSignerFactory : TransactionSignerFactory { initialMessage = Message(), twinKey = twinKey, ) { signResponse -> - store.dispatch(action = GlobalAction.IsSignWithRing(signResponse.isRing)) + lastSignedWalletFormStore.update( + if (signResponse.isRing) WalletForm.Ring else WalletForm.Card, + ) } } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/di/libs/blockchainsdk/TransactionSignerFactoryModule.kt b/app/src/main/java/com/tangem/tap/di/libs/blockchainsdk/TransactionSignerFactoryModule.kt index d0997c9038..badf261801 100644 --- a/app/src/main/java/com/tangem/tap/di/libs/blockchainsdk/TransactionSignerFactoryModule.kt +++ b/app/src/main/java/com/tangem/tap/di/libs/blockchainsdk/TransactionSignerFactoryModule.kt @@ -1,5 +1,6 @@ package com.tangem.tap.di.libs.blockchainsdk +import com.tangem.core.analytics.store.LastSignedWalletFormStore import com.tangem.data.card.TransactionSignerFactory import com.tangem.tap.common.libs.blockchainsdk.DefaultTransactionSignerFactory import dagger.Module @@ -17,7 +18,9 @@ internal class TransactionSignerFactoryModule { @Provides @Singleton - fun provideTransactionSignerFactory(): TransactionSignerFactory { - return DefaultTransactionSignerFactory() + fun provideTransactionSignerFactory( + lastSignedWalletFormStore: LastSignedWalletFormStore, + ): TransactionSignerFactory { + return DefaultTransactionSignerFactory(lastSignedWalletFormStore) } } \ No newline at end of file diff --git a/core/analytics/build.gradle.kts b/core/analytics/build.gradle.kts index 819db765b9..60348ec1a4 100644 --- a/core/analytics/build.gradle.kts +++ b/core/analytics/build.gradle.kts @@ -4,6 +4,10 @@ plugins { id("configuration") } +tasks.withType().configureEach { + useJUnitPlatform() +} + dependencies { /** DI */ @@ -25,4 +29,8 @@ dependencies { /** For calculating user id hash */ implementation(tangemDeps.card.core) + + /** Tests */ + testImplementation(projects.test.core) + testRuntimeOnly(deps.test.junit5.engine) } \ No newline at end of file diff --git a/core/analytics/src/main/java/com/tangem/core/analytics/di/LastSignedWalletFormStoreModule.kt b/core/analytics/src/main/java/com/tangem/core/analytics/di/LastSignedWalletFormStoreModule.kt new file mode 100644 index 0000000000..cc0f32e6ac --- /dev/null +++ b/core/analytics/src/main/java/com/tangem/core/analytics/di/LastSignedWalletFormStoreModule.kt @@ -0,0 +1,16 @@ +package com.tangem.core.analytics.di + +import com.tangem.core.analytics.paramsinterceptor.SendTransactionSignerInfoInterceptor +import com.tangem.core.analytics.store.LastSignedWalletFormStore +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent + +@Module +@InstallIn(SingletonComponent::class) +internal interface LastSignedWalletFormStoreModule { + + @Binds + fun bindLastSignedWalletFormStore(impl: SendTransactionSignerInfoInterceptor): LastSignedWalletFormStore +} \ No newline at end of file diff --git a/core/analytics/src/main/java/com/tangem/core/analytics/paramsinterceptor/SendTransactionSignerInfoInterceptor.kt b/core/analytics/src/main/java/com/tangem/core/analytics/paramsinterceptor/SendTransactionSignerInfoInterceptor.kt new file mode 100644 index 0000000000..ee56dca5cf --- /dev/null +++ b/core/analytics/src/main/java/com/tangem/core/analytics/paramsinterceptor/SendTransactionSignerInfoInterceptor.kt @@ -0,0 +1,34 @@ +package com.tangem.core.analytics.paramsinterceptor + +import com.tangem.core.analytics.api.ParamsInterceptor +import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.analytics.models.Basic +import com.tangem.core.analytics.store.LastSignedWalletFormStore +import kotlinx.coroutines.flow.MutableStateFlow +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class SendTransactionSignerInfoInterceptor @Inject constructor() : + ParamsInterceptor, + LastSignedWalletFormStore { + + private val walletForm = MutableStateFlow(Basic.TransactionSent.WalletForm.Card) + + override fun update(form: Basic.TransactionSent.WalletForm) { + walletForm.value = form + } + + override fun id(): String = ID + + override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = event is Basic.TransactionSent + + override fun intercept(params: MutableMap) { + params[AnalyticsParam.WALLET_FORM] = walletForm.value.name + } + + private companion object { + const val ID = "SendTransactionSignerInfoInterceptor" + } +} \ No newline at end of file diff --git a/core/analytics/src/main/java/com/tangem/core/analytics/store/LastSignedWalletFormStore.kt b/core/analytics/src/main/java/com/tangem/core/analytics/store/LastSignedWalletFormStore.kt new file mode 100644 index 0000000000..b44f753e15 --- /dev/null +++ b/core/analytics/src/main/java/com/tangem/core/analytics/store/LastSignedWalletFormStore.kt @@ -0,0 +1,8 @@ +package com.tangem.core.analytics.store + +import com.tangem.core.analytics.models.Basic + +interface LastSignedWalletFormStore { + + fun update(form: Basic.TransactionSent.WalletForm) +} \ No newline at end of file diff --git a/core/analytics/src/test/kotlin/com/tangem/core/analytics/paramsinterceptor/SendTransactionSignerInfoInterceptorTest.kt b/core/analytics/src/test/kotlin/com/tangem/core/analytics/paramsinterceptor/SendTransactionSignerInfoInterceptorTest.kt new file mode 100644 index 0000000000..d1f6f22bf2 --- /dev/null +++ b/core/analytics/src/test/kotlin/com/tangem/core/analytics/paramsinterceptor/SendTransactionSignerInfoInterceptorTest.kt @@ -0,0 +1,83 @@ +package com.tangem.core.analytics.paramsinterceptor + +import com.google.common.truth.Truth +import com.tangem.core.analytics.models.AnalyticsEvent +import com.tangem.core.analytics.models.AnalyticsParam +import com.tangem.core.analytics.models.Basic +import io.mockk.mockk +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +internal class SendTransactionSignerInfoInterceptorTest { + + private lateinit var interceptor: SendTransactionSignerInfoInterceptor + + @BeforeEach + fun setUp() { + interceptor = SendTransactionSignerInfoInterceptor() + } + + @Test + fun `id returns stable identifier`() { + Truth.assertThat(interceptor.id()).isEqualTo("SendTransactionSignerInfoInterceptor") + } + + @Test + fun `canBeAppliedTo returns true for TransactionSent event`() { + val event = mockk() + + Truth.assertThat(interceptor.canBeAppliedTo(event)).isTrue() + } + + @Test + fun `canBeAppliedTo returns false for any other event`() { + val event = mockk() + + Truth.assertThat(interceptor.canBeAppliedTo(event)).isFalse() + } + + @Test + fun `intercept writes Card by default`() { + val params = mutableMapOf() + + interceptor.intercept(params) + + Truth.assertThat(params[AnalyticsParam.WALLET_FORM]) + .isEqualTo(Basic.TransactionSent.WalletForm.Card.name) + } + + @Test + fun `intercept writes last updated wallet form`() { + interceptor.update(Basic.TransactionSent.WalletForm.Ring) + val params = mutableMapOf() + + interceptor.intercept(params) + + Truth.assertThat(params[AnalyticsParam.WALLET_FORM]) + .isEqualTo(Basic.TransactionSent.WalletForm.Ring.name) + } + + @Test + fun `update overrides previous wallet form`() { + interceptor.update(Basic.TransactionSent.WalletForm.Ring) + interceptor.update(Basic.TransactionSent.WalletForm.Card) + val params = mutableMapOf() + + interceptor.intercept(params) + + Truth.assertThat(params[AnalyticsParam.WALLET_FORM]) + .isEqualTo(Basic.TransactionSent.WalletForm.Card.name) + } + + @Test + fun `intercept preserves other params`() { + val params = mutableMapOf("Source" to "Send") + + interceptor.intercept(params) + + Truth.assertThat(params).containsEntry("Source", "Send") + Truth.assertThat(params).containsKey(AnalyticsParam.WALLET_FORM) + } +} \ No newline at end of file