Updated on 2026-08-14

This commit is contained in:
Tangem 2024-03-19 18:11:56 +00:00
commit b76e1bbc45
219 changed files with 4585 additions and 5271 deletions

View file

@ -84,6 +84,7 @@ internal class WalletDeepLinksHandler @Inject constructor(
amount = it.baseCurrencyAmount,
destinationAddress = it.depositWalletAddress,
transactionId = it.transactionId,
tag = it.depositWalletAddressTag,
)
}

View file

@ -23,7 +23,7 @@ sealed class WalletScreenAnalyticsEvent {
override val oneTimeEventId: String = id + userWalletId.stringValue
}
object WalletOpened : Basic(event = "Wallet Opened")
data object WalletOpened : Basic(event = "Wallet Opened")
class CardWasScanned(source: AnalyticsParam.ScannedFrom) : Basic(
event = "Card Was Scanned",
@ -53,8 +53,8 @@ sealed class WalletScreenAnalyticsEvent {
params: Map<String, String> = mapOf(),
) : AnalyticsEvent(category = "Main Screen", event = event, params = params) {
object ScreenOpened : MainScreen(event = "Screen opened")
object WalletSwipe : MainScreen(event = "Wallet Swipe")
data object ScreenOpened : MainScreen(event = "Screen opened")
data object WalletSwipe : MainScreen(event = "Wallet Swipe")
class EnableBiometrics(state: AnalyticsParam.OnOffState) : MainScreen(
event = "Enable Biometric",
@ -66,37 +66,39 @@ sealed class WalletScreenAnalyticsEvent {
params = mapOf("Result" to result.value),
)
object NoticeBackupYourWalletTapped : MainScreen(event = "Notice - Backup Your Wallet Tapped")
object NoticeScanYourCardTapped : MainScreen(event = "Notice - Scan Your Card Tapped")
object NoticeWalletLocked : MainScreen(event = "Notice - Wallet Locked")
object WalletUnlockTapped : MainScreen(event = "Notice - Wallet Unlock Tapped")
data object NoticeBackupYourWalletTapped : MainScreen(event = "Notice - Backup Your Wallet Tapped")
data object NoticeScanYourCardTapped : MainScreen(event = "Notice - Scan Your Card Tapped")
data object NoticeWalletLocked : MainScreen(event = "Notice - Wallet Locked")
data object WalletUnlockTapped : MainScreen(event = "Notice - Wallet Unlock Tapped")
object NetworksUnreachable : MainScreen(event = "Notice - Networks Unreachable")
data object NetworksUnreachable : MainScreen(event = "Notice - Networks Unreachable")
object MissingAddresses : MainScreen(event = "Notice - Missing Addresses")
data object MissingAddresses : MainScreen(event = "Notice - Missing Addresses")
object CardSignedTransactions : MainScreen(event = "Notice - Card Signed Transactions")
data object CardSignedTransactions : MainScreen(event = "Notice - Card Signed Transactions")
object HowDoYouLikeTangem : MainScreen(event = "Notice - How Do You Like Tangem")
data object HowDoYouLikeTangem : MainScreen(event = "Notice - How Do You Like Tangem")
object ProductSampleCard : MainScreen(event = "Notice - Product Sample Card")
data object ProductSampleCard : MainScreen(event = "Notice - Product Sample Card")
object TestnetCard : MainScreen(event = "Notice - Testnet Card")
data object TestnetCard : MainScreen(event = "Notice - Testnet Card")
object DemoCard : MainScreen(event = "Notice - Demo Card")
data object DemoCard : MainScreen(event = "Notice - Demo Card")
object DevelopmentCard : MainScreen(event = "Notice - Development Card")
data object DevelopmentCard : MainScreen(event = "Notice - Development Card")
object WalletUnlock : MainScreen(event = "Notice - Wallet Unlock")
data object WalletUnlock : MainScreen(event = "Notice - Wallet Unlock")
object BackupYourWallet : MainScreen(event = "Notice - Backup Your Wallet")
data object BackupYourWallet : MainScreen(event = "Notice - Backup Your Wallet")
object UnlockAllWithBiometrics : MainScreen(event = "Button - Unlock All With Biometrics")
data object BackupError : MainScreen(event = "Notice - Backup Error")
object UnlockWithCardScan : MainScreen(event = "Button - Unlock With Card Scan")
data object UnlockAllWithBiometrics : MainScreen(event = "Button - Unlock All With Biometrics")
object EditWalletTapped : MainScreen(event = "Button - Edit Wallet Tapped")
data object UnlockWithCardScan : MainScreen(event = "Button - Unlock With Card Scan")
object DeleteWalletTapped : MainScreen(event = "Button - Delete Wallet Tapped")
data object EditWalletTapped : MainScreen(event = "Button - Edit Wallet Tapped")
data object DeleteWalletTapped : MainScreen(event = "Button - Delete Wallet Tapped")
}
}

View file

@ -43,6 +43,7 @@ internal class WalletWarningsAnalyticsSender @Inject constructor(
is WalletNotification.Informational.DemoCard -> MainScreen.DemoCard
is WalletNotification.Informational.MissingAddresses -> MainScreen.MissingAddresses
is WalletNotification.RateApp -> MainScreen.HowDoYouLikeTangem
is WalletNotification.Critical.BackupError -> MainScreen.BackupError
is WalletNotification.UnlockWallets -> null // See [SelectedWalletAnalyticsSender]
is WalletNotification.Informational.NoAccount,
is WalletNotification.Warning.LowSignatures,

View file

@ -0,0 +1,42 @@
package com.tangem.feature.wallet.presentation.wallet.domain
import com.tangem.common.card.EllipticCurve
import com.tangem.domain.common.configs.CardConfig
import com.tangem.domain.models.scan.CardDTO
import javax.inject.Inject
class BackupValidator @Inject constructor() {
fun isValid(cardDTO: CardDTO): Boolean {
return validateBackupStatus(cardDTO) && validateCurves(cardDTO)
}
private fun validateCurves(cardDTO: CardDTO): Boolean {
val config = CardConfig.createConfig(cardDTO)
// / Since the curve `bls12381_G2_AUG` was added later into first generation of wallets,
// we cannot determine whether this curve is missing due to an error or because the user
// did not want to recreate the wallet.
val expectedCurves = config.mandatoryCurves
.filterNot { it == EllipticCurve.Bls12381G2Aug }
val curves = cardDTO.wallets.map { it.curve }
for (expectedCurve in expectedCurves) {
val cardCurvesCount = curves.count { it == expectedCurve }
// missing curve
if (cardCurvesCount == 0) {
return false
}
// duplicated curve
if (cardCurvesCount > 1) {
return false
}
}
return true
}
private fun validateBackupStatus(cardDTO: CardDTO): Boolean {
val backupStatus = cardDTO.backupStatus
return backupStatus != null && backupStatus !is CardDTO.BackupStatus.CardLinked
}
}

View file

@ -37,6 +37,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
private val shouldShowSwapPromoWalletUseCase: ShouldShowSwapPromoWalletUseCase,
private val promoRepository: PromoRepository,
private val isNeedToBackupUseCase: IsNeedToBackupUseCase,
private val backupValidator: BackupValidator,
) {
private var readyForRateAppNotification = false
@ -57,7 +58,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
buildList {
addSwapPromoNotification(shouldShowPromo, promoBanner, clickIntents)
addCriticalNotifications(cardTypesResolver)
addCriticalNotifications(userWallet)
addInformationalNotifications(cardTypesResolver, maybeTokenList, clickIntents)
@ -85,7 +86,13 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
)
}
private fun MutableList<WalletNotification>.addCriticalNotifications(cardTypesResolver: CardTypesResolver) {
private fun MutableList<WalletNotification>.addCriticalNotifications(userWallet: UserWallet) {
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
addIf(
element = WalletNotification.Critical.BackupError,
condition = !backupValidator.isValid(userWallet.scanResponse.card) || userWallet.hasBackupError,
)
addIf(
element = WalletNotification.Critical.DevCard,
condition = !cardTypesResolver.isReleaseFirmwareType(),

View file

@ -36,7 +36,10 @@ sealed class WalletBottomSheetConfig(
),
iconResId = R.drawable.ic_locked_24,
primaryButtonConfig = ButtonConfig(
text = resourceReference(id = R.string.user_wallet_list_unlock_all),
text = resourceReference(
id = R.string.user_wallet_list_unlock_all_with,
formatArgs = wrappedList(resourceReference(R.string.common_biometrics)),
),
onClick = onUnlockClick,
),
secondaryButtonConfig = ButtonConfig(

View file

@ -36,6 +36,11 @@ sealed class WalletNotification(val config: NotificationConfig) {
title = resourceReference(id = R.string.warning_failed_to_verify_card_title),
subtitle = resourceReference(id = R.string.warning_failed_to_verify_card_message),
)
data object BackupError : Critical(
title = resourceReference(R.string.warning_backup_errors_title),
subtitle = resourceReference(R.string.warning_backup_errors_message),
)
}
sealed class Warning(