Updated on 2026-08-14
This commit is contained in:
parent
5a8ebb312c
commit
047a48eaf0
12 changed files with 76 additions and 18 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
|
|
@ -129,12 +130,14 @@ internal object WalletsDomainModule {
|
|||
userWalletsListRepository: UserWalletsListRepository,
|
||||
hotWalletFeatureToggles: HotWalletFeatureToggles,
|
||||
walletsRepository: WalletsRepository,
|
||||
analyticsEventHandler: AnalyticsEventHandler,
|
||||
): SaveWalletUseCase {
|
||||
return SaveWalletUseCase(
|
||||
userWalletsListManager = userWalletsListManager,
|
||||
userWalletsListRepository = userWalletsListRepository,
|
||||
walletsRepository = walletsRepository,
|
||||
useNewRepository = hotWalletFeatureToggles.isHotWalletEnabled,
|
||||
analyticsEventHandler = analyticsEventHandler,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.tangem.domain.models.wallet.UserWallet
|
|||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.models.wallet.isLocked
|
||||
import com.tangem.domain.wallets.R
|
||||
import com.tangem.domain.wallets.analytics.WalletSettingsAnalyticEvents
|
||||
import com.tangem.domain.wallets.builder.UserWalletIdBuilder
|
||||
import com.tangem.domain.wallets.hot.HotWalletAccessCodeAttemptsRepository
|
||||
import com.tangem.domain.wallets.hot.HotWalletPasswordRequester
|
||||
|
|
@ -390,6 +391,7 @@ internal class DefaultUserWalletsListRepository(
|
|||
if (newUserWallet.walletId == oldUserWallet.walletId &&
|
||||
oldUserWallet is UserWallet.Hot && newUserWallet is UserWallet.Cold
|
||||
) {
|
||||
trackWalletUpgradeEvent()
|
||||
removeHotWalletsFromSDKAndRepos(walletIds = listOf(oldUserWallet.walletId))
|
||||
// When upgrading from Hot to Cold, if biometric lock is available, set it
|
||||
if (hasBiometry()) {
|
||||
|
|
@ -536,4 +538,8 @@ internal class DefaultUserWalletsListRepository(
|
|||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun trackWalletUpgradeEvent() {
|
||||
analyticsEventHandler.send(event = WalletSettingsAnalyticEvents.WalletUpgraded())
|
||||
}
|
||||
}
|
||||
|
|
@ -85,6 +85,7 @@ sealed class AnalyticsParam {
|
|||
data object ImportWallet : ScreensSources("Import Wallet")
|
||||
data object CreateWalletIntro : ScreensSources("Create Wallet Intro")
|
||||
data object AddNewWallet : ScreensSources("Add New Wallet")
|
||||
data object AddNew : ScreensSources("Add New")
|
||||
data object CreateWallet : ScreensSources("Create Wallet")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package com.tangem.domain.wallets.analytics
|
||||
|
||||
import com.tangem.core.analytics.models.AnalyticsEvent
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
import com.tangem.core.analytics.models.OneTimeAnalyticsEvent
|
||||
|
||||
sealed class Settings(
|
||||
category: String = "Settings",
|
||||
|
|
@ -9,4 +12,13 @@ sealed class Settings(
|
|||
) : AnalyticsEvent(category, event, params) {
|
||||
|
||||
class ButtonManageTokens : Settings(event = "Button - Manage Tokens")
|
||||
|
||||
class ColdWalletAdded(
|
||||
source: AnalyticsParam.ScreensSources?,
|
||||
) : Settings(
|
||||
event = "Cold Wallet Added",
|
||||
params = mapOf(AnalyticsParam.SOURCE to (source?.value ?: "Unknown")),
|
||||
), OneTimeAnalyticsEvent, AppsFlyerIncludedEvent {
|
||||
override val oneTimeEventId: String = id
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.tangem.core.analytics.models.AnalyticsEvent
|
|||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.ACTION
|
||||
import com.tangem.core.analytics.models.AnalyticsParam.Key.STATUS
|
||||
import com.tangem.core.analytics.models.AppsFlyerIncludedEvent
|
||||
|
||||
sealed class WalletSettingsAnalyticEvents(
|
||||
category: String = "Settings / Wallet Settings",
|
||||
|
|
@ -166,6 +167,10 @@ sealed class WalletSettingsAnalyticEvents(
|
|||
event = "Button - Start Upgrade",
|
||||
)
|
||||
|
||||
class WalletUpgraded : WalletSettingsAnalyticEvents(
|
||||
event = "Wallet Upgraded",
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
enum class RecoveryPhraseScreenAction(val value: String) {
|
||||
Upgrade("Upgrade"),
|
||||
Backup("Backup"),
|
||||
|
|
|
|||
|
|
@ -6,9 +6,12 @@ import arrow.core.raise.either
|
|||
import arrow.core.right
|
||||
import com.tangem.common.doOnFailure
|
||||
import com.tangem.common.doOnSuccess
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.domain.common.wallets.UserWalletsListRepository
|
||||
import com.tangem.domain.common.wallets.error.SaveWalletError
|
||||
import com.tangem.domain.models.wallet.UserWallet
|
||||
import com.tangem.domain.wallets.analytics.Settings
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListError
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
|
|
@ -16,8 +19,6 @@ import com.tangem.domain.wallets.repository.WalletsRepository
|
|||
/**
|
||||
* Use case for saving user wallet
|
||||
*
|
||||
* @property userWalletsListManager user wallets list manager
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class SaveWalletUseCase(
|
||||
|
|
@ -25,14 +26,21 @@ class SaveWalletUseCase(
|
|||
private val userWalletsListRepository: UserWalletsListRepository,
|
||||
private val walletsRepository: WalletsRepository,
|
||||
private val useNewRepository: Boolean,
|
||||
private val analyticsEventHandler: AnalyticsEventHandler,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(userWallet: UserWallet, canOverride: Boolean = false): Either<SaveWalletError, Unit> {
|
||||
suspend operator fun invoke(
|
||||
userWallet: UserWallet,
|
||||
canOverride: Boolean = false,
|
||||
analyticsSource: AnalyticsParam.ScreensSources? = null,
|
||||
): Either<SaveWalletError, Unit> {
|
||||
return if (useNewRepository) {
|
||||
either {
|
||||
val newUserWallet =
|
||||
userWalletsListRepository.userWalletsSync().none { it.walletId == userWallet.walletId }
|
||||
val userWallet = userWalletsListRepository.saveWithoutLock(userWallet, canOverride).bind()
|
||||
val userWallet = userWalletsListRepository.saveWithoutLock(userWallet, canOverride)
|
||||
.onRight { trackColdWalletAddedIfNeeded(analyticsSource, it) }
|
||||
.bind()
|
||||
|
||||
if (newUserWallet) {
|
||||
when (userWallet) {
|
||||
|
|
@ -76,4 +84,11 @@ class SaveWalletUseCase(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun trackColdWalletAddedIfNeeded(source: AnalyticsParam.ScreensSources?, userWallet: UserWallet) {
|
||||
val hasHotWallet = userWalletsListRepository.userWalletsSync().any { it is UserWallet.Hot }
|
||||
if (hasHotWallet && userWallet is UserWallet.Cold) {
|
||||
analyticsEventHandler.send(event = Settings.ColdWalletAdded(source))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -75,7 +75,12 @@ internal class UserWalletSaver @Inject constructor(
|
|||
|
||||
private suspend fun Raise<Error>.saveWallet(userWallet: UserWallet) {
|
||||
fold(
|
||||
block = { saveWalletUseCase(userWallet).bind() },
|
||||
block = {
|
||||
saveWalletUseCase(
|
||||
userWallet = userWallet,
|
||||
analyticsSource = AnalyticsParam.ScreensSources.Settings,
|
||||
).bind()
|
||||
},
|
||||
recover = { error ->
|
||||
when (error) {
|
||||
is SaveWalletError.WalletAlreadySaved -> {
|
||||
|
|
|
|||
|
|
@ -133,7 +133,10 @@ internal class CreateHardwareWalletModel @Inject constructor(
|
|||
return
|
||||
}
|
||||
|
||||
saveWalletUseCase(userWallet = userWallet).fold(
|
||||
saveWalletUseCase(
|
||||
userWallet = userWallet,
|
||||
analyticsSource = AnalyticsParam.ScreensSources.AddNew,
|
||||
).fold(
|
||||
ifLeft = { saveWalletError ->
|
||||
delay(HIDE_PROGRESS_DELAY)
|
||||
setLoading(false)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import arrow.core.getOrElse
|
|||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.extensions.ByteArrayKey
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
|
|
@ -267,6 +268,7 @@ internal class MultiWalletFinalizeModel @Inject constructor(
|
|||
scanResponse = scanResponse.updateScanResponseAfterBackup(),
|
||||
),
|
||||
canOverride = true,
|
||||
analyticsSource = AnalyticsParam.ScreensSources.Onboarding,
|
||||
)
|
||||
userWalletCreated
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import androidx.compose.runtime.Stable
|
|||
import arrow.core.getOrElse
|
||||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
|
|
@ -173,7 +174,10 @@ internal class OnboardingVisaInProgressModel @Inject constructor(
|
|||
}
|
||||
|
||||
val userWallet = createUserWallet(params.scanResponse, newTokens)
|
||||
saveWalletUseCase(userWallet)
|
||||
saveWalletUseCase(
|
||||
userWallet = userWallet,
|
||||
analyticsSource = AnalyticsParam.ScreensSources.Onboarding,
|
||||
)
|
||||
visaAuthTokenStorage.remove(params.scanResponse.card.cardId)
|
||||
otpStorage.removeOTP(params.scanResponse.card.cardId)
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ sealed class WalletScreenAnalyticsEvent {
|
|||
}
|
||||
put("Wallet Type", seedPhrase)
|
||||
},
|
||||
)
|
||||
), AppsFlyerIncludedEvent
|
||||
|
||||
data class NoticeFinishActivation(
|
||||
private val activationState: ActivationState,
|
||||
|
|
|
|||
|
|
@ -197,18 +197,20 @@ internal class WelcomeModel @Inject constructor(
|
|||
onSuccess = { scanResponse ->
|
||||
val userWallet =
|
||||
coldUserWalletBuilderFactory.create(scanResponse = scanResponse).build() ?: return@scan
|
||||
saveWalletUseCase.invoke(userWallet)
|
||||
.onLeft { error ->
|
||||
if (error is SaveWalletError.WalletAlreadySaved) {
|
||||
userWalletsListRepository.unlock(
|
||||
userWallet.walletId,
|
||||
unlockMethod = UserWalletsListRepository.UnlockMethod.Scan(scanResponse),
|
||||
).onRight {
|
||||
userWalletsListRepository.select(userWallet.walletId)
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
saveWalletUseCase.invoke(
|
||||
userWallet = userWallet,
|
||||
analyticsSource = AnalyticsParam.ScreensSources.SignIn,
|
||||
).onLeft { error ->
|
||||
if (error is SaveWalletError.WalletAlreadySaved) {
|
||||
userWalletsListRepository.unlock(
|
||||
userWallet.walletId,
|
||||
unlockMethod = UserWalletsListRepository.UnlockMethod.Scan(scanResponse),
|
||||
).onRight {
|
||||
userWalletsListRepository.select(userWallet.walletId)
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
}
|
||||
}
|
||||
.onRight {
|
||||
router.replaceAll(AppRoute.Wallet)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue