From b0d9a8957f5be94c903f9a8ea4749b84d97bf7b8 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 15 Nov 2022 00:17:49 +0500 Subject: [PATCH 01/22] Updated on 2026-08-14 --- .../com/tangem/tap/common/DialogManager.kt | 3 ++- .../note/redux/OnboardingNoteMiddleware.kt | 12 +++++++++++- .../tap/features/wallet/redux/WalletAction.kt | 5 ++++- .../middlewares/WalletDialogsMiddleware.kt | 2 +- .../wallet/redux/models/WalletDialog.kt | 5 ++++- ...ssianCardholdersWarningBottomSheetDialog.kt | 18 ++++++++++++++++-- 6 files changed, 38 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/DialogManager.kt b/app/src/main/java/com/tangem/tap/common/DialogManager.kt index ed8d4542b9..4d1c3734ea 100644 --- a/app/src/main/java/com/tangem/tap/common/DialogManager.kt +++ b/app/src/main/java/com/tangem/tap/common/DialogManager.kt @@ -152,7 +152,8 @@ class DialogManager : StoreSubscriber { primaryButtonRes = state.dialog.primaryButtonRes, primaryButtonAction = state.dialog.onOk, ) - is WalletDialog.RussianCardholdersWarningDialog -> RussianCardholdersWarningBottomSheetDialog(context) + is WalletDialog.RussianCardholdersWarningDialog -> + RussianCardholdersWarningBottomSheetDialog(context, state.dialog.data) else -> null } dialog?.show() diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt index ef0c5a743a..5ecccaa431 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt @@ -10,6 +10,7 @@ import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.extensions.dispatchDebugErrorNotification import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchErrorNotification +import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchOpenUrl import com.tangem.tap.common.extensions.getAddressData import com.tangem.tap.common.extensions.getTopUpUrl @@ -24,8 +25,11 @@ import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.hasWallets import com.tangem.tap.domain.extensions.makePrimaryWalletManager import com.tangem.tap.features.demo.DemoHelper +import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdkManager @@ -172,11 +176,17 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch return } + val topUpUrl = walletManager.getTopUpUrl() ?: return val blockchain = walletManager.wallet.blockchain + if (globalState.userCountryCode == RUSSIA_COUNTRY_CODE) { + val dialogData = WalletDialog.RussianCardholdersWarningDialog.Data(topUpUrl, blockchain) + store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog(dialogData)) + return + } + val currencyType = AnalyticsParam.CurrencyType.Blockchain(blockchain) Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType)) - val topUpUrl = walletManager.getTopUpUrl() ?: return store.dispatchOpenUrl(topUpUrl) } OnboardingNoteAction.Done -> { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index 8843a8eb40..02e6073066 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -15,6 +15,7 @@ import com.tangem.tap.domain.TapError import com.tangem.tap.domain.configurable.warningMessage.WarningMessage import com.tangem.tap.domain.tokens.models.BlockchainNetwork import com.tangem.tap.features.wallet.models.Currency +import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.wallet.R import org.rekotlin.Action import java.math.BigDecimal @@ -154,7 +155,9 @@ sealed class WalletAction : Action { object SignedHashesMultiWalletDialog : DialogAction() object ChooseTradeActionDialog : DialogAction() data class ChooseCurrency(val amounts: List?) : DialogAction() - object RussianCardholdersWarningDialog : DialogAction() + data class RussianCardholdersWarningDialog( + val dialogData: WalletDialog.RussianCardholdersWarningDialog.Data? = null + ) : DialogAction() object Hide : DialogAction() } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt index 64d2122fa2..f94e6def86 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletDialogsMiddleware.kt @@ -38,7 +38,7 @@ class WalletDialogsMiddleware { ) } is WalletAction.DialogAction.RussianCardholdersWarningDialog -> { - store.dispatchDialogShow(WalletDialog.RussianCardholdersWarningDialog) + store.dispatchDialogShow(WalletDialog.RussianCardholdersWarningDialog(action.dialogData)) } is WalletAction.DialogAction.Hide -> { store.dispatchDialogHide() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt index 68718acd45..fc182e2c4f 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.wallet.redux.models import com.tangem.blockchain.common.Amount +import com.tangem.blockchain.common.Blockchain import com.tangem.tap.common.entities.FiatCurrency import com.tangem.tap.common.redux.StateDialog import com.tangem.wallet.R @@ -31,5 +32,7 @@ sealed interface WalletDialog : StateDialog { val titleRes: Int = R.string.token_details_unable_hide_alert_title } - object RussianCardholdersWarningDialog : WalletDialog + data class RussianCardholdersWarningDialog(val data: Data?) : WalletDialog { + data class Data(val topUpUrl: String, val blockchain: Blockchain) + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt index 526b991006..b8022e2724 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt @@ -5,14 +5,22 @@ import android.os.Bundle import android.view.LayoutInflater import com.google.android.material.bottomsheet.BottomSheetDialog import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.analytics.events.AnalyticsParam +import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.analytics.events.Token import com.tangem.tap.common.extensions.dispatchDialogHide +import com.tangem.tap.common.extensions.dispatchOpenUrl import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.tap.store import com.tangem.wallet.databinding.DialogRussiansCardholdersWarningBinding -class RussianCardholdersWarningBottomSheetDialog(context: Context) : BottomSheetDialog(context) { +class RussianCardholdersWarningBottomSheetDialog( + context: Context, + private val dialogData: WalletDialog.RussianCardholdersWarningDialog.Data?, +) : BottomSheetDialog + (context) { private var binding: DialogRussiansCardholdersWarningBinding? = null @@ -32,7 +40,13 @@ class RussianCardholdersWarningBottomSheetDialog(context: Context) : BottomSheet } binding?.btnYes?.setOnClickListener { - store.dispatch(WalletAction.TradeCryptoAction.Buy(checkUserLocation = false)) + if (dialogData != null) { + val currencyType = AnalyticsParam.CurrencyType.Blockchain(dialogData.blockchain) + Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType)) + store.dispatchOpenUrl(dialogData.topUpUrl) + } else { + store.dispatch(WalletAction.TradeCryptoAction.Buy(checkUserLocation = false)) + } dismiss() } binding?.btnNo?.setOnClickListener { From 4424a8b9b6af6c03d1b5fb3b585db9b1381d9fbf Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 15 Nov 2022 02:27:54 +0500 Subject: [PATCH 02/22] Updated on 2026-08-14 --- .../java/com/tangem/tap/TapApplication.kt | 18 ++++++++-- .../com/tangem/tap/common/moshi/Adapters.kt | 16 +++++++++ .../tap/persistence/PreferencesStorage.kt | 8 ++--- .../tap/persistence/ToppedUpWalletStorage.kt | 21 ++++++++++- .../tangem/network/common/MoshiConverter.kt | 35 +++++++------------ 5 files changed, 69 insertions(+), 29 deletions(-) create mode 100644 app/src/main/java/com/tangem/tap/common/moshi/Adapters.kt diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index 568ca4af60..5074f09e8d 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -27,6 +27,7 @@ import com.tangem.tap.common.feedback.AdditionalFeedbackInfo import com.tangem.tap.common.feedback.FeedbackManager import com.tangem.tap.common.images.createCoilImageLoader import com.tangem.tap.common.log.TangemLogCollector +import com.tangem.tap.common.moshi.BigDecimalAdapter import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.appReducer import com.tangem.tap.common.redux.global.GlobalAction @@ -38,6 +39,7 @@ import com.tangem.tap.domain.configurable.warningMessage.WarningMessagesManager import com.tangem.tap.domain.tokens.UserTokensRepository import com.tangem.tap.domain.walletconnect.WalletConnectRepository import com.tangem.tap.network.NetworkConnectivity +import com.tangem.tap.persistence.CardBalanceStateAdapter import com.tangem.tap.persistence.PreferencesStorage import com.tangem.wallet.BuildConfig import com.zendesk.logger.Logger @@ -70,13 +72,14 @@ class TapApplication : Application(), ImageLoaderFactory { foregroundActivityObserver = ForegroundActivityObserver() registerActivityLifecycleCallbacks(foregroundActivityObserver.callbacks) + initMoshiConverter() DomainLayer.init() NetworkConnectivity.createInstance(store, this) preferencesStorage = PreferencesStorage(this) walletConnectRepository = WalletConnectRepository(this) assetReader = AndroidAssetReader(this) - val configLoader = FeaturesLocalLoader(assetReader, MoshiConverter.defaultMoshi()) + val configLoader = FeaturesLocalLoader(assetReader, MoshiConverter.INSTANCE.moshi) initConfigManager(configLoader, ::initWithConfigDependency) initWarningMessagesManager() @@ -88,6 +91,17 @@ class TapApplication : Application(), ImageLoaderFactory { ) } + private fun initMoshiConverter() { + fun appAdapters(): List = listOf( + BigDecimalAdapter(), + CardBalanceStateAdapter(), + ) + MoshiConverter.reInitInstance( + adapters = appAdapters() + MoshiJsonConverter.getTangemSdkAdapters(), + typedAdapters = MoshiJsonConverter.getTangemSdkTypedAdapters(), + ) + } + override fun newImageLoader(): ImageLoader { return createCoilImageLoader( context = this, @@ -124,7 +138,7 @@ class TapApplication : Application(), ImageLoaderFactory { config = config, isDebug = BuildConfig.DEBUG, logConfig = LogConfig.analyticsHandlers, - jsonConverter = MoshiJsonConverter.INSTANCE, + jsonConverter = MoshiConverter.INSTANCE, ) factory.build(Analytics, buildData) } diff --git a/app/src/main/java/com/tangem/tap/common/moshi/Adapters.kt b/app/src/main/java/com/tangem/tap/common/moshi/Adapters.kt new file mode 100644 index 0000000000..c0ec09ea9c --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/moshi/Adapters.kt @@ -0,0 +1,16 @@ +package com.tangem.tap.common.moshi + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson +import java.math.BigDecimal + +/** +[REDACTED_AUTHOR] + */ +class BigDecimalAdapter { + @FromJson + fun fromJson(value: String) = BigDecimal(value) + + @ToJson + fun toJson(value: BigDecimal) = value.toString() +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt b/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt index 38a03e482d..0e213fc01b 100644 --- a/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt +++ b/app/src/main/java/com/tangem/tap/persistence/PreferencesStorage.kt @@ -4,7 +4,7 @@ import android.app.Application import android.content.Context import android.content.SharedPreferences import androidx.core.content.edit -import com.tangem.common.json.MoshiJsonConverter +import com.tangem.network.common.MoshiConverter import java.util.* class PreferencesStorage(applicationContext: Application) { @@ -21,12 +21,12 @@ class PreferencesStorage(applicationContext: Application) { init { incrementLaunchCounter() appRatingLaunchObserver = AppRatingLaunchObserver(preferences, getCountOfLaunches()) - usedCardsPrefStorage = UsedCardsPrefStorage(preferences, MoshiJsonConverter.INSTANCE) + usedCardsPrefStorage = UsedCardsPrefStorage(preferences, MoshiConverter.INSTANCE) usedCardsPrefStorage.migrate() - fiatCurrenciesPrefStorage = FiatCurrenciesPrefStorage(preferences, MoshiJsonConverter.INSTANCE) + fiatCurrenciesPrefStorage = FiatCurrenciesPrefStorage(preferences, MoshiConverter.INSTANCE) fiatCurrenciesPrefStorage.migrate() disclaimerPrefStorage = DisclaimerPrefStorage(preferences) - toppedUpWalletStorage = ToppedUpWalletStorage(preferences, MoshiJsonConverter.INSTANCE) + toppedUpWalletStorage = ToppedUpWalletStorage(preferences, MoshiConverter.INSTANCE) } var chatFirstLaunchTime: Long? diff --git a/app/src/main/java/com/tangem/tap/persistence/ToppedUpWalletStorage.kt b/app/src/main/java/com/tangem/tap/persistence/ToppedUpWalletStorage.kt index 7ec028e8ea..e270b2b820 100644 --- a/app/src/main/java/com/tangem/tap/persistence/ToppedUpWalletStorage.kt +++ b/app/src/main/java/com/tangem/tap/persistence/ToppedUpWalletStorage.kt @@ -2,7 +2,10 @@ package com.tangem.tap.persistence import android.content.SharedPreferences import androidx.core.content.edit +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson import com.tangem.common.json.MoshiJsonConverter +import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.filters.BasicTopUpFilter import timber.log.Timber @@ -44,7 +47,9 @@ class ToppedUpWalletStorage( private fun restore(): MutableSet { val json = preferences.getString(KEY, null) ?: return mutableSetOf() return try { - jsonConverter.fromJson(json, jsonConverter.typedList(BasicTopUpFilter.Data::class.java))!! + val typedList = jsonConverter.typedList(BasicTopUpFilter.Data::class.java) + val listData = jsonConverter.fromJson>(json, typedList)!! + listData.toMutableSet() } catch (ex: Exception) { preferences.edit(true) { remove(KEY) } mutableSetOf() @@ -54,4 +59,18 @@ class ToppedUpWalletStorage( companion object { private const val KEY = "userWalletsInfo" } +} + +class CardBalanceStateAdapter { + @ToJson + fun toJson(src: AnalyticsParam.CardBalanceState): String = src.value + + @FromJson + fun fromJson(json: String): AnalyticsParam.CardBalanceState { + return when (json) { + AnalyticsParam.CardBalanceState.Empty.value -> AnalyticsParam.CardBalanceState.Empty + AnalyticsParam.CardBalanceState.Full.value -> AnalyticsParam.CardBalanceState.Full + else -> throw IllegalArgumentException() + } + } } \ No newline at end of file diff --git a/network/src/main/java/com/tangem/network/common/MoshiConverter.kt b/network/src/main/java/com/tangem/network/common/MoshiConverter.kt index 1f967032e3..47b5cc4b64 100644 --- a/network/src/main/java/com/tangem/network/common/MoshiConverter.kt +++ b/network/src/main/java/com/tangem/network/common/MoshiConverter.kt @@ -1,38 +1,29 @@ package com.tangem.network.common -import com.squareup.moshi.FromJson +import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi -import com.squareup.moshi.ToJson -import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import com.tangem.common.json.MoshiJsonConverter -import com.tangem.common.json.TangemSdkAdapter import retrofit2.Converter import retrofit2.converter.moshi.MoshiConverterFactory -import java.math.BigDecimal /** [REDACTED_AUTHOR] */ -class MoshiConverter { +object MoshiConverter { - companion object { - fun createFactory(moshi: Moshi = defaultMoshi()): Converter.Factory = MoshiConverterFactory.create(moshi) + var INSTANCE = MoshiJsonConverter() + private set - fun defaultMoshi(): Moshi = Moshi.Builder() - .add(BigDecimalAdapter) - .add(KotlinJsonAdapterFactory()) - .add(TangemSdkAdapter.DerivationPathAdapter()) - .add(TangemSdkAdapter.DerivationNodeAdapter()) - .build() - - fun sdkMoshi(): Moshi = MoshiJsonConverter.INSTANCE.moshi + fun reInitInstance( + adapters: List = listOf(), + typedAdapters: Map, JsonAdapter<*>> = mapOf(), + ) { + INSTANCE = MoshiJsonConverter(adapters, typedAdapters) } -} -object BigDecimalAdapter { - @FromJson - fun fromJson(string: String) = BigDecimal(string) + fun createFactory(moshi: Moshi = INSTANCE.moshi): Converter.Factory = MoshiConverterFactory.create(moshi) - @ToJson - fun toJson(value: BigDecimal) = value.toString() + fun defaultMoshi(): Moshi = INSTANCE.moshi + + fun sdkMoshi(): Moshi = MoshiJsonConverter.INSTANCE.moshi } \ No newline at end of file From 327d84b8cf0064c7f43f66e08975cd91705d5dd4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Sat, 19 Nov 2022 16:42:19 +0500 Subject: [PATCH 03/22] Updated on 2026-08-14 --- .../onboarding/products/note/redux/OnboardingNoteMiddleware.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt index 97e13e9aaf..5ecccaa431 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt @@ -30,7 +30,6 @@ import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.ProgressState import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.features.wallet.redux.models.WalletDialog -import com.tangem.tap.features.wallet.redux.WalletAction import com.tangem.tap.scope import com.tangem.tap.store import com.tangem.tap.tangemSdkManager From 7dbfbdd2ac74e2448e5f9b51b0e399e1dbcfa54a Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 11 Jan 2023 08:00:05 +0300 Subject: [PATCH 04/22] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- .../java/com/tangem/tap/TapApplication.kt | 2 -- .../converters/BasicEventConverter.kt | 2 +- .../filters/ShopPurchasedEventFilter.kt | 25 ------------------- .../appsFlyer/AppsFlyerAnalyticsHandler.kt | 11 ++++++++ .../firebase/FirebaseAnalyticsHandler.kt | 14 ++++++++--- 6 files changed, 24 insertions(+), 32 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index 8453faa078..8ef48dcffb 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit 8453faa078220801858166081947972639f166db +Subproject commit 8ef48dcffbbf6dbe9c1bb565790824e7b1f2061b diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index 5074f09e8d..dc85dff25e 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -19,7 +19,6 @@ import com.tangem.tap.common.analytics.AnalyticsFactory import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder import com.tangem.tap.common.analytics.filters.BasicSignInFilter import com.tangem.tap.common.analytics.filters.BasicTopUpFilter -import com.tangem.tap.common.analytics.filters.ShopPurchasedEventFilter import com.tangem.tap.common.analytics.handlers.amplitude.AmplitudeAnalyticsHandler import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHandler import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler @@ -129,7 +128,6 @@ class TapApplication : Application(), ImageLoaderFactory { factory.addHandlerBuilder(AppsFlyerAnalyticsHandler.Builder()) factory.addHandlerBuilder(FirebaseAnalyticsHandler.Builder()) - factory.addFilter(ShopPurchasedEventFilter()) factory.addFilter(BasicSignInFilter()) factory.addFilter(BasicTopUpFilter(preferencesStorage.toppedUpWalletStorage)) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt index 3950f458bc..02db18e5a8 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt @@ -70,7 +70,7 @@ private fun statesIsReadyToCreateEvent(scanResponse: ScanResponse, state: Wallet if (it.currencyData.amount == null) 0 else 1 }.reduce { acc, i -> acc + i } - if (balancesCount != state.wallets.size) return false + if (balancesCount != state.walletsData.size) return false return true } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt b/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt deleted file mode 100644 index dffa123240..0000000000 --- a/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.tangem.tap.common.analytics.filters - -import com.tangem.tap.common.analytics.api.AnalyticsEventFilter -import com.tangem.tap.common.analytics.api.AnalyticsHandler -import com.tangem.tap.common.analytics.events.AnalyticsEvent -import com.tangem.tap.common.analytics.events.Shop -import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHandler -import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler - -/** -[REDACTED_AUTHOR] - */ -class ShopPurchasedEventFilter : AnalyticsEventFilter { - - override fun canBeAppliedTo(event: AnalyticsEvent): Boolean = event is Shop.Purchased - - override fun canBeSent(event: AnalyticsEvent): Boolean = true - - override fun canBeConsumedByHandler(handler: AnalyticsHandler, event: AnalyticsEvent): Boolean { - return when (handler) { - is AppsFlyerAnalyticsHandler, is FirebaseAnalyticsHandler -> true - else -> false - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt index c3968d9d72..80039ad002 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt @@ -1,7 +1,10 @@ package com.tangem.tap.common.analytics.handlers.appsFlyer +import com.appsflyer.AFInAppEventType import com.tangem.tap.common.analytics.api.AnalyticsHandler import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder +import com.tangem.tap.common.analytics.events.AnalyticsEvent +import com.tangem.tap.common.analytics.events.Shop class AppsFlyerAnalyticsHandler( private val client: AppsFlyerAnalyticsClient, @@ -13,6 +16,14 @@ class AppsFlyerAnalyticsHandler( client.logEvent(event, params) } + override fun send(event: AnalyticsEvent) { + if (event is Shop.Purchased) { + send(AFInAppEventType.PURCHASE, event.params) + } else { + super.send(event) + } + } + companion object { const val ID = "AppsFlyer" } diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt index 109e61d0a5..bd8bd6d445 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/firebase/FirebaseAnalyticsHandler.kt @@ -1,10 +1,12 @@ package com.tangem.tap.common.analytics.handlers.firebase +import com.google.firebase.analytics.FirebaseAnalytics import com.tangem.tap.common.analytics.api.AnalyticsHandler import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder import com.tangem.tap.common.analytics.api.ErrorEventHandler import com.tangem.tap.common.analytics.converters.AnalyticsErrorConverter import com.tangem.tap.common.analytics.events.AnalyticsEvent +import com.tangem.tap.common.analytics.events.Shop class FirebaseAnalyticsHandler( private val client: FirebaseAnalyticsClient, @@ -17,9 +19,9 @@ class FirebaseAnalyticsHandler( } override fun send(event: AnalyticsEvent) { - when (event.error) { - null -> super.send(event) - else -> { + val error = event.error + when { + error != null -> { val errorConverter = AnalyticsErrorConverter() if (!errorConverter.canBeHandled(event.error)) return @@ -29,6 +31,12 @@ class FirebaseAnalyticsHandler( errorParams.putAll(event.params) send(event.error, errorParams) } + event is Shop.Purchased -> { + send(FirebaseAnalytics.Event.PURCHASE, event.params) + } + else -> { + super.send(event) + } } } From 029e4e1cd8a0aa0b1508adf80fbb42519a0ade52 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 11 Jan 2023 15:07:05 +0400 Subject: [PATCH 05/22] Updated on 2026-08-14 --- .../tap/features/wallet/models/WalletWarning.kt | 7 ++++++- .../tangem/tap/features/wallet/redux/WalletState.kt | 11 ++++++++--- .../tap/features/wallet/ui/WalletWarningConverter.kt | 6 +++++- app/src/main/res/values-de/strings_final.xml | 2 +- app/src/main/res/values-fr/strings_final.xml | 2 +- app/src/main/res/values-it/strings_final.xml | 2 +- app/src/main/res/values-ru/strings_final.xml | 2 +- app/src/main/res/values/strings_final.xml | 2 +- 8 files changed, 24 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt b/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt index 3b80a95845..3e960b5123 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/models/WalletWarning.kt @@ -9,7 +9,12 @@ sealed class WalletWarning( ) : WalletWarning(1) object TransactionInProgress : WalletWarning(10) - data class BalanceNotEnoughForFee(val blockchainFullName: String) : WalletWarning(30) + data class BalanceNotEnoughForFee( + val tokenName: String, + val blockchainFullName: String, + val blockchainCurrencyName: String, + ) : WalletWarning(30) + data class Rent(val walletRent: WalletRent) : WalletWarning(40) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 6219fea552..2973700363 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -370,11 +370,16 @@ data class WalletData( } private fun assembleTokenWarnings(walletWarnings: MutableList){ - if (!currency.isToken()) return + if (currency !is Currency.Token) return - val blockchainFullName = currency.blockchain.fullName if ((blockchainAmountIsEmpty() && !tokenAmountIsEmpty())) { - walletWarnings.add(WalletWarning.BalanceNotEnoughForFee(blockchainFullName)) + walletWarnings.add( + WalletWarning.BalanceNotEnoughForFee( + tokenName = currency.token.name, + blockchainFullName = currency.blockchain.fullName, + blockchainCurrencyName = currency.blockchain.currency, + ), + ) } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt index 624d34da3e..321d88db1c 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt @@ -24,7 +24,11 @@ class WalletWarningConverter( is WalletWarning.BalanceNotEnoughForFee -> { context.getString( R.string.token_details_send_blocked_fee_format, - message.blockchainFullName, message.blockchainFullName, + message.tokenName, + message.blockchainFullName, + message.tokenName, + message.blockchainFullName, + message.blockchainCurrencyName, ) } WalletWarning.TransactionInProgress -> { diff --git a/app/src/main/res/values-de/strings_final.xml b/app/src/main/res/values-de/strings_final.xml index b7e64d53df..4a635afd9a 100644 --- a/app/src/main/res/values-de/strings_final.xml +++ b/app/src/main/res/values-de/strings_final.xml @@ -37,7 +37,7 @@ Search tokens You are currently running in Demo mode. All funds are not real. This feature is disabled in Demo mode - Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. + %s is a token in the %s network. To make a %s transaction you need to deposit some %s (%s) to cover the network fee. Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Tokens in Solana network are not supported by this card due to firmware limitation. diff --git a/app/src/main/res/values-fr/strings_final.xml b/app/src/main/res/values-fr/strings_final.xml index b7e64d53df..4a635afd9a 100644 --- a/app/src/main/res/values-fr/strings_final.xml +++ b/app/src/main/res/values-fr/strings_final.xml @@ -37,7 +37,7 @@ Search tokens You are currently running in Demo mode. All funds are not real. This feature is disabled in Demo mode - Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. + %s is a token in the %s network. To make a %s transaction you need to deposit some %s (%s) to cover the network fee. Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Tokens in Solana network are not supported by this card due to firmware limitation. diff --git a/app/src/main/res/values-it/strings_final.xml b/app/src/main/res/values-it/strings_final.xml index b7e64d53df..4a635afd9a 100644 --- a/app/src/main/res/values-it/strings_final.xml +++ b/app/src/main/res/values-it/strings_final.xml @@ -37,7 +37,7 @@ Search tokens You are currently running in Demo mode. All funds are not real. This feature is disabled in Demo mode - Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. + %s is a token in the %s network. To make a %s transaction you need to deposit some %s (%s) to cover the network fee. Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Tokens in Solana network are not supported by this card due to firmware limitation. diff --git a/app/src/main/res/values-ru/strings_final.xml b/app/src/main/res/values-ru/strings_final.xml index ad4f23ca35..21c250d6c4 100644 --- a/app/src/main/res/values-ru/strings_final.xml +++ b/app/src/main/res/values-ru/strings_final.xml @@ -37,7 +37,7 @@ Поиск токенов Приложение работает в демонстрационном режиме. Средства на всех счетах ненастоящие. Эта функция недоступна в демонстрационном режиме - Недостаточно средств для комиссии на вашем %s кошельке для отправки транзакции. Сначала пополните свой %s кошелек. + %s — это токен в сети %s. Чтобы отправить транзакцию %s, необходимо пополнить баланс %s (%s) для оплаты комиссии сети. Доступные сети Внимание! Валюты на разных сетях имеют разные адреса. Убедитесь, что адрес соответствует сети, в которой вы отправляете средства. Токены в сети Solana не поддерживаются этой картой из-за ограничений прошивки. diff --git a/app/src/main/res/values/strings_final.xml b/app/src/main/res/values/strings_final.xml index 70e85346c6..4a8c50e734 100644 --- a/app/src/main/res/values/strings_final.xml +++ b/app/src/main/res/values/strings_final.xml @@ -37,7 +37,7 @@ Search tokens You are currently running in Demo mode. All funds are not real. This feature is disabled in Demo mode - Not enough funds for fee on your %s wallet to send a transaction. Top up your %s wallet first. + %s is a token in the %s network. To make a %s transaction you need to deposit some %s (%s) to cover the network fee. Available networks Note that tokens on different networks have different addresses. Double check that your address matches the network when you transfer funds. Tokens in Solana network are not supported by this card due to firmware limitation. From 629eae99d535c5c7b057b9c494c630bc8565aeef Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 11 Jan 2023 14:57:29 +0300 Subject: [PATCH 06/22] Updated on 2026-08-14 --- app/src/main/assets/tangem-app-config | 2 +- .../tangem/tap/domain/configurable/config/ConfigManager.kt | 4 ++-- .../tangem/tap/domain/configurable/config/JsonModels.kt | 7 ++++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index 8ef48dcffb..93150ef69d 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit 8ef48dcffbbf6dbe9c1bb565790824e7b1f2061b +Subproject commit 93150ef69daf244a92266d7cdfbc9294b745b4e2 diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt b/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt index 12e3d14a80..67b78dff14 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/config/ConfigManager.kt @@ -102,7 +102,7 @@ class ConfigManager { infuraProjectId = values.infuraProjectId, tronGridApiKey = values.tronGridApiKey, ), - appsFlyerDevKey = values.appsFlyerDevKey, + appsFlyerDevKey = values.appsFlyer.appsFlyerDevKey, amplitudeApiKey = values.amplitudeApiKey, shopify = values.shopifyShop, zendesk = values.zendesk, @@ -130,7 +130,7 @@ class ConfigManager { ), infuraProjectId = values.infuraProjectId, ), - appsFlyerDevKey = values.appsFlyerDevKey, + appsFlyerDevKey = values.appsFlyer.appsFlyerDevKey, amplitudeApiKey = values.amplitudeApiKey, shopify = values.shopifyShop, zendesk = values.zendesk, diff --git a/app/src/main/java/com/tangem/tap/domain/configurable/config/JsonModels.kt b/app/src/main/java/com/tangem/tap/domain/configurable/config/JsonModels.kt index 1966ac9303..77a1f0d6cc 100644 --- a/app/src/main/java/com/tangem/tap/domain/configurable/config/JsonModels.kt +++ b/app/src/main/java/com/tangem/tap/domain/configurable/config/JsonModels.kt @@ -29,7 +29,7 @@ class ConfigValueModel( val bscQuiknodeApiKey: String, val blockcypherTokens: Set?, val infuraProjectId: String?, - val appsFlyerDevKey: String, + val appsFlyer: AppsFlyer, val shopifyShop: ShopifyShop?, val zendesk: ZendeskConfig?, val saltPay: SaltPayConfig, @@ -37,6 +37,11 @@ class ConfigValueModel( val amplitudeApiKey: String, ) +data class AppsFlyer( + val appsFlyerDevKey: String, + val appsFlyerAppID: String, +) + class ConfigModel( val features: FeatureModel?, val configValues: ConfigValueModel?, From 7c84005df348e716cf136bafbb56813e2194a093 Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 13 Jan 2023 15:42:41 +0300 Subject: [PATCH 07/22] Updated on 2026-08-14 --- .../tap/common/analytics/events/Onboarding.kt | 1 + .../tangem/tap/common/analytics/events/Shop.kt | 6 +++--- .../tangem/tap/common/feedback/FeedbackManager.kt | 2 ++ .../features/details/redux/DetailsMiddleware.kt | 6 ++++-- .../details/ui/details/DetailsScreenState.kt | 6 +++--- .../tap/features/home/redux/HomeMiddleware.kt | 2 ++ .../features/onboarding/OnboardingMenuProvider.kt | 3 +++ .../products/twins/redux/TwinCardsMiddleware.kt | 15 +++++++++------ .../tap/features/shop/redux/ShopMiddleware.kt | 3 +++ .../tangem/tap/features/shop/ui/ShopFragment.kt | 3 --- .../tap/features/tokens/ui/AddTokensFragment.kt | 1 - .../wallet/redux/middlewares/WalletMiddleware.kt | 4 ++++ .../features/wallet/ui/wallet/MultiWalletView.kt | 3 +++ 13 files changed, 37 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt index 5634c25afa..6d5e5f44f1 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Onboarding.kt @@ -73,4 +73,5 @@ sealed class Onboarding( class ClaimScreenOpened : Onboarding("Onboarding", "Claim screen opened") class ButtonClaim : Onboarding("Onboarding", "Button - Claim") class ClaimWasSuccessfully : Onboarding("Onboarding", "Claim was successfully") + class ButtonChat: Onboarding("Onboarding", "Button - Chat") } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt index 9634f2929b..f2cb5268c1 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Shop.kt @@ -10,7 +10,7 @@ sealed class Shop( params: Map = mapOf(), ) : AnalyticsEvent("Shop", event, params) { - class ScreenOpened : IntroductionProcess("Shop Screen Opened") + class ScreenOpened : Shop("Shop Screen Opened") class Purchased(sku: String, count: String, amount: String, couponCode: String?) : Shop( event = "Purchased", @@ -22,8 +22,8 @@ sealed class Shop( ).filterNotNull(), ) - class Redirected(partnerName: String) : Shop( + class Redirected(partnerName: String?) : Shop( event = "Redirected", - params = mapOf("Partner" to partnerName), + params = partnerName?.let { mapOf("Partner" to partnerName) } ?: mapOf(), ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt index 12fe1e42e9..3ee976483c 100644 --- a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt +++ b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt @@ -3,6 +3,7 @@ package com.tangem.tap.common.feedback import android.content.Context import android.os.Build import com.tangem.domain.common.TapWorkarounds +import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.extensions.sendEmail import com.tangem.tap.common.log.TangemLogCollector import com.tangem.tap.common.zendesk.ZendeskConfig @@ -108,6 +109,7 @@ class FeedbackManager( } private fun showMessagingActivity(context: Context) { + Analytics.send(com.tangem.tap.common.analytics.events.Chat.ScreenOpened()) MessagingActivity.builder() .withMultilineResponseOptionsEnabled(false) .withBotLabelStringRes(R.string.chat_bot_name) diff --git a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt index b316098ff4..e3fc84b294 100644 --- a/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/details/redux/DetailsMiddleware.kt @@ -126,7 +126,8 @@ class DetailsMiddleware { store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Home)) } is CompletionResult.Failure -> { - (result.error as? TangemSdkError)?.let { error -> + val error = result.error + if (error is TangemSdkError && error !is TangemSdkError.UserCancelled) { Analytics.send(Settings.CardSettings.FactoryResetFinished(error)) } } @@ -166,7 +167,8 @@ class DetailsMiddleware { store.dispatch(DetailsAction.ManageSecurity.SaveChanges.Success) } is CompletionResult.Failure -> { - (result.error as? TangemSdkError)?.let { error -> + val error = result.error + if (error is TangemSdkError && error !is TangemSdkError.UserCancelled) { Analytics.send(Settings.CardSettings.SecurityModeChanged(paramValue, error)) } store.dispatch(DetailsAction.ManageSecurity.SaveChanges.Failure) diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt index a92efc7e2b..ac1ae7916e 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsScreenState.kt @@ -41,7 +41,7 @@ sealed class SocialNetwork(val id: String, val iconRes: Int) { object Facebook : SocialNetwork("Facebook", R.drawable.ic_facebook) object Instagram : SocialNetwork("Instagram", R.drawable.ic_instagram) object GitHub : SocialNetwork("GitHub", R.drawable.ic_github) - object Youtube : SocialNetwork("Youtube", R.drawable.ic_youtube) + object YouTube : SocialNetwork("YouTube", R.drawable.ic_youtube) object LinkedIn : SocialNetwork("LinkedIn", R.drawable.ic_linkedin) } @@ -52,7 +52,7 @@ object TangemSocialAccounts { SocialNetworkLink(SocialNetwork.Facebook, "https://m.facebook.com/TangemCards/"), SocialNetworkLink(SocialNetwork.Instagram, "https://instagram.com/tangemcards"), SocialNetworkLink(SocialNetwork.GitHub, "https://github.com/tangem"), - SocialNetworkLink(SocialNetwork.Youtube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"), + SocialNetworkLink(SocialNetwork.YouTube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"), SocialNetworkLink(SocialNetwork.LinkedIn, "https://www.linkedin.com/company/tangem"), ) val accountsRu: List = listOf( @@ -61,7 +61,7 @@ object TangemSocialAccounts { SocialNetworkLink(SocialNetwork.Facebook, "https://m.facebook.com/TangemCards/"), SocialNetworkLink(SocialNetwork.Instagram, "https://instagram.com/tangemcards"), SocialNetworkLink(SocialNetwork.GitHub, "https://github.com/tangem"), - SocialNetworkLink(SocialNetwork.Youtube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"), + SocialNetworkLink(SocialNetwork.YouTube, "https://youtube.com/channel/UCFGwLS7yggzVkP6ozte0m1w"), SocialNetworkLink(SocialNetwork.LinkedIn, "https://www.linkedin.com/company/tangem"), ) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt index c3c0145ec8..37a1da2c8b 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt @@ -11,6 +11,7 @@ import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.backupService import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.analytics.events.IntroductionProcess +import com.tangem.tap.common.analytics.events.Shop import com.tangem.tap.common.analytics.paramsInterceptor.BatchIdParamsInterceptor import com.tangem.tap.common.entities.IndeterminateProgressButton import com.tangem.tap.common.extensions.dispatchDialogShow @@ -100,6 +101,7 @@ private fun handleHomeAction(appState: () -> AppState?, action: Action, dispatch postUiDelayBg(300) { store.dispatch(scanCardAction) } } is HomeAction.GoToShop -> { + Analytics.send(Shop.ScreenOpened()) when (action.userCountryCode) { RUSSIA_COUNTRY_CODE, BELARUS_COUNTRY_CODE -> store.dispatchOpenUrl(BUY_WALLET_URL) else -> store.dispatch(NavigationAction.NavigateTo(AppScreen.Shop)) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt index 2fff1d0fab..7c816d9210 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt @@ -4,6 +4,8 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import androidx.core.view.MenuProvider +import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.feedback.SupportInfo import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.store @@ -19,6 +21,7 @@ class OnboardingMenuProvider : MenuProvider { override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) { R.id.menu_item_chat_support -> { + Analytics.send(Onboarding.ButtonChat()) store.dispatch(GlobalAction.OpenChat(SupportInfo())) true } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt index aa6de330d6..cfb3159305 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt @@ -101,10 +101,7 @@ private fun handle(action: Action, dispatch: DispatchFunction) { CreateTwinWalletMode.CreateWallet -> { if (preferencesStorage.wasTwinsOnboardingShown()) { val step = when { - !scanResponse.twinsIsTwinned() -> { - Analytics.send(Onboarding.CreateWallet.ScreenOpened()) - TwinCardsStep.CreateFirstWallet - } + !scanResponse.twinsIsTwinned() -> TwinCardsStep.CreateFirstWallet twinCardsState.walletBalance.balanceIsToppedUp() -> TwinCardsStep.Done else -> TwinCardsStep.TopUpWallet } @@ -145,7 +142,14 @@ private fun handle(action: Action, dispatch: DispatchFunction) { Analytics.send(Onboarding.Twins.ScreenOpened()) preferencesStorage.saveTwinsOnboardingShown() } - TwinCardsStep.TopUpWallet -> store.dispatch(TwinCardsAction.Balance.Update) + TwinCardsStep.CreateFirstWallet -> { + Analytics.send(Onboarding.CreateWallet.ScreenOpened()) + Analytics.send(Onboarding.Twins.SetupStarted()) + } + TwinCardsStep.TopUpWallet -> { + Analytics.send(Onboarding.Topup.ScreenOpened()) + store.dispatch(TwinCardsAction.Balance.Update) + } TwinCardsStep.Done -> { finishCardActivation() postUi(500) { store.dispatch(TwinCardsAction.Confetti.Show) } @@ -153,7 +157,6 @@ private fun handle(action: Action, dispatch: DispatchFunction) { } } is TwinCardsAction.Wallet.LaunchFirstStep -> { - Analytics.send(Onboarding.Twins.SetupStarted()) val manager = TwinCardsManager( card = getScanResponse().card, assetReader = action.reader, diff --git a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt index f7f126c05f..5c5a9d72b9 100644 --- a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt @@ -1,5 +1,7 @@ package com.tangem.tap.features.shop.redux +import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.analytics.events.Shop import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchOpenUrl import com.tangem.tap.common.redux.AppState @@ -113,6 +115,7 @@ private fun handle(action: Action) { } } ShopAction.StartWebCheckout -> { + Analytics.send(Shop.Redirected(null)) store.dispatchOpenUrl(shopService.getCheckoutUrl(shopState.selectedProduct)) store.dispatch(ShopAction.FinishSuccessfulOrder) } diff --git a/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt b/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt index 338561267b..622f440a18 100644 --- a/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/shop/ui/ShopFragment.kt @@ -12,8 +12,6 @@ import androidx.activity.OnBackPressedCallback import by.kirich1409.viewbindingdelegate.viewBinding import com.tangem.tap.common.GlobalLayoutStateHandler import com.tangem.tap.common.KeyboardObserver -import com.tangem.tap.common.analytics.Analytics -import com.tangem.tap.common.analytics.events.Shop import com.tangem.tap.common.extensions.show import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.common.shop.data.ProductType @@ -43,7 +41,6 @@ class ShopFragment : BaseStoreFragment(R.layout.fragment_shop), StoreSubscriber< override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - Analytics.send(Shop.ScreenOpened()) activity?.onBackPressedDispatcher?.addCallback(this, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { diff --git a/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt b/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt index 36b1f82337..1c8ffe8305 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/ui/AddTokensFragment.kt @@ -50,7 +50,6 @@ class AddTokensFragment : Fragment(R.layout.fragment_add_tokens), override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) - Analytics.send(ManageTokens.ScreenOpened()) activity?.onBackPressedDispatcher?.addCallback( this, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 5e245d4038..0210359cfd 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -12,6 +12,7 @@ import com.tangem.domain.common.extensions.withMainContext import com.tangem.operations.attestation.Attestation import com.tangem.operations.attestation.OnlineCardVerifier import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Token import com.tangem.tap.common.extensions.copyToClipboard import com.tangem.tap.common.extensions.dispatchDebugErrorNotification @@ -261,6 +262,9 @@ class WalletMiddleware { } else { store.dispatch(newAction) if (newAction is PrepareSendScreen) { + store.state.walletState.getSelectedWalletData()?.currency?.let { currency -> + Analytics.send(Token.ButtonSend(AnalyticsParam.CurrencyType.Currency(currency))) + } store.dispatch(NavigationAction.NavigateTo(AppScreen.Send)) } } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt index d4172e31ef..f9cb956296 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/wallet/MultiWalletView.kt @@ -8,6 +8,7 @@ import com.tangem.domain.common.TapWorkarounds.derivationStyle import com.tangem.domain.common.TapWorkarounds.isTestCard import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.analytics.events.MainScreen +import com.tangem.tap.common.analytics.events.ManageTokens import com.tangem.tap.common.analytics.events.Portfolio import com.tangem.tap.common.extensions.animateVisibility import com.tangem.tap.common.extensions.formatAmountAsSpannedString @@ -105,6 +106,8 @@ class MultiWalletView : WalletView() { derivationStyle = card.derivationStyle, ), ) + + Analytics.send(ManageTokens.ScreenOpened()) store.dispatch(NavigationAction.NavigateTo(AppScreen.AddTokens)) } handleErrorStates(state = state, binding = binding, fragment = fragment) From 5a6594aee04ad9e6926abd304acafb3c9f8e209e Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Jan 2023 12:51:42 +0300 Subject: [PATCH 08/22] Updated on 2026-08-14 --- .../java/com/tangem/tap/common/analytics/events/Settings.kt | 1 + .../com/tangem/tap/common/analytics/events/WalletConnect.kt | 1 + .../tangem/tap/features/details/ui/details/DetailsViewModel.kt | 1 + .../features/details/ui/walletconnect/WalletConnectFragment.kt | 3 +++ .../tap/features/wallet/redux/middlewares/WalletMiddleware.kt | 2 ++ 5 files changed, 8 insertions(+) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt index 38725048a7..6f1834839a 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Settings.kt @@ -20,6 +20,7 @@ sealed class Settings( class ButtonCardSettings : Settings(event = "Button - Card Settings") class ButtonAppSettings : Settings(event = "Button - App Settings") class ButtonCreateBackup : Settings(event = "Button - Create Backup") + class ButtonWalletConnect : Settings(event = "Button - Wallet Connect") class ButtonSocialNetwork(network: SocialNetwork) : Settings( event = "Button - Social Network", diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt index 1ff587b2aa..1c406f24b1 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt @@ -9,6 +9,7 @@ sealed class WalletConnect( error: Throwable? = null, ) : AnalyticsEvent("Wallet Connect", event, params, error) { + class ScreenOpened : Settings(event = "WC Screen Opened") class NewSessionEstablished : WalletConnect("New Session Established") class SessionDisconnected : WalletConnect("Session Disconnected") class RequestSigned : WalletConnect("Request Signed") diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt index c48aeab31d..5645d3c90f 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/details/DetailsViewModel.kt @@ -61,6 +61,7 @@ class DetailsViewModel(private val store: Store) { private fun handleClickingSettingsItem(item: SettingsElement) { when (item) { SettingsElement.WalletConnect -> { + Analytics.send(Settings.ButtonWalletConnect()) store.dispatch(NavigationAction.NavigateTo(AppScreen.WalletConnectSessions)) } SettingsElement.Chat -> { diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt index 8d3de292ae..f642f91320 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt @@ -10,6 +10,8 @@ import androidx.compose.ui.platform.ComposeView import androidx.fragment.app.Fragment import androidx.transition.TransitionInflater import com.google.accompanist.appcompattheme.AppCompatTheme +import com.tangem.tap.common.analytics.Analytics +import com.tangem.tap.common.analytics.events.WalletConnect import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectState @@ -23,6 +25,7 @@ class WalletConnectFragment : Fragment(), StoreSubscriber { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + Analytics.send(WalletConnect.ScreenOpened()) val inflater = TransitionInflater.from(requireContext()) enterTransition = inflater.inflateTransition(android.R.transition.fade) exitTransition = inflater.inflateTransition(android.R.transition.fade) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 0210359cfd..dca805579a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -237,10 +237,12 @@ class WalletMiddleware { } } is WalletAction.CopyAddress -> { + Analytics.send(Token.Recieve.ButtonCopyAddress()) action.context.copyToClipboard(action.address) store.dispatch(WalletAction.CopyAddress.Success) } is WalletAction.ShareAddress -> { + Analytics.send(Token.Recieve.ButtonShareAddress()) action.context.shareText(action.address) } is WalletAction.ExploreAddress -> { From 03c10dac668dfd1a2ced010c6ced8d9678729333 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 16 Jan 2023 22:05:39 +0300 Subject: [PATCH 09/22] Updated on 2026-08-14 --- .../converters/ShopOrderToEventConverter.kt | 12 +++++----- .../tap/common/shop/TangemShopService.kt | 4 ++-- .../note/redux/OnboardingNoteMiddleware.kt | 12 +++++----- .../twins/redux/TwinCardsMiddleware.kt | 23 +++++++++++++++---- .../middlewares/TradeCryptoMiddleware.kt | 9 ++++---- .../wallet/redux/models/WalletDialog.kt | 3 +-- ...sianCardholdersWarningBottomSheetDialog.kt | 4 ---- 7 files changed, 39 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt index ddbd1683bd..49f6762db9 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/ShopOrderToEventConverter.kt @@ -8,19 +8,19 @@ import com.tangem.tap.common.shop.data.ProductType /** [REDACTED_AUTHOR] */ -class ShopOrderToEventConverter : Converter, Shop.Purchased> { +class ShopOrderToEventConverter : Converter, Shop.Purchased> { - override fun convert(value: Pair): Shop.Purchased { - val order = value.first + override fun convert(value: Pair): Shop.Purchased { + val checkout = value.first val productType = value.second - val sku = order.lineItems.edges.firstOrNull()?.node?.variant?.sku ?: productType.sku + val sku = checkout.lineItems?.edges?.firstOrNull()?.node?.variant?.sku ?: productType.sku val count = when (productType) { ProductType.WALLET_2_CARDS -> "2" ProductType.WALLET_3_CARDS -> "3" } - val amount = "${order.totalPriceV2.amount} ${order.totalPriceV2.currencyCode.name}" - val code = (order.discountApplications.edges.firstOrNull()?.node as? Storefront.DiscountCodeApplication)?.code + val amount = "${checkout.totalPriceV2.amount} ${checkout.totalPriceV2.currencyCode.name}" + val code = (checkout.discountApplications.edges.firstOrNull()?.node as? Storefront.DiscountCodeApplication)?.code return Shop.Purchased(sku, count, amount, code) } diff --git a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt index 808cb5bbbc..848ef979a6 100644 --- a/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt +++ b/app/src/main/java/com/tangem/tap/common/shop/TangemShopService.kt @@ -200,8 +200,8 @@ class TangemShopService(application: Application, shopifyShop: ShopifyShop) { suspend fun waitForCheckout(productType: ProductType) { val result = shopifyService.checkout(true, checkouts[productType]!!.id) result.onSuccess { checkout -> - checkout.order?.let { - val event = ShopOrderToEventConverter().convert(it to productType) + if (checkout.order != null && checkout.lineItems != null) { + val event = ShopOrderToEventConverter().convert(checkout to productType) Analytics.send(event) } } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt index 5ecccaa431..fe20b14405 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/note/redux/OnboardingNoteMiddleware.kt @@ -178,16 +178,16 @@ private fun handleNoteAction(appState: () -> AppState?, action: Action, dispatch val topUpUrl = walletManager.getTopUpUrl() ?: return val blockchain = walletManager.wallet.blockchain - if (globalState.userCountryCode == RUSSIA_COUNTRY_CODE) { - val dialogData = WalletDialog.RussianCardholdersWarningDialog.Data(topUpUrl, blockchain) - store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog(dialogData)) - return - } val currencyType = AnalyticsParam.CurrencyType.Blockchain(blockchain) Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType)) - store.dispatchOpenUrl(topUpUrl) + if (globalState.userCountryCode == RUSSIA_COUNTRY_CODE) { + val dialogData = WalletDialog.RussianCardholdersWarningDialog.Data(topUpUrl) + store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog(dialogData)) + } else { + store.dispatchOpenUrl(topUpUrl) + } } OnboardingNoteAction.Done -> { store.dispatch(GlobalAction.Onboarding.Stop) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt index cfb3159305..b4967c1f39 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/twins/redux/TwinCardsMiddleware.kt @@ -1,6 +1,5 @@ package com.tangem.tap.features.onboarding.products.twins.redux -import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.extensions.Result import com.tangem.common.CompletionResult import com.tangem.common.extensions.guard @@ -10,8 +9,10 @@ import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Onboarding +import com.tangem.tap.common.extensions.dispatchDebugErrorNotification import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchErrorNotification +import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchOpenUrl import com.tangem.tap.common.extensions.getAddressData import com.tangem.tap.common.extensions.getTopUpUrl @@ -25,8 +26,11 @@ import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.domain.TapError import com.tangem.tap.domain.extensions.makePrimaryWalletManager import com.tangem.tap.domain.twins.TwinCardsManager +import com.tangem.tap.features.home.RUSSIA_COUNTRY_CODE import com.tangem.tap.features.wallet.models.Currency import com.tangem.tap.features.wallet.redux.ProgressState +import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.models.WalletDialog import com.tangem.tap.preferencesStorage import com.tangem.tap.scope import com.tangem.tap.store @@ -277,12 +281,23 @@ private fun handle(action: Action, dispatch: DispatchFunction) { store.dispatchDialogShow(appDialog) } is TwinCardsAction.TopUp -> { - val topUpUrl = twinCardsState.walletManager?.getTopUpUrl() ?: return + val walletManager = twinCardsState.walletManager.guard { + store.dispatchDebugErrorNotification("NPE: WalletManager") + return + } - val currencyType = AnalyticsParam.CurrencyType.Blockchain(Blockchain.Bitcoin) + val topUpUrl = walletManager.getTopUpUrl() ?: return + val blockchain = walletManager.wallet.blockchain + + val currencyType = AnalyticsParam.CurrencyType.Blockchain(blockchain) Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType)) - store.dispatchOpenUrl(topUpUrl) + if (globalState.userCountryCode == RUSSIA_COUNTRY_CODE) { + val dialogData = WalletDialog.RussianCardholdersWarningDialog.Data(topUpUrl) + store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog(dialogData)) + } else { + store.dispatchOpenUrl(topUpUrl) + } } TwinCardsAction.Done -> { scope.launch { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt index 5d6a9fc2d7..7134d73f7d 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/TradeCryptoMiddleware.kt @@ -39,21 +39,22 @@ class TradeCryptoMiddleware { state: () -> AppState?, action: WalletAction.TradeCryptoAction.Buy, ) { + val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return + + val currency = selectedWalletData.currency + Analytics.send(Token.ButtonBuy(AnalyticsParam.CurrencyType.Currency(currency))) + if (action.checkUserLocation && state()?.globalState?.userCountryCode == RUSSIA_COUNTRY_CODE) { store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog()) return } - val selectedWalletData = store.state.walletState.getSelectedWalletData() ?: return val card = store.state.globalState.scanResponse?.card ?: return - val addresses = selectedWalletData.walletAddresses?.list.orEmpty() if (addresses.isEmpty()) return val exchangeManager = store.state.globalState.exchangeManager val appCurrency = store.state.globalState.appCurrency - val currency = selectedWalletData.currency - Analytics.send(Token.ButtonBuy(AnalyticsParam.CurrencyType.Currency(currency))) if (currency is Currency.Token && currency.blockchain.isTestnet()) { val walletManager = store.state.walletState.getWalletManager(currency) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt index fc182e2c4f..6e809d677e 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt @@ -1,7 +1,6 @@ package com.tangem.tap.features.wallet.redux.models import com.tangem.blockchain.common.Amount -import com.tangem.blockchain.common.Blockchain import com.tangem.tap.common.entities.FiatCurrency import com.tangem.tap.common.redux.StateDialog import com.tangem.wallet.R @@ -33,6 +32,6 @@ sealed interface WalletDialog : StateDialog { } data class RussianCardholdersWarningDialog(val data: Data?) : WalletDialog { - data class Data(val topUpUrl: String, val blockchain: Blockchain) + data class Data(val topUpUrl: String) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt index b8022e2724..5d65240001 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/dialogs/RussianCardholdersWarningBottomSheetDialog.kt @@ -5,8 +5,6 @@ import android.os.Bundle import android.view.LayoutInflater import com.google.android.material.bottomsheet.BottomSheetDialog import com.tangem.tap.common.analytics.Analytics -import com.tangem.tap.common.analytics.events.AnalyticsParam -import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.analytics.events.Token import com.tangem.tap.common.extensions.dispatchDialogHide import com.tangem.tap.common.extensions.dispatchOpenUrl @@ -41,8 +39,6 @@ class RussianCardholdersWarningBottomSheetDialog( binding?.btnYes?.setOnClickListener { if (dialogData != null) { - val currencyType = AnalyticsParam.CurrencyType.Blockchain(dialogData.blockchain) - Analytics.send(Onboarding.Topup.ButtonBuyCrypto(currencyType)) store.dispatchOpenUrl(dialogData.topUpUrl) } else { store.dispatch(WalletAction.TradeCryptoAction.Buy(checkUserLocation = false)) From 223858d6e64a4f174aaef321b1aa26798b18b5a2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Jan 2023 16:45:59 +0300 Subject: [PATCH 10/22] Updated on 2026-08-14 --- .../java/com/tangem/tap/common/IntentHandler.kt | 2 +- .../com/tangem/tap/features/home/HomeFragment.kt | 2 +- .../tangem/tap/features/home/redux/HomeAction.kt | 6 +++++- .../tap/features/home/redux/HomeMiddleware.kt | 13 +++++++++---- .../wallet/redux/OnboardingWalletMiddleware.kt | 2 +- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/IntentHandler.kt b/app/src/main/java/com/tangem/tap/common/IntentHandler.kt index 1e41053369..be6ef95e79 100644 --- a/app/src/main/java/com/tangem/tap/common/IntentHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/IntentHandler.kt @@ -35,7 +35,7 @@ class IntentHandler { intent.action = null store.dispatch(NavigationAction.NavigateTo(AppScreen.Home)) store.dispatch(NavigationAction.PopBackTo(AppScreen.Home)) - store.dispatch(HomeAction.ReadCard) + store.dispatch(HomeAction.ReadCard()) } } } diff --git a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt index c06f921c2f..587e981005 100644 --- a/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/home/HomeFragment.kt @@ -86,7 +86,7 @@ class HomeFragment : Fragment(), StoreSubscriber { homeState, onScanButtonClick = { Analytics.send(IntroductionProcess.ButtonScanCard()) - store.dispatch(HomeAction.ReadCard) + store.dispatch(HomeAction.ReadCard()) }, onShopButtonClick = { Analytics.send(IntroductionProcess.ButtonBuyCards()) diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt index 0a276dff4f..74dde30ea8 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt @@ -1,6 +1,7 @@ package com.tangem.tap.features.home.redux import com.tangem.tap.common.entities.IndeterminateProgressButton +import com.tangem.tap.common.redux.navigation.AppScreen import org.rekotlin.Action sealed class HomeAction : Action { @@ -9,7 +10,10 @@ sealed class HomeAction : Action { data class ShouldScanCardOnResume(val shouldScanCard: Boolean) : HomeAction() // from ui - object ReadCard : HomeAction() + data class ReadCard( + val fromScreen: AppScreen = AppScreen.Home, + ) : HomeAction() + data class ScanInProgress(val scanInProgress: Boolean) : HomeAction() data class GoToShop(val userCountryCode: String?) : HomeAction() diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt index 37a1da2c8b..23c14d184a 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt @@ -11,6 +11,7 @@ import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.backupService import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.analytics.events.IntroductionProcess +import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.common.analytics.events.Shop import com.tangem.tap.common.analytics.paramsInterceptor.BatchIdParamsInterceptor import com.tangem.tap.common.entities.IndeterminateProgressButton @@ -76,7 +77,7 @@ private fun handleHomeAction(appState: () -> AppState?, action: Action, dispatch is HomeAction.ShouldScanCardOnResume -> { if (action.shouldScanCard) { store.dispatch(HomeAction.ShouldScanCardOnResume(false)) - postUiDelayBg(700) { store.dispatch(HomeAction.ReadCard) } + postUiDelayBg(700) { store.dispatch(HomeAction.ReadCard(AppScreen.Wallet)) } } } is HomeAction.ReadCard -> { @@ -90,7 +91,7 @@ private fun handleHomeAction(appState: () -> AppState?, action: Action, dispatch nextHandler = { showDisclaimerIfNeed( scanResponse = scanResponse, - nextHandler = ::onScanSuccess, + nextHandler = { onScanSuccess(action.fromScreen, scanResponse) }, ) }, ) @@ -154,8 +155,12 @@ private fun showDisclaimerIfNeed(scanResponse: ScanResponse, nextHandler: (ScanR } } -private fun onScanSuccess(scanResponse: ScanResponse) { - Analytics.send(IntroductionProcess.CardWasScanned()) +private fun onScanSuccess(fromScreen: AppScreen, scanResponse: ScanResponse) { + when (fromScreen) { + AppScreen.Wallet -> Analytics.send(MainScreen.CardWasScanned()) + else -> Analytics.send(IntroductionProcess.CardWasScanned()) + } + val globalState = store.state.globalState val tapWalletManager = globalState.tapWalletManager tapWalletManager.updateConfigManager(scanResponse) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt index dfe53282ed..b0be522213 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletMiddleware.kt @@ -149,7 +149,7 @@ private fun handleWalletAction(action: Action, state: () -> AppState?, dispatch: if (scanResponse == null) { store.dispatch(NavigationAction.PopBackTo()) - store.dispatch(HomeAction.ReadCard) + store.dispatch(HomeAction.ReadCard()) } else { val backupState = store.state.onboardingWalletState.backupState val updatedScanResponse = updateScanResponseAfterBackup(scanResponse, backupState) From bc9fce72247ae209a28db2129c0d4ab7d904498c Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 20 Jan 2023 20:04:57 +0300 Subject: [PATCH 11/22] Updated on 2026-08-14 --- app/src/main/java/com/tangem/tap/TapApplication.kt | 13 +------------ .../handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt | 3 +-- .../tangem/tap/common/feedback/FeedbackManager.kt | 2 +- .../ui/walletconnect/WalletConnectFragment.kt | 2 +- .../features/onboarding/OnboardingMenuProvider.kt | 2 +- .../tap/features/shop/redux/ShopMiddleware.kt | 2 +- .../wallet/redux/middlewares/WalletMiddleware.kt | 2 +- .../features/wallet/redux/models/WalletDialog.kt | 6 +++--- .../features/wallet/ui/WalletWarningConverter.kt | 5 +---- 9 files changed, 11 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index 3ccb770ad4..d2b413e412 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -11,13 +11,13 @@ import com.tangem.blockchain.common.BlockchainSdkConfig import com.tangem.blockchain.common.WalletManagerFactory import com.tangem.blockchain.network.BlockchainSdkRetrofitBuilder import com.tangem.common.json.MoshiJsonConverter +import com.tangem.core.analytics.Analytics import com.tangem.datasource.api.common.MoshiConverter import com.tangem.domain.DomainLayer import com.tangem.domain.common.LogConfig import com.tangem.tap.common.AndroidAssetReader import com.tangem.tap.common.AssetReader import com.tangem.tap.common.IntentHandler -import com.tangem.core.analytics.Analytics import com.tangem.tap.common.analytics.AnalyticsFactory import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder import com.tangem.tap.common.analytics.filters.BasicSignInFilter @@ -170,17 +170,6 @@ class TapApplication : Application(), ImageLoaderFactory { ) } - private fun initMoshiConverter() { - fun appAdapters(): List = listOf( - BigDecimalAdapter(), - CardBalanceStateAdapter(), - ) - MoshiConverter.reInitInstance( - adapters = appAdapters() + MoshiJsonConverter.getTangemSdkAdapters(), - typedAdapters = MoshiJsonConverter.getTangemSdkTypedAdapters(), - ) - } - override fun newImageLoader(): ImageLoader { return createCoilImageLoader( context = this, diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt index e9ece28a44..d1b3189ab1 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsFlyer/AppsFlyerAnalyticsHandler.kt @@ -1,10 +1,9 @@ package com.tangem.tap.common.analytics.handlers.appsFlyer import com.appsflyer.AFInAppEventType +import com.tangem.core.analytics.AnalyticsEvent import com.tangem.core.analytics.api.AnalyticsHandler -import com.tangem.tap.common.analytics.api.AnalyticsHandler import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder -import com.tangem.tap.common.analytics.events.AnalyticsEvent import com.tangem.tap.common.analytics.events.Shop class AppsFlyerAnalyticsHandler( diff --git a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt index 3ee976483c..b44db4004b 100644 --- a/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt +++ b/app/src/main/java/com/tangem/tap/common/feedback/FeedbackManager.kt @@ -2,8 +2,8 @@ package com.tangem.tap.common.feedback import android.content.Context import android.os.Build +import com.tangem.core.analytics.Analytics import com.tangem.domain.common.TapWorkarounds -import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.extensions.sendEmail import com.tangem.tap.common.log.TangemLogCollector import com.tangem.tap.common.zendesk.ZendeskConfig diff --git a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt index 4b01e513a2..8b29784828 100644 --- a/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/details/ui/walletconnect/WalletConnectFragment.kt @@ -9,8 +9,8 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.platform.ComposeView import androidx.fragment.app.Fragment import androidx.transition.TransitionInflater +import com.tangem.core.analytics.Analytics import com.tangem.core.ui.res.TangemTheme -import com.tangem.tap.common.analytics.Analytics import com.tangem.tap.common.analytics.events.WalletConnect import com.tangem.tap.common.redux.navigation.NavigationAction import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt index 7c816d9210..4af057eb58 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingMenuProvider.kt @@ -4,7 +4,7 @@ import android.view.Menu import android.view.MenuInflater import android.view.MenuItem import androidx.core.view.MenuProvider -import com.tangem.tap.common.analytics.Analytics +import com.tangem.core.analytics.Analytics import com.tangem.tap.common.analytics.events.Onboarding import com.tangem.tap.common.feedback.SupportInfo import com.tangem.tap.common.redux.global.GlobalAction diff --git a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt index 5c5a9d72b9..62e21e95e1 100644 --- a/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/shop/redux/ShopMiddleware.kt @@ -1,6 +1,6 @@ package com.tangem.tap.features.shop.redux -import com.tangem.tap.common.analytics.Analytics +import com.tangem.core.analytics.Analytics import com.tangem.tap.common.analytics.events.Shop import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchOpenUrl diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index f26b34fa01..dc19d83445 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -276,7 +276,7 @@ class WalletMiddleware { } else { store.dispatch(newAction) if (newAction is PrepareSendScreen) { - store.state.walletState.getSelectedWalletData()?.currency?.let { currency -> + store.state.walletState.selectedWalletData?.currency?.let { currency -> Analytics.send(Token.ButtonSend(AnalyticsParam.CurrencyType.Currency(currency))) } store.dispatch(NavigationAction.NavigateTo(AppScreen.Send)) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt index f1a7575391..fb16e8420c 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/models/WalletDialog.kt @@ -16,7 +16,7 @@ sealed interface WalletDialog : StateDialog { data class RemoveWalletDialog( val currencyTitle: String, - val onOk: () -> Unit + val onOk: () -> Unit, ) : WalletDialog { val messageRes: Int = R.string.token_details_hide_alert_message val titleRes: Int = R.string.token_details_hide_alert_title @@ -25,13 +25,13 @@ sealed interface WalletDialog : StateDialog { data class TokensAreLinkedDialog( val currencyTitle: String, - val currencySymbol: String + val currencySymbol: String, ) : WalletDialog { val messageRes: Int = R.string.token_details_unable_hide_alert_message val titleRes: Int = R.string.token_details_unable_hide_alert_title } data class RussianCardholdersWarningDialog(val data: Data?) : WalletDialog { - data class Data(val topUpUrl: String, val blockchain: Blockchain) + data class Data(val topUpUrl: String) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt index 0effd1a9ba..a3ffb44b3a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletWarningConverter.kt @@ -24,17 +24,14 @@ class WalletWarningConverter( is WalletWarning.BalanceNotEnoughForFee -> { context.getString( R.string.token_details_send_blocked_fee_format, - message.tokenName, message.blockchainFullName, - message.tokenName, message.blockchainFullName, - message.blockchainCurrencyName, ) } is WalletWarning.TransactionInProgress -> { context.getString( R.string.token_details_send_blocked_tx_format, - message.currencyName + message.currencyName, ) } is WalletWarning.Rent -> { From 3bb298da17e735bb47e1dcb984a309e521cadc32 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Jan 2023 16:41:20 +0300 Subject: [PATCH 12/22] Updated on 2026-08-14 --- .../DefaultWalletCurrenciesManager.kt | 38 +++++++++------- .../utils/WalletDataOperations.kt | 4 +- .../utils/WalletStoreOperations.kt | 43 ++++++++----------- 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt index dd19a02575..2b5a565f7e 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletCurrencies/implementation/DefaultWalletCurrenciesManager.kt @@ -1,5 +1,6 @@ package com.tangem.tap.domain.walletCurrencies.implementation +import com.tangem.blockchain.common.Blockchain import com.tangem.blockchain.common.DerivationStyle import com.tangem.common.CompletionResult import com.tangem.common.flatMap @@ -54,28 +55,17 @@ internal class DefaultWalletCurrenciesManager( currenciesToAdd: List, ): CompletionResult = withContext(Dispatchers.Default) { val card = userWallet.scanResponse.card - val updatedBlockchainNetworks = currenciesToAdd - .addMissingBlockchains(card) - .toBlockchainNetworks() val newCurrencies = (getSavedCurrencies(userWallet.walletId) + currenciesToAdd) .addMissingBlockchains(card) - updateWalletStores(userWallet, updatedBlockchainNetworks) + updateWalletStores(userWallet, newCurrencies.toBlockchainNetworks()) .map { saveUserCurrencies(card, newCurrencies) } .flatMap { - val updatedBlockchains = updatedBlockchainNetworks - .map { it.blockchain } - val updatedWalletStores = walletStoresRepository.get(userWallet.walletId) - .firstOrNull() - ?.filter { it.blockchain in updatedBlockchains } - ?: return@flatMap CompletionResult.Success(Unit) - - walletAmountsRepository.updateAmountsForWalletStores( - walletStores = updatedWalletStores, + updateWalletStoresAmounts( userWallet = userWallet, - fiatCurrency = appCurrencyProvider(), + updatedBlockchains = currenciesToAdd.map { it.blockchain }.distinct(), ) } } @@ -161,6 +151,10 @@ internal class DefaultWalletCurrenciesManager( return newCurrencies } + private fun findDerivationPath(currency: Currency, cardDerivationStyle: DerivationStyle?): String? { + return currency.derivationPath ?: currency.blockchain.derivationPath(cardDerivationStyle)?.rawPath + } + private suspend fun updateWalletStores( userWallet: UserWallet, blockchainNetworks: List, @@ -184,7 +178,19 @@ internal class DefaultWalletCurrenciesManager( .fold() } - private fun findDerivationPath(currency: Currency, cardDerivationStyle: DerivationStyle?): String? { - return currency.derivationPath ?: currency.blockchain.derivationPath(cardDerivationStyle)?.rawPath + private suspend fun updateWalletStoresAmounts( + userWallet: UserWallet, + updatedBlockchains: List, + ): CompletionResult { + val updatedWalletStores = walletStoresRepository.get(userWallet.walletId) + .firstOrNull() + ?.filter { it.blockchain in updatedBlockchains } + ?: return CompletionResult.Success(Unit) + + return walletAmountsRepository.updateAmountsForWalletStores( + walletStores = updatedWalletStores, + userWallet = userWallet, + fiatCurrency = appCurrencyProvider(), + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt index 7ad0e38363..64e2241737 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletDataOperations.kt @@ -158,12 +158,12 @@ internal fun List.updateWithUnreachable(): List.updateWithSelf( - walletsData: List, + newWalletsData: List, ): List { val oldWalletsData = this val updatedWalletsData = arrayListOf() - walletsData.forEach { newWalletData -> + newWalletsData.forEach { newWalletData -> val walletDataToUpdate = oldWalletsData.find(newWalletData::isSameWalletData) if (walletDataToUpdate != null) { updatedWalletsData.add(walletDataToUpdate.updateWithSelf(newWalletData)) diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt index 2aa7ffcf2d..0e9e9d8715 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/repository/implementation/utils/WalletStoreOperations.kt @@ -88,39 +88,34 @@ internal fun WalletStoreModel.updateWithRent(rent: WalletStoreModel.WalletRent?) ) } -internal fun WalletStoreModel.isSameWalletStore(other: WalletStoreModel): Boolean { - return this.blockchain == other.blockchain && - this.derivationPath == other.derivationPath -} - private inline fun List.replaceWalletStores( walletStoresToUpdate: List, update: (walletStore: WalletStoreModel) -> WalletStoreModel, ): List { val mutableStores = ArrayList(this) - walletStoresToUpdate - .asSequence() - .map { it.blockchain to it.derivationPath } - .forEach { (blockchain, derivationPath) -> - val index = mutableStores.indexOfFirst { - it.blockchain == blockchain && it.derivationPath == derivationPath - } - val currentWalletStore = mutableStores[index] - val updatedWalletStore = update(currentWalletStore) + walletStoresToUpdate.forEach { walletStoreToUpdate -> + val index = mutableStores.indexOfFirst(walletStoreToUpdate::isSameWalletStore) + val currentWalletStore = mutableStores[index] + val updatedWalletStore = update(currentWalletStore) - if (currentWalletStore != updatedWalletStore) { - Timber.d( - """ - Update wallet store in storage - |- User wallet ID: ${updatedWalletStore.userWalletId} - |- Blockchain: ${updatedWalletStore.blockchain} - """.trimIndent(), - ) + if (currentWalletStore != updatedWalletStore) { + Timber.d( + """ + Update wallet store in storage + |- User wallet ID: ${updatedWalletStore.userWalletId} + |- Blockchain: ${updatedWalletStore.blockchain} + """.trimIndent(), + ) - mutableStores[index] = updatedWalletStore - } + mutableStores[index] = updatedWalletStore } + } return mutableStores +} + +internal fun WalletStoreModel.isSameWalletStore(other: WalletStoreModel): Boolean { + return this.blockchain == other.blockchain && + this.derivationPath == other.derivationPath } \ No newline at end of file From a029f8527c2d1e6ee576d0e3dcda95800b6ecca1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Jan 2023 16:27:08 +0300 Subject: [PATCH 13/22] Updated on 2026-08-14 --- .../com/tangem/tap/common/analytics/events/Token.kt | 10 +++++----- .../onboarding/AddressInfoBottomSheetDialog.kt | 6 +++--- .../wallet/redux/middlewares/WalletMiddleware.kt | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt index 99badb9998..0ad3ca514e 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/Token.kt @@ -46,14 +46,14 @@ sealed class Token( params = mapOf("Token" to type.value), ) - sealed class Recieve( + sealed class Receive( event: String, params: Map = mapOf(), - ) : Token("Token / Recieve", event, params) { + ) : Token("Token / Receive", event, params) { - class ScreenOpened : Recieve("Recieve Screen Opened") - class ButtonCopyAddress : Recieve("Button - Copy Address") - class ButtonShareAddress : Recieve("Button - Share Address") + class ScreenOpened : Receive("Receive Screen Opened") + class ButtonCopyAddress : Receive("Button - Copy Address") + class ButtonShareAddress : Receive("Button - Share Address") } sealed class Send( diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt index 0372ae6ee4..66e30fe595 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/AddressInfoBottomSheetDialog.kt @@ -42,7 +42,7 @@ class AddressInfoBottomSheetDialog( override fun show() { super.show() - Analytics.send(Token.Recieve.ScreenOpened()) + Analytics.send(Token.Receive.ScreenOpened()) showData(data = stateDialog.addressData) } @@ -54,12 +54,12 @@ class AddressInfoBottomSheetDialog( imvQrCode.setImageBitmap(data.qrCode) tvAddress.text = data.address btnFlCopyAddress.setOnClickListener { - Analytics.send(Token.Recieve.ButtonCopyAddress()) + Analytics.send(Token.Receive.ButtonCopyAddress()) context.copyToClipboard(data.address) store.dispatchToastNotification(R.string.copy_toast_msg) } btnFlShare.setOnClickListener { - Analytics.send(Token.Recieve.ButtonShareAddress()) + Analytics.send(Token.Receive.ButtonShareAddress()) store.dispatchShare(data.shareUrl) } val blockchain = stateDialog.currency.blockchain diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index dc19d83445..1bbe68a519 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -249,12 +249,12 @@ class WalletMiddleware { } } is WalletAction.CopyAddress -> { - Analytics.send(Token.Recieve.ButtonCopyAddress()) + Analytics.send(Token.Receive.ButtonCopyAddress()) action.context.copyToClipboard(action.address) store.dispatch(WalletAction.CopyAddress.Success) } is WalletAction.ShareAddress -> { - Analytics.send(Token.Recieve.ButtonShareAddress()) + Analytics.send(Token.Receive.ButtonShareAddress()) action.context.shareText(action.address) } is WalletAction.ExploreAddress -> { From 9e8b302330cd07c609576cb5bb2d88425dad5f4c Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Jan 2023 16:48:34 +0300 Subject: [PATCH 14/22] Updated on 2026-08-14 --- .../com/tangem/tap/common/analytics/events/WalletConnect.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt index 2d6c404ce7..9ce10213ac 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/WalletConnect.kt @@ -11,7 +11,7 @@ sealed class WalletConnect( error: Throwable? = null, ) : AnalyticsEvent("Wallet Connect", event, params, error) { - class ScreenOpened : Settings(event = "WC Screen Opened") + class ScreenOpened : WalletConnect(event = "WC Screen Opened") class NewSessionEstablished : WalletConnect("New Session Established") class SessionDisconnected : WalletConnect("Session Disconnected") class RequestSigned : WalletConnect("Request Signed") From b80a3444de5f8288244d89d6bc983f27ba9167f4 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Jan 2023 17:01:14 +0300 Subject: [PATCH 15/22] Updated on 2026-08-14 --- .../tap/common/analytics/events/SignIn.kt | 17 +++++++++++++++++ .../tap/features/welcome/ui/WelcomeFragment.kt | 8 ++++++++ .../tap/features/welcome/ui/WelcomeViewModel.kt | 4 ++++ 3 files changed, 29 insertions(+) create mode 100644 app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt new file mode 100644 index 0000000000..5b7fff71ea --- /dev/null +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt @@ -0,0 +1,17 @@ +package com.tangem.tap.common.analytics.events + +import com.tangem.core.analytics.AnalyticsEvent + +/** +[REDACTED_AUTHOR] + */ +sealed class SignIn( + event: String, + params: Map = mapOf(), + error: Throwable? = null, +) : AnalyticsEvent("Sign In", event, params, error) { + + class ScreenOpened : SignIn(event = "Sing In Screen Opened") + class ButtonBiometricSignIn : SignIn(event = "Button - Biometric Sign In") + class ButtonCardSignIn : SignIn(event = "Button - Card Sign In") +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt index 9ff1ad727f..70477f5ad1 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeFragment.kt @@ -1,5 +1,6 @@ package com.tangem.tap.features.welcome.ui +import android.os.Bundle import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth @@ -18,9 +19,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.fragment.app.viewModels +import com.tangem.core.analytics.Analytics import com.tangem.core.ui.components.SystemBarsEffect import com.tangem.core.ui.fragments.ComposeFragment import com.tangem.core.ui.res.TangemTheme +import com.tangem.tap.common.analytics.events.SignIn import com.tangem.tap.features.details.ui.cardsettings.resolveReference import com.tangem.tap.features.welcome.ui.components.WelcomeScreenContent import com.tangem.wallet.R @@ -28,6 +31,11 @@ import com.tangem.wallet.R internal class WelcomeFragment : ComposeFragment() { private val viewModel by viewModels() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + Analytics.send(SignIn.ScreenOpened()) + } + @Composable override fun provideState(): State { return viewModel.state.collectAsState() diff --git a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt index a047d8518e..b810503287 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/ui/WelcomeViewModel.kt @@ -1,6 +1,8 @@ package com.tangem.tap.features.welcome.ui import androidx.lifecycle.ViewModel +import com.tangem.core.analytics.Analytics +import com.tangem.tap.common.analytics.events.SignIn import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.features.details.ui.cardsettings.TextReference import com.tangem.tap.features.welcome.redux.WelcomeAction @@ -21,10 +23,12 @@ internal class WelcomeViewModel : ViewModel(), StoreSubscriber { } fun unlockWallets() { + Analytics.send(SignIn.ButtonBiometricSignIn()) store.dispatch(WelcomeAction.ProceedWithBiometrics) } fun scanCard() { + Analytics.send(SignIn.ButtonCardSignIn()) store.dispatch(WelcomeAction.ProceedWithCard) } From ecb01b46528b2dd395719ec81c99ff5ddbea162c Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Jan 2023 18:54:12 +0300 Subject: [PATCH 16/22] Updated on 2026-08-14 --- .../tap/common/analytics/events/MyWallets.kt | 16 +++++++-------- .../tap/domain/scanCard/ScanCardProcessor.kt | 19 ++++++++++++------ .../tap/features/home/redux/HomeAction.kt | 7 +++---- .../tap/features/home/redux/HomeMiddleware.kt | 20 +++++-------------- .../tap/features/home/redux/HomeReducer.kt | 3 --- .../tap/features/home/redux/HomeState.kt | 1 - .../tap/features/wallet/redux/WalletAction.kt | 3 ++- .../middlewares/MultiWalletMiddleware.kt | 5 +++-- .../redux/middlewares/WalletMiddleware.kt | 8 ++++++-- .../redux/WalletSelectorMiddleware.kt | 11 +++++----- .../ui/WalletSelectorBottomSheetFragment.kt | 4 ++-- .../welcome/redux/WelcomeMiddleware.kt | 2 ++ 12 files changed, 49 insertions(+), 50 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt index 2b660fa11d..d83a8371d6 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt @@ -7,14 +7,14 @@ sealed class MyWallets( params: Map = mapOf(), ) : AnalyticsEvent("My Wallets", event, params) { - object MyWalletsScreenOpened : MyWallets(event = "My Wallets Screen Opened") - object CardWasScanned : MyWallets(event = "Card Was Scanned") - object WalletUnlockTapped : MyWallets(event = "Wallet Unlock Tapped") + class MyWalletsScreenOpened : MyWallets(event = "My Wallets Screen Opened") + class CardWasScanned : MyWallets(event = "Card Was Scanned") + class WalletUnlockTapped : MyWallets(event = "Wallet Unlock Tapped") - object Button { - object ScanNewCard : MyWallets(event = "Button - Scan New Card") - object UnlockWithBiometrics : MyWallets(event = "Button - Unlock all with Face ID") - object EditWalletTapped : MyWallets(event = "Button - Edit Wallet Tapped") - object DeleteWalletTapped : MyWallets(event = "Button - Delete Wallet Tapped") + sealed class Button { + class ScanNewCard : MyWallets(event = "Button - Scan New Card") + class UnlockWithBiometrics : MyWallets(event = "Button - Unlock all with Face ID") + class EditWalletTapped : MyWallets(event = "Button - Edit Wallet Tapped") + class DeleteWalletTapped : MyWallets(event = "Button - Delete Wallet Tapped") } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt b/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt index 7b33c2f9fc..b9e8f526f9 100644 --- a/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt +++ b/app/src/main/java/com/tangem/tap/domain/scanCard/ScanCardProcessor.kt @@ -6,13 +6,13 @@ import com.tangem.common.core.TangemSdkError import com.tangem.common.doOnFailure import com.tangem.common.doOnSuccess import com.tangem.common.services.Result +import com.tangem.core.analytics.Analytics +import com.tangem.core.analytics.AnalyticsEvent import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.extensions.withMainContext import com.tangem.operations.backup.BackupService import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE import com.tangem.tap.backupService -import com.tangem.core.analytics.Analytics -import com.tangem.tap.common.analytics.events.IntroductionProcess import com.tangem.tap.common.analytics.paramsInterceptor.BatchIdParamsInterceptor import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchOnMain @@ -45,6 +45,7 @@ import kotlinx.coroutines.launch // TODO: Create repository for that object ScanCardProcessor { suspend fun scan( + analyticsEvent: AnalyticsEvent? = null, additionalBlockchainsToDerive: Collection? = null, cardId: String? = null, onProgressStateChange: suspend (showProgress: Boolean) -> Unit = {}, @@ -77,6 +78,8 @@ object ScanCardProcessor { tangemSdkManager.changeDisplayedCardIdNumbersCount(scanResponse) onScanStateChange(false) + sendAnalytics(analyticsEvent, scanResponse.card.batchId) + checkForUnfinishedBackupForSaltPay( backupService = backupService, scanResponse = scanResponse, @@ -102,6 +105,14 @@ object ScanCardProcessor { } } + private fun sendAnalytics( + analyticsEvent: AnalyticsEvent?, + batchId: String, + ) { + Analytics.addParamsInterceptor(BatchIdParamsInterceptor(batchId)) + analyticsEvent?.let { Analytics.send(it) } + } + /** * It checks only the SaltPay cards. To check for unfinished backups for the standard Wallet cards * see BackupAction.CheckForUnfinishedBackup @@ -173,14 +184,10 @@ object ScanCardProcessor { crossinline onSuccess: suspend (ScanResponse) -> Unit, crossinline onFailure: suspend (error: TangemError) -> Unit, ) { - Analytics.send(IntroductionProcess.CardWasScanned()) - val globalState = store.state.globalState val tapWalletManager = globalState.tapWalletManager tapWalletManager.updateConfigManager(scanResponse) - Analytics.addParamsInterceptor(BatchIdParamsInterceptor(scanResponse.card.batchId)) - store.dispatchOnMain(TwinCardsAction.IfTwinsPrepareState(scanResponse)) if (scanResponse.isSaltPay()) { diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt index e7d0c79e2e..59e169ee04 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeAction.kt @@ -1,17 +1,16 @@ package com.tangem.tap.features.home.redux +import com.tangem.core.analytics.AnalyticsEvent +import com.tangem.tap.common.analytics.events.IntroductionProcess import com.tangem.tap.common.entities.IndeterminateProgressButton -import com.tangem.tap.common.redux.navigation.AppScreen import org.rekotlin.Action sealed class HomeAction : Action { object Init : HomeAction() - data class ShouldScanCardOnResume(val shouldScanCard: Boolean) : HomeAction() - // from ui data class ReadCard( - val fromScreen: AppScreen = AppScreen.Home, + val analyticsEvent: AnalyticsEvent? = IntroductionProcess.CardWasScanned(), ) : HomeAction() data class ScanInProgress(val scanInProgress: Boolean) : HomeAction() diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt index 33bf357557..b85a6601c5 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeMiddleware.kt @@ -4,16 +4,13 @@ import com.tangem.common.doOnFailure import com.tangem.common.doOnResult import com.tangem.common.doOnSuccess import com.tangem.core.analytics.Analytics -import com.tangem.tap.common.analytics.events.IntroductionProcess -import com.tangem.tap.common.analytics.events.MainScreen +import com.tangem.core.analytics.AnalyticsEvent import com.tangem.tap.common.analytics.events.Shop -import com.tangem.tap.common.analytics.paramsInterceptor.BatchIdParamsInterceptor import com.tangem.tap.common.entities.IndeterminateProgressButton import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.dispatchOpenUrl import com.tangem.tap.common.extensions.onCardScanned import com.tangem.tap.common.extensions.onUserWalletSelected -import com.tangem.tap.common.postUiDelayBg import com.tangem.tap.common.redux.AppState import com.tangem.tap.common.redux.global.GlobalAction import com.tangem.tap.common.redux.navigation.AppScreen @@ -59,13 +56,9 @@ private fun handleHomeAction(action: Action) { store.dispatch(GlobalAction.ExchangeManager.Init) store.dispatch(GlobalAction.FetchUserCountry) } - is HomeAction.ShouldScanCardOnResume -> { - if (action.shouldScanCard) { - store.dispatch(HomeAction.ShouldScanCardOnResume(false)) - postUiDelayBg(700) { store.dispatch(HomeAction.ReadCard(AppScreen.Wallet)) } - } + is HomeAction.ReadCard -> { + readCard(action.analyticsEvent) } - is HomeAction.ReadCard -> readCard(action.fromScreen) is HomeAction.GoToShop -> { Analytics.send(Shop.ScreenOpened()) when (action.userCountryCode) { @@ -76,12 +69,13 @@ private fun handleHomeAction(action: Action) { } } -private fun readCard(fromScreen: AppScreen) = scope.launch { +private fun readCard(analyticsEvent: AnalyticsEvent?) = scope.launch { delay(timeMillis = 200) tangemSdkManager.setAccessCodeRequestPolicy( useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes, ) ScanCardProcessor.scan( + analyticsEvent = analyticsEvent, onProgressStateChange = { showProgress -> if (showProgress) { changeButtonState(ButtonState.PROGRESS) @@ -97,10 +91,6 @@ private fun readCard(fromScreen: AppScreen) = scope.launch { changeButtonState(ButtonState.ENABLED) }, onSuccess = { scanResponse -> - when (fromScreen) { - AppScreen.Wallet -> Analytics.send(MainScreen.CardWasScanned()) - else -> Analytics.send(IntroductionProcess.CardWasScanned()) - } scope.launch { if (preferencesStorage.shouldSaveUserWallets) { val userWallet = UserWalletBuilder(scanResponse).build() ?: return@launch diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt index 511aea3ddc..8e1583baa5 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeReducer.kt @@ -18,9 +18,6 @@ private fun internalReduce(action: Action, state: AppState): HomeState { is HomeAction.ScanInProgress -> { state = state.copy(scanInProgress = action.scanInProgress) } - is HomeAction.ShouldScanCardOnResume -> { - state = state.copy(shouldScanCardOnResume = action.shouldScanCard) - } is HomeAction.ChangeScanCardButtonState -> { state = state.copy(btnScanState = action.state) } diff --git a/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt b/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt index 9ef6ea2b57..618e432dec 100644 --- a/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt +++ b/app/src/main/java/com/tangem/tap/features/home/redux/HomeState.kt @@ -6,7 +6,6 @@ import com.tangem.tap.features.wallet.redux.ProgressState import org.rekotlin.StateType data class HomeState( - val shouldScanCardOnResume: Boolean = false, val scanInProgress: Boolean = false, val btnScanState: IndeterminateProgressButton = IndeterminateProgressButton(ButtonState.ENABLED), ) : StateType { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index 0cc8039e96..c261f4c7ba 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -7,6 +7,7 @@ import com.tangem.blockchain.common.Token import com.tangem.blockchain.common.Wallet import com.tangem.blockchain.common.WalletManager import com.tangem.blockchain.common.address.AddressType +import com.tangem.core.analytics.AnalyticsEvent import com.tangem.domain.common.CardDTO import com.tangem.tap.common.entities.FiatCurrency import com.tangem.tap.common.redux.NotificationAction @@ -142,7 +143,7 @@ sealed class WalletAction : Action { object Failure : WalletAction() } - object Scan : WalletAction() + data class Scan(val onScanSuccessEvent: AnalyticsEvent?) : WalletAction() data class Send(val amount: Amount? = null) : WalletAction() diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index 87341ef9c0..1a9f71f51a 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -5,8 +5,8 @@ import com.tangem.blockchain.common.Token import com.tangem.blockchain.common.WalletManager import com.tangem.common.doOnSuccess import com.tangem.common.extensions.guard -import com.tangem.domain.common.extensions.withMainContext import com.tangem.core.analytics.Analytics +import com.tangem.domain.common.extensions.withMainContext import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.common.analytics.events.Token.ButtonRemoveToken @@ -173,7 +173,7 @@ class MultiWalletMiddleware { if (selectedWallet != null) { scanAndUpdateCard(selectedWallet, walletState) } else { - store.dispatch(WalletAction.Scan) + store.dispatch(WalletAction.Scan(onScanSuccessEvent = null)) } } } @@ -185,6 +185,7 @@ class MultiWalletMiddleware { ) = scope.launch(Dispatchers.Default) { Analytics.send(MainScreen.CardWasScanned()) ScanCardProcessor.scan( + analyticsEvent = null, cardId = selectedUserWallet.cardId, additionalBlockchainsToDerive = state?.missingDerivations?.map { it.blockchain }, ) { scanResponse -> diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index 1bbe68a519..a20c8b5b36 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -59,6 +59,7 @@ import com.tangem.wallet.R import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.rekotlin.Action import org.rekotlin.DispatchFunction @@ -194,8 +195,11 @@ class WalletMiddleware { } } is WalletAction.Scan -> { - store.dispatch(HomeAction.ShouldScanCardOnResume(true)) store.dispatch(NavigationAction.PopBackTo(AppScreen.Home)) + scope.launch { + delay(700) + store.dispatchOnMain(HomeAction.ReadCard(action.onScanSuccessEvent)) + } } is WalletAction.LoadCardInfo -> { val attestationFailed = action.card.attestation.status == Attestation.Status.Failed @@ -366,7 +370,7 @@ class WalletMiddleware { } else -> { Analytics.send(MainScreen.ButtonScanCard()) - store.dispatch(WalletAction.Scan) + store.dispatch(WalletAction.Scan(MainScreen.CardWasScanned())) } } } diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt index 38832e455a..ed12b4cd7b 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt @@ -121,7 +121,7 @@ internal class WalletSelectorMiddleware { } private fun unlockWalletsWithBiometry() { - Analytics.send(MyWallets.Button.UnlockWithBiometrics) + Analytics.send(MyWallets.Button.UnlockWithBiometrics()) scope.launch { userWalletsListManager.unlockWithBiometry() @@ -135,7 +135,7 @@ internal class WalletSelectorMiddleware { } private fun addWallet() = scope.launch { - Analytics.send(MyWallets.Button.ScanNewCard) + Analytics.send(MyWallets.Button.ScanNewCard()) val prevUseBiometricsForAccessCode = tangemSdkManager.useBiometricsForAccessCode() @@ -145,6 +145,7 @@ internal class WalletSelectorMiddleware { ) ScanCardProcessor.scan( + analyticsEvent = MyWallets.CardWasScanned(), onWalletNotCreated = { // No need to rollback policy, continue with the policy set before the card scan store.dispatchOnMain(WalletSelectorAction.AddWallet.Success) @@ -175,8 +176,6 @@ internal class WalletSelectorMiddleware { return userWalletsListManager.save(userWallet) .doOnSuccess { - Analytics.send(MyWallets.CardWasScanned) - store.dispatchOnMain(WalletSelectorAction.AddWallet.Success) store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet)) store.onUserWalletSelected(userWallet) @@ -227,7 +226,7 @@ internal class WalletSelectorMiddleware { } private fun deleteWallets(userWalletsIds: List, state: WalletSelectorState) { - Analytics.send(MyWallets.Button.DeleteWalletTapped) + Analytics.send(MyWallets.Button.DeleteWalletTapped()) scope.launch { when (userWalletsIds.size) { @@ -244,7 +243,7 @@ internal class WalletSelectorMiddleware { } private fun renameWallet(userWalletId: UserWalletId, newName: String) { - Analytics.send(MyWallets.Button.EditWalletTapped) + Analytics.send(MyWallets.Button.EditWalletTapped()) scope.launch { userWalletsListManager.update(userWalletId) { it.copy(name = newName) } diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorBottomSheetFragment.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorBottomSheetFragment.kt index 96bba1df0e..f8bc829bde 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorBottomSheetFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorBottomSheetFragment.kt @@ -20,9 +20,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.rememberNestedScrollInteropConnection import androidx.fragment.app.viewModels +import com.tangem.core.analytics.Analytics import com.tangem.core.ui.fragments.ComposeBottomSheetFragment import com.tangem.core.ui.res.TangemTheme -import com.tangem.core.analytics.Analytics import com.tangem.tap.common.analytics.events.MyWallets import com.tangem.tap.features.details.ui.cardsettings.resolveReference import com.tangem.tap.features.walletSelector.ui.components.RenameWalletDialogContent @@ -33,7 +33,7 @@ internal class WalletSelectorBottomSheetFragment : ComposeBottomSheetFragment() override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - Analytics.send(MyWallets.MyWalletsScreenOpened) + Analytics.send(MyWallets.MyWalletsScreenOpened()) return super.onCreateDialog(savedInstanceState) } diff --git a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt index e7cb2e01e7..808f4ea74f 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt @@ -4,6 +4,7 @@ import android.content.Intent import com.tangem.common.doOnFailure import com.tangem.common.doOnSuccess import com.tangem.domain.common.ScanResponse +import com.tangem.tap.common.analytics.events.IntroductionProcess import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.onUserWalletSelected import com.tangem.tap.common.redux.AppState @@ -98,6 +99,7 @@ internal class WelcomeMiddleware { useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes, ) ScanCardProcessor.scan( + analyticsEvent = IntroductionProcess.CardWasScanned(), onSuccess = { scanResponse -> scope.launch { onCardScanned(scanResponse) } }, From caaea924a27341d304b2cc21c18c09e2767b940f Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Jan 2023 20:17:29 +0300 Subject: [PATCH 17/22] Updated on 2026-08-14 --- .../saveWallet/ui/SaveWalletBottomSheetFragment.kt | 11 +++++++---- .../tap/features/saveWallet/ui/SaveWalletViewModel.kt | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/saveWallet/ui/SaveWalletBottomSheetFragment.kt b/app/src/main/java/com/tangem/tap/features/saveWallet/ui/SaveWalletBottomSheetFragment.kt index f4663eda6e..63803d4095 100644 --- a/app/src/main/java/com/tangem/tap/features/saveWallet/ui/SaveWalletBottomSheetFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/saveWallet/ui/SaveWalletBottomSheetFragment.kt @@ -28,9 +28,9 @@ internal class SaveWalletBottomSheetFragment : ComposeBottomSheetFragment() - override fun onDismiss(dialog: DialogInterface) { - viewModel.dismiss() - super.onDismiss(dialog) + override fun onCancel(dialog: DialogInterface) { + viewModel.cancelOrClose() + super.onCancel(dialog) } @Composable @@ -51,7 +51,10 @@ internal class SaveWalletBottomSheetFragment : ComposeBottomSheetFragment Date: Mon, 23 Jan 2023 22:13:52 +0300 Subject: [PATCH 18/22] Updated on 2026-08-14 --- .../java/com/tangem/tap/common/analytics/events/MyWallets.kt | 2 +- .../features/walletSelector/redux/WalletSelectorMiddleware.kt | 3 +-- .../tap/features/walletSelector/ui/WalletSelectorViewModel.kt | 3 +++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt index d83a8371d6..4db0526ad2 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/MyWallets.kt @@ -9,12 +9,12 @@ sealed class MyWallets( class MyWalletsScreenOpened : MyWallets(event = "My Wallets Screen Opened") class CardWasScanned : MyWallets(event = "Card Was Scanned") - class WalletUnlockTapped : MyWallets(event = "Wallet Unlock Tapped") sealed class Button { class ScanNewCard : MyWallets(event = "Button - Scan New Card") class UnlockWithBiometrics : MyWallets(event = "Button - Unlock all with Face ID") class EditWalletTapped : MyWallets(event = "Button - Edit Wallet Tapped") class DeleteWalletTapped : MyWallets(event = "Button - Delete Wallet Tapped") + class WalletUnlockTapped : MyWallets(event = "Button - Wallet Unlock Tapped") } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt index ed12b4cd7b..fcf97e11db 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt @@ -206,6 +206,7 @@ internal class WalletSelectorMiddleware { } private suspend fun unlockUserWalletWithScannedCard(userWallet: UserWallet): CompletionResult { + Analytics.send(MyWallets.Button.WalletUnlockTapped()) tangemSdkManager.changeDisplayedCardIdNumbersCount(userWallet.scanResponse) return tangemSdkManager.scanCard(userWallet.cardId) .map { scannedCard -> @@ -243,8 +244,6 @@ internal class WalletSelectorMiddleware { } private fun renameWallet(userWalletId: UserWalletId, newName: String) { - Analytics.send(MyWallets.Button.EditWalletTapped()) - scope.launch { userWalletsListManager.update(userWalletId) { it.copy(name = newName) } .doOnFailure { error -> diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt index 52a99013e3..edb923f5ba 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/ui/WalletSelectorViewModel.kt @@ -2,7 +2,9 @@ package com.tangem.tap.features.walletSelector.ui import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.tangem.core.analytics.Analytics import com.tangem.domain.common.util.UserWalletId +import com.tangem.tap.common.analytics.events.MyWallets import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.features.walletSelector.redux.WalletSelectorAction import com.tangem.tap.features.walletSelector.redux.WalletSelectorState @@ -71,6 +73,7 @@ internal class WalletSelectorViewModel : ViewModel(), StoreSubscriber From 35dbee86913c6777370d682261c0cd92a43464d5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 23 Jan 2023 23:09:44 +0300 Subject: [PATCH 19/22] Updated on 2026-08-14 --- .../features/wallet/redux/middlewares/MultiWalletMiddleware.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index 1a9f71f51a..e6632583c4 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -8,7 +8,6 @@ import com.tangem.common.extensions.guard import com.tangem.core.analytics.Analytics import com.tangem.domain.common.extensions.withMainContext import com.tangem.tap.common.analytics.events.AnalyticsParam -import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.common.analytics.events.Token.ButtonRemoveToken import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchErrorNotification @@ -183,7 +182,6 @@ class MultiWalletMiddleware { selectedUserWallet: UserWallet, state: WalletState?, ) = scope.launch(Dispatchers.Default) { - Analytics.send(MainScreen.CardWasScanned()) ScanCardProcessor.scan( analyticsEvent = null, cardId = selectedUserWallet.cardId, From 3a57ac60c2204d3566463faf7dab94dda283533c Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 25 Jan 2023 01:33:28 +0300 Subject: [PATCH 20/22] Updated on 2026-08-14 --- .../converters/BasicEventConverter.kt | 171 +++++++++++++----- .../converters/ParamCardCurrencyConverter.kt | 1 + .../filters/ShopPurchasedEventFilter.kt | 0 .../com/tangem/tap/domain/TapWalletManager.kt | 7 +- .../walletStores/WalletStoresManager.kt | 1 + .../DefaultWalletStoresManager.kt | 4 + .../DummyWalletStoresManager.kt | 4 + .../tap/features/wallet/redux/WalletAction.kt | 1 + .../tap/features/wallet/redux/WalletState.kt | 4 + .../middlewares/MultiWalletMiddleware.kt | 4 + .../redux/middlewares/WalletMiddleware.kt | 21 +++ .../redux/reducers/MultiWalletReducer.kt | 8 +- .../tap/features/wallet/ui/WalletFragment.kt | 12 +- 13 files changed, 177 insertions(+), 61 deletions(-) delete mode 100644 app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt index 4936e61523..1eeda46c6f 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/BasicEventConverter.kt @@ -2,77 +2,156 @@ package com.tangem.tap.common.analytics.converters import com.tangem.common.Converter import com.tangem.common.extensions.isZero +import com.tangem.core.analytics.Analytics import com.tangem.domain.common.ScanResponse import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.Basic import com.tangem.tap.common.analytics.filters.BasicTopUpFilter import com.tangem.tap.domain.extensions.isMultiwalletAllowed +import com.tangem.tap.domain.model.WalletDataModel import com.tangem.tap.domain.model.builders.UserWalletIdBuilder import com.tangem.tap.features.wallet.redux.ProgressState -import com.tangem.tap.features.wallet.redux.WalletData import com.tangem.tap.features.wallet.redux.WalletState import com.tangem.tap.features.wallet.redux.reducers.calculateTotalCryptoAmount +import timber.log.Timber +import java.math.BigDecimal /** [REDACTED_AUTHOR] */ -class BasicSignInEventConverter( - private val scanResponse: ScanResponse, -) : Converter { +class BasicEventsPreChecker { - override fun convert(value: WalletState): Basic.SignedIn? { - if (!statesIsReadyToCreateEvent(scanResponse, value)) return null - val cardCurrency = ParamCardCurrencyConverter().convert(scanResponse) ?: return null + fun tryToSend(converterData: BasicEventsSourceData) { + if (!isReadyToSend(converterData)) return + + BasicSignInEventConverter().convert(converterData)?.let { Analytics.send(it) } + BasicTopUpEventConverter().convert(converterData)?.let { Analytics.send(it) } + } + + private fun isReadyToSend(data: BasicEventsSourceData): Boolean { + val (scanResponse, walletState, biometricsWalletDataModels) = data + if (walletState.derivationsCheckIsScheduled) { + Timber.d("FAILED: derivationsCheckIsScheduled") + return false + } + if (scanResponse.card.isMultiwalletAllowed && walletState.missingDerivations.isNotEmpty()) { + Timber.d("FAILED: isMultiwalletAllowed || missingDerivations.isNotEmpty") + return false + } + + if (biometricsWalletDataModels == null) { + Timber.d("SWITCH: OLD") + val walletsDataFromStores = data.walletState.walletsDataFromStores + if (walletsDataFromStores.isEmpty()) { + Timber.d("FAILED: walletsDataFromStores.isEmpty") + return false + } + + val totalBalanceState = data.walletState.totalBalance?.state + if (totalBalanceState == null || totalBalanceState == ProgressState.Loading || + totalBalanceState == ProgressState.Refreshing + ) { + Timber.d("FAILED: totalBalanceState: ${totalBalanceState?.name}") + return false + } + + val balancesCount = walletsDataFromStores + .map { if (it.currencyData.amount == null) 0 else 1 } + .reduce { acc, i -> acc + i } + + if (balancesCount != walletsDataFromStores.size) { + Timber.d("FAILED: balancesCount != walletsDataFromStores.size") + return false + } + } else { + Timber.d("SWITCH: BIOMETRICS") + if (biometricsWalletDataModels.isEmpty()) { + Timber.d("FAILED: biometricsWalletDataModels.isEmpty") + return false + } + + if (biometricsWalletDataModels.any { + it.status is WalletDataModel.Loading || + it.status is WalletDataModel.NoAccount || + it.status is WalletDataModel.Unreachable || + it.status is WalletDataModel.MissedDerivation || + it.status.isErrorStatus + }) { + Timber.d("FAILED: by status") + return false + } + } + + Timber.d("SUCCESS") + return true + } +} + +/** + * With biometrics enabled, we should check its storage instead of "WalletState.walletsDataFromStores" + * because the latter is updated after some time. + * @property biometricsWalletDataModels - wallet data models from the 'WalletStoresManager'. If null, then + * the "WalletState.walletsDataFromStores" will be used to determine appropriate state + */ +data class BasicEventsSourceData( + val scanResponse: ScanResponse, + val walletState: WalletState, + val biometricsWalletDataModels: List?, +) { + val batchId: String by lazy { scanResponse.card.batchId } + + val userWalletIdStringValue: String? by lazy { + UserWalletIdBuilder.scanResponse(scanResponse) + .build() + ?.stringValue + } + + val paramCardCurrency: AnalyticsParam.CardCurrency? by lazy { ParamCardCurrencyConverter().convert(scanResponse) } + + val paramCardBalanceState: AnalyticsParam.CardBalanceState by lazy { calculateAmount().toCardBalanceState() } + + private fun calculateAmount(): BigDecimal { + return biometricsWalletDataModels?.calculateTotalCryptoAmount() + ?: walletState.walletsDataFromStores.calculateTotalCryptoAmount() + } + + private fun BigDecimal.toCardBalanceState(): AnalyticsParam.CardBalanceState = when { + isZero() -> AnalyticsParam.CardBalanceState.Empty + else -> AnalyticsParam.CardBalanceState.Full + } + + private fun List.calculateTotalCryptoAmount(): BigDecimal { + return this + .map { it.status.amount } + .reduce(BigDecimal::plus) + } +} + +class BasicSignInEventConverter : Converter { + + override fun convert(value: BasicEventsSourceData): Basic.SignedIn? { + if (value.paramCardCurrency == null || value.userWalletIdStringValue == null) return null return Basic.SignedIn( - state = AnalyticsParam.CardBalanceState.from(value.walletsDataFromStores), - currency = cardCurrency, - batch = scanResponse.card.batchId, + state = value.paramCardBalanceState, + currency = value.paramCardCurrency!!, + batch = value.batchId, ).apply { - filterData = UserWalletIdBuilder.scanResponse(scanResponse) - .build() - ?.stringValue + filterData = value.userWalletIdStringValue } } } -class BasicTopUpEventConverter( - private val scanResponse: ScanResponse, -) : Converter { +class BasicTopUpEventConverter : Converter { - override fun convert(value: WalletState): Basic.ToppedUp? { - if (!statesIsReadyToCreateEvent(scanResponse, value)) return null - val cardCurrency = ParamCardCurrencyConverter().convert(scanResponse) ?: return null + override fun convert(value: BasicEventsSourceData): Basic.ToppedUp? { + if (value.paramCardCurrency == null || value.userWalletIdStringValue == null) return null val data = BasicTopUpFilter.Data( - walletId = UserWalletIdBuilder.scanResponse(scanResponse).build()?.stringValue ?: "", - cardBalanceState = AnalyticsParam.CardBalanceState.from(value.walletsDataFromStores), + walletId = value.userWalletIdStringValue!!, + cardBalanceState = value.paramCardBalanceState, ) - return Basic.ToppedUp(cardCurrency).apply { filterData = data } + return Basic.ToppedUp(value.paramCardCurrency!!).apply { filterData = data } } -} - -private fun AnalyticsParam.CardBalanceState.Companion.from(walletsData: List): AnalyticsParam.CardBalanceState { - val totalCryptoAmount = walletsData.calculateTotalCryptoAmount() - return when { - totalCryptoAmount.isZero() -> AnalyticsParam.CardBalanceState.Empty - else -> AnalyticsParam.CardBalanceState.Full - } -} - -private fun statesIsReadyToCreateEvent(scanResponse: ScanResponse, state: WalletState): Boolean { - if (scanResponse.card.isMultiwalletAllowed && state.missingDerivations.isNotEmpty()) return false - if (state.walletsDataFromStores.isEmpty()) return false - - val totalBalanceState = state.totalBalance?.state ?: return false - if (totalBalanceState == ProgressState.Loading || totalBalanceState == ProgressState.Refreshing) return false - - val balancesCount = state.walletsDataFromStores.map { - if (it.currencyData.amount == null) 0 else 1 - }.reduce { acc, i -> acc + i } - - if (balancesCount != state.walletsDataFromStores.size) return false - - return true } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt b/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt index e64b751f4f..e359de8e5a 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/converters/ParamCardCurrencyConverter.kt @@ -22,6 +22,7 @@ class ParamCardCurrencyConverter : Converter AnalyticsParam.CurrencyType.Blockchain(Blockchain.Bitcoin) value.isSaltPay() -> AnalyticsParam.CurrencyType.Token(SaltPayWorkaround.tokenFrom(Blockchain.SaltPay)) + value.getBlockchain() != Blockchain.Unknown -> AnalyticsParam.CurrencyType.Blockchain(value.getBlockchain()) value.getPrimaryToken() != null -> AnalyticsParam.CurrencyType.Token(value.getPrimaryToken()!!) else -> null } ?: return null diff --git a/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt b/app/src/main/java/com/tangem/tap/common/analytics/filters/ShopPurchasedEventFilter.kt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt index ea26d15848..4eb41fd759 100644 --- a/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/TapWalletManager.kt @@ -31,6 +31,7 @@ import com.tangem.tap.features.details.redux.walletconnect.WalletConnectAction import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction import com.tangem.tap.features.wallet.models.toBlockchainNetworks import com.tangem.tap.features.wallet.redux.WalletAction +import com.tangem.tap.features.wallet.redux.middlewares.handleBasicAnalyticsEvent import com.tangem.tap.network.NetworkConnectivity import com.tangem.tap.store import com.tangem.tap.tangemSdkManager @@ -117,6 +118,7 @@ class TapWalletManager { .doOnSuccess { Timber.d("Wallet stores fetched for ${userWallet.walletId}") store.dispatchOnMain(WalletAction.LoadData.Success) + handleBasicAnalyticsEvent() } .doOnFailure { error -> val errorAction = when (error) { @@ -190,6 +192,7 @@ class TapWalletManager { } if (data.card.isMultiwalletAllowed) { + dispatchOnMain(WalletAction.MultiWallet.ScheduleCheckForMissingDerivation) loadMultiWalletData(data) } else { loadSingleWalletData(data) @@ -212,9 +215,7 @@ class TapWalletManager { .filter { it.derivationPath != null && !scanResponse.hasDerivation(it.blockchain, it.derivationPath) } - if (missingDerivations.isNotEmpty()) { - store.dispatch(WalletAction.MultiWallet.AddMissingDerivations(missingDerivations)) - } + store.dispatch(WalletAction.MultiWallet.AddMissingDerivations(missingDerivations)) } private suspend fun loadSingleWalletData(data: ScanResponse) { diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/WalletStoresManager.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/WalletStoresManager.kt index e834cf0541..f1fdaff7aa 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/WalletStoresManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/WalletStoresManager.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.Flow interface WalletStoresManager { fun getAll(): Flow>> fun get(userWalletId: UserWalletId): Flow> + suspend fun getSync(userWalletId: UserWalletId): List suspend fun delete(userWalletsIds: List): CompletionResult suspend fun clear(): CompletionResult diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt index 219d7f4af1..22e86d2fa1 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DefaultWalletStoresManager.kt @@ -44,6 +44,10 @@ internal class DefaultWalletStoresManager( .distinctUntilChanged() } + override suspend fun getSync(userWalletId: UserWalletId): List { + return walletStoresRepository.getSync(userWalletId) + } + override suspend fun delete(userWalletsIds: List): CompletionResult { return walletStoresRepository.delete(userWalletsIds) .flatMap { walletManagersRepository.delete(userWalletsIds) } diff --git a/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DummyWalletStoresManager.kt b/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DummyWalletStoresManager.kt index b1729a0b11..7657f2d47b 100644 --- a/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DummyWalletStoresManager.kt +++ b/app/src/main/java/com/tangem/tap/domain/walletStores/implementation/DummyWalletStoresManager.kt @@ -17,6 +17,10 @@ internal class DummyWalletStoresManager : WalletStoresManager { return emptyFlow() } + override suspend fun getSync(userWalletId: UserWalletId): List { + return emptyList() + } + override suspend fun delete(userWalletsIds: List): CompletionResult { return CompletionResult.Success(Unit) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt index c261f4c7ba..dc3e074fac 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletAction.kt @@ -102,6 +102,7 @@ sealed class WalletAction : Action { data class SetPrimaryToken(val token: Token) : MultiWallet() data class ShowWalletBackupWarning(val show: Boolean) : MultiWallet() object BackupWallet : MultiWallet() + object ScheduleCheckForMissingDerivation : MultiWallet() data class AddMissingDerivations(val blockchains: List) : MultiWallet() object ScanToGetDerivations : MultiWallet() } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt index 49773a9854..0566b5d4a4 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/WalletState.kt @@ -29,6 +29,9 @@ import org.rekotlin.StateType import java.math.BigDecimal import kotlin.properties.ReadOnlyProperty +/** + * @property derivationsCheckIsScheduled - used only for analytics + */ data class WalletState( val cardId: String = "", val state: ProgressState = ProgressState.Done, @@ -46,6 +49,7 @@ data class WalletState( val totalBalance: TotalBalance? = null, val showBackupWarning: Boolean = false, val missingDerivations: List = emptyList(), + val derivationsCheckIsScheduled: Boolean = false, val loadingUserTokens: Boolean = false, val walletCardsCount: Int? = null, ) : StateType { diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt index e6632583c4..e6798ea6ca 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/MultiWalletMiddleware.kt @@ -167,6 +167,9 @@ class MultiWalletMiddleware { store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingWallet)) } } + is WalletAction.MultiWallet.AddMissingDerivations -> { + scope.launch { handleBasicAnalyticsEvent() } + } is WalletAction.MultiWallet.ScanToGetDerivations -> { val selectedWallet = userWalletsListManager.selectedUserWalletSync if (selectedWallet != null) { @@ -182,6 +185,7 @@ class MultiWalletMiddleware { selectedUserWallet: UserWallet, state: WalletState?, ) = scope.launch(Dispatchers.Default) { + dispatchOnMain(WalletAction.MultiWallet.ScheduleCheckForMissingDerivation) ScanCardProcessor.scan( analyticsEvent = null, cardId = selectedUserWallet.cardId, diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt index a20c8b5b36..80b1ddfc2b 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/middlewares/WalletMiddleware.kt @@ -12,6 +12,8 @@ import com.tangem.core.analytics.Analytics import com.tangem.domain.common.extensions.withMainContext import com.tangem.operations.attestation.Attestation import com.tangem.operations.attestation.OnlineCardVerifier +import com.tangem.tap.common.analytics.converters.BasicEventsPreChecker +import com.tangem.tap.common.analytics.converters.BasicEventsSourceData import com.tangem.tap.common.analytics.events.AnalyticsParam import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.common.analytics.events.Token @@ -34,6 +36,7 @@ import com.tangem.tap.domain.failedRates import com.tangem.tap.domain.loadedRates import com.tangem.tap.domain.model.WalletDataModel import com.tangem.tap.domain.model.WalletStoreModel +import com.tangem.tap.domain.model.builders.UserWalletIdBuilder import com.tangem.tap.features.demo.DemoHelper import com.tangem.tap.features.home.redux.HomeAction import com.tangem.tap.features.send.redux.PrepareSendScreen @@ -55,6 +58,7 @@ import com.tangem.tap.tangemSdkManager import com.tangem.tap.totalFiatBalanceCalculator import com.tangem.tap.userWalletsListManager import com.tangem.tap.userWalletsListManagerSafe +import com.tangem.tap.walletStoresManager import com.tangem.wallet.R import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async @@ -108,6 +112,7 @@ class WalletMiddleware { walletState.walletManagers.map { walletManager -> async { globalState.tapWalletManager.loadWalletData(walletManager) } }.awaitAll() + handleBasicAnalyticsEvent() } else { val walletManager = walletState.getWalletManager(action.blockchain) ?: action.walletManager @@ -295,6 +300,7 @@ class WalletMiddleware { } is WalletAction.UserWalletChanged -> Unit is WalletAction.WalletStoresChanged -> { + store.dispatchOnMain(WalletAction.MultiWallet.ScheduleCheckForMissingDerivation) updateWalletStores(action.walletStores, walletState) fetchTotalFiatBalance(action.walletStores) findMissedDerivations(action.walletStores) @@ -489,4 +495,19 @@ class WalletMiddleware { } } } +} + +suspend fun handleBasicAnalyticsEvent() { + val scanResponse = store.state.globalState.scanResponse ?: return + + val biometricsWalletDataModels = if (preferencesStorage.shouldSaveUserWallets) { + UserWalletIdBuilder.scanResponse(scanResponse).build()?.let { userWalletId -> + walletStoresManager.getSync(userWalletId).map { it.walletsData }.flatten() + } + } else { + null + } + + val converterData = BasicEventsSourceData(scanResponse, store.state.walletState, biometricsWalletDataModels) + BasicEventsPreChecker().tryToSend(converterData) } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt index afb523a5ca..711373d52f 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/redux/reducers/MultiWalletReducer.kt @@ -185,7 +185,13 @@ class MultiWalletReducer { is WalletAction.MultiWallet.SetPrimaryToken -> state.copy(primaryToken = action.token) is WalletAction.MultiWallet.SaveCurrencies -> state is WalletAction.MultiWallet.ShowWalletBackupWarning -> state.copy(showBackupWarning = action.show) - is WalletAction.MultiWallet.AddMissingDerivations -> state.copy(missingDerivations = action.blockchains) + is WalletAction.MultiWallet.ScheduleCheckForMissingDerivation -> state.copy( + derivationsCheckIsScheduled = true, + ) + is WalletAction.MultiWallet.AddMissingDerivations -> state.copy( + missingDerivations = action.blockchains, + derivationsCheckIsScheduled = false + ) is WalletAction.MultiWallet.BackupWallet -> state is WalletAction.MultiWallet.ScanToGetDerivations -> state.copy(state = ProgressState.Loading) } diff --git a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt index 7c622df177..15eacf8c99 100644 --- a/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt +++ b/app/src/main/java/com/tangem/tap/features/wallet/ui/WalletFragment.kt @@ -17,13 +17,11 @@ import androidx.transition.TransitionInflater import by.kirich1409.viewbindingdelegate.viewBinding import coil.load import coil.size.Scale +import com.tangem.core.analytics.Analytics import com.tangem.core.ui.fragments.setStatusBarColor import com.tangem.core.ui.utils.OneTouchClickListener import com.tangem.domain.common.TapWorkarounds.isSaltPay import com.tangem.tap.MainActivity -import com.tangem.core.analytics.Analytics -import com.tangem.tap.common.analytics.converters.BasicSignInEventConverter -import com.tangem.tap.common.analytics.converters.BasicTopUpEventConverter import com.tangem.tap.common.analytics.events.MainScreen import com.tangem.tap.common.analytics.events.Portfolio import com.tangem.tap.common.extensions.show @@ -148,7 +146,6 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber Date: Wed, 25 Jan 2023 02:26:34 +0300 Subject: [PATCH 21/22] Updated on 2026-08-14 --- .../java/com/tangem/tap/common/analytics/events/SignIn.kt | 2 ++ .../tangem/tap/features/welcome/redux/WelcomeMiddleware.kt | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt b/app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt index 5b7fff71ea..cad34430d9 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/events/SignIn.kt @@ -12,6 +12,8 @@ sealed class SignIn( ) : AnalyticsEvent("Sign In", event, params, error) { class ScreenOpened : SignIn(event = "Sing In Screen Opened") + class CardWasScanned : SignIn(event = "Card Was Scanned") + class ButtonBiometricSignIn : SignIn(event = "Button - Biometric Sign In") class ButtonCardSignIn : SignIn(event = "Button - Card Sign In") } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt index 808f4ea74f..c1cdf0f74e 100644 --- a/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/welcome/redux/WelcomeMiddleware.kt @@ -4,7 +4,7 @@ import android.content.Intent import com.tangem.common.doOnFailure import com.tangem.common.doOnSuccess import com.tangem.domain.common.ScanResponse -import com.tangem.tap.common.analytics.events.IntroductionProcess +import com.tangem.tap.common.analytics.events.SignIn import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.onUserWalletSelected import com.tangem.tap.common.redux.AppState @@ -99,7 +99,7 @@ internal class WelcomeMiddleware { useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes, ) ScanCardProcessor.scan( - analyticsEvent = IntroductionProcess.CardWasScanned(), + analyticsEvent = SignIn.CardWasScanned(), onSuccess = { scanResponse -> scope.launch { onCardScanned(scanResponse) } }, From 2633d5f7138dc05e2f8e5dafda3694f696d66d8b Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 25 Jan 2023 02:35:37 +0300 Subject: [PATCH 22/22] Updated on 2026-08-14 --- .../features/walletSelector/redux/WalletSelectorMiddleware.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt index fcf97e11db..4405407dcd 100644 --- a/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt +++ b/app/src/main/java/com/tangem/tap/features/walletSelector/redux/WalletSelectorMiddleware.kt @@ -10,6 +10,7 @@ import com.tangem.core.analytics.Analytics import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.util.UserWalletId import com.tangem.tap.common.analytics.events.MyWallets +import com.tangem.tap.common.analytics.paramsInterceptor.BatchIdParamsInterceptor import com.tangem.tap.common.extensions.dispatchOnMain import com.tangem.tap.common.extensions.onUserWalletSelected import com.tangem.tap.common.redux.AppState @@ -198,6 +199,9 @@ internal class WalletSelectorMiddleware { .doOnSuccess { val selectedUserWallet = userWalletsListManager.selectedUserWalletSync if (selectedUserWallet != null) { + val batchId = selectedUserWallet.scanResponse.card.batchId + Analytics.addParamsInterceptor(BatchIdParamsInterceptor(batchId)) + store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet)) store.onUserWalletSelected(selectedUserWallet) }