From 8d16f06c0890210e60bdb2e778cc8e871d5c765f Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 7 Mar 2024 18:43:13 +0000 Subject: [PATCH] Updated on 2026-08-14 --- .../model/UserWalletInformation.kt | 1 + .../tap/domain/userWalletList/utils/Mapper.kt | 2 + .../features/onboarding/OnboardingHelper.kt | 16 ++++-- .../wallet/redux/OnboardingWalletAction.kt | 49 ++++++++++--------- .../redux/OnboardingWalletMiddleware.kt | 6 +++ .../wallet/redux/OnboardingWalletReducer.kt | 1 + .../wallet/redux/OnboardingWalletState.kt | 1 + .../card/DefaultDerivationsRepositoryTest.kt | 1 + .../domain/userwallets/UserWalletBuilder.kt | 9 ++++ .../com/tangem/domain/models/scan/CardDTO.kt | 2 +- .../domain/wallets/models/UserWallet.kt | 1 + .../analytics/WalletScreenAnalyticsEvent.kt | 44 +++++++++-------- .../utils/WalletWarningsAnalyticsSender.kt | 1 + .../wallet/domain/BackupValidator.kt | 42 ++++++++++++++++ .../domain/GetMultiWalletWarningsFactory.kt | 12 ++++- .../wallet/state/model/WalletNotification.kt | 9 +++- 16 files changed, 142 insertions(+), 55 deletions(-) create mode 100644 features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/BackupValidator.kt diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletInformation.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletInformation.kt index fe064832d6..8a3f2fe559 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletInformation.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/model/UserWalletInformation.kt @@ -18,4 +18,5 @@ internal data class UserWalletPublicInformation( val cardsInWallet: Set, val scanResponse: ScanResponse, val isMultiCurrency: Boolean, + val hasBackupError: Boolean = false, ) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt index 4116cde096..451e717e9e 100644 --- a/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt +++ b/app/src/main/java/com/tangem/tap/domain/userWalletList/utils/Mapper.kt @@ -20,6 +20,7 @@ internal val UserWallet.publicInformation: UserWalletPublicInformation wallets = emptyList(), ), ), + hasBackupError = hasBackupError, ) internal fun UserWalletPublicInformation.toUserWallet(): UserWallet { @@ -30,6 +31,7 @@ internal fun UserWalletPublicInformation.toUserWallet(): UserWallet { cardsInWallet = cardsInWallet, scanResponse = scanResponse, isMultiCurrency = isMultiCurrency, + hasBackupError = hasBackupError, ) } diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt index fd59efff07..dee9d0f733 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/OnboardingHelper.kt @@ -72,13 +72,14 @@ object OnboardingHelper { scanResponse: ScanResponse, accessCode: String? = null, backupCardsIds: List? = null, + hasBackupError: Boolean = false, ) { Analytics.setContext(scanResponse) scope.launch { when { // When should save user wallets, then save card without navigate to save wallet screen store.inject(DaggerGraphState::walletsRepository).shouldSaveUserWalletsSync() -> { - proceedWithScanResponse(scanResponse, backupCardsIds) + proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError) store.dispatchOnMain( SaveWalletAction.ProvideBackupInfo( @@ -92,7 +93,7 @@ object OnboardingHelper { // When should not save user wallets but device has biometry and save wallet screen has not been shown, // then open save wallet screen tangemSdkManager.canUseBiometry && preferencesStorage.shouldShowSaveUserWalletScreen -> { - proceedWithScanResponse(scanResponse, backupCardsIds) + proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError) delay(timeMillis = 1_200) @@ -109,7 +110,7 @@ object OnboardingHelper { } // If device has no biometry and save wallet screen has been shown, then go through old scenario else -> { - proceedWithScanResponse(scanResponse, backupCardsIds) + proceedWithScanResponse(scanResponse, backupCardsIds, hasBackupError) store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Wallet)) } } @@ -129,8 +130,13 @@ object OnboardingHelper { } } - private suspend fun proceedWithScanResponse(scanResponse: ScanResponse, backupCardsIds: List?) { - val userWallet = UserWalletBuilder(scanResponse) + private suspend fun proceedWithScanResponse( + scanResponse: ScanResponse, + backupCardsIds: List?, + hasBackupError: Boolean, + ) { + val userWallet = UserWalletBuilder(scanResponse = scanResponse) + .hasBackupError(hasBackupError) .backupCardsIds(backupCardsIds?.toSet()) .build() .guard { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt index 6b536fc754..5bd2df0285 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletAction.kt @@ -9,23 +9,23 @@ import kotlinx.coroutines.CoroutineScope import org.rekotlin.Action sealed class OnboardingWalletAction : Action { - object Init : OnboardingWalletAction() - object GetToCreateWalletStep : OnboardingWalletAction() - object CreateWallet : OnboardingWalletAction() + data object Init : OnboardingWalletAction() + data object GetToCreateWalletStep : OnboardingWalletAction() + data object CreateWallet : OnboardingWalletAction() data class WalletWasCreated( val shouldSendAnalyticsEvent: Boolean, val result: CompletionResult, ) : OnboardingWalletAction() - object Done : OnboardingWalletAction() + data object Done : OnboardingWalletAction() data class FinishOnboarding(val scope: CoroutineScope) : OnboardingWalletAction() - object ResumeBackup : OnboardingWalletAction() + data object ResumeBackup : OnboardingWalletAction() data class LoadArtwork(val cardArtworkUriForUnfinishedBackup: Uri? = null) : OnboardingWalletAction() class SetArtworkUrl(val artworkUri: Uri?) : OnboardingWalletAction() - object OnBackPressed : OnboardingWalletAction() + data object OnBackPressed : OnboardingWalletAction() } sealed class OnboardingWallet2Action : OnboardingWalletAction() { @@ -49,45 +49,46 @@ sealed class OnboardingWallet2Action : OnboardingWalletAction() { sealed class BackupAction : Action { - object IntroduceBackup : BackupAction() - object StartBackup : BackupAction() - object SkipBackup : BackupAction() + data object IntroduceBackup : BackupAction() + data object StartBackup : BackupAction() + data object SkipBackup : BackupAction() - object StartAddingPrimaryCard : BackupAction() - object ScanPrimaryCard : BackupAction() + data object ErrorInBackupCard : BackupAction() + data object StartAddingPrimaryCard : BackupAction() + data object ScanPrimaryCard : BackupAction() /** * Check for unfinished backup of standard Wallets * See more GlobalAction.Onboarding.StartForUnfinishedBackup */ - object CheckForUnfinishedBackup : BackupAction() + data object CheckForUnfinishedBackup : BackupAction() - object StartAddingBackupCards : BackupAction() - object AddBackupCard : BackupAction() { - object Success : BackupAction() + data object StartAddingBackupCards : BackupAction() + data object AddBackupCard : BackupAction() { + data object Success : BackupAction() data class ChangeButtonLoading(val isLoading: Boolean) : BackupAction() } - object FinishAddingBackupCards : BackupAction() + data object FinishAddingBackupCards : BackupAction() - object ShowAccessCodeInfoScreen : BackupAction() - object ShowEnterAccessCodeScreen : BackupAction() + data object ShowAccessCodeInfoScreen : BackupAction() + data object ShowEnterAccessCodeScreen : BackupAction() data class CheckAccessCode(val accessCode: String) : BackupAction() data class SetAccessCodeError(val error: AccessCodeError?) : BackupAction() data class SaveFirstAccessCode(val accessCode: String) : BackupAction() data class SaveAccessCodeConfirmation(val accessCodeConfirmation: String) : BackupAction() - object OnAccessCodeDialogClosed : BackupAction() + data object OnAccessCodeDialogClosed : BackupAction() - object PrepareToWritePrimaryCard : BackupAction() - object WritePrimaryCard : BackupAction() + data object PrepareToWritePrimaryCard : BackupAction() + data object WritePrimaryCard : BackupAction() data class PrepareToWriteBackupCard(val cardNumber: Int) : BackupAction() data class WriteBackupCard(val cardNumber: Int) : BackupAction() data class FinishBackup(val withAnalytics: Boolean = true) : BackupAction() - object DiscardBackup : BackupAction() - object DiscardSavedBackup : BackupAction() - object ResumeFoundUnfinishedBackup : BackupAction() + data object DiscardBackup : BackupAction() + data object DiscardSavedBackup : BackupAction() + data object ResumeFoundUnfinishedBackup : BackupAction() data class ResetBackupCard(val cardId: String) : BackupAction() } \ No newline at end of file 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 460734903f..16045b38c8 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 @@ -20,6 +20,7 @@ import com.tangem.domain.userwallets.Artwork import com.tangem.domain.userwallets.UserWalletBuilder import com.tangem.feature.onboarding.data.model.CreateWalletResponse import com.tangem.feature.onboarding.presentation.wallet2.analytics.SeedPhraseSource +import com.tangem.feature.wallet.presentation.wallet.domain.BackupValidator import com.tangem.operations.attestation.OnlineCardVerifier import com.tangem.operations.backup.BackupService import com.tangem.tap.* @@ -173,6 +174,7 @@ private fun handleWalletAction(action: Action) { scanResponse = updatedScanResponse, accessCode = backupState.accessCode, backupCardsIds = backupState.backupCardIds, + hasBackupError = backupState.hasBackupError, ) } } @@ -484,6 +486,10 @@ private fun handleBackupAction(appState: () -> AppState?, action: BackupAction) backupService.proceedBackup { result -> when (result) { is CompletionResult.Success -> { + val backupValidator = BackupValidator() + if (!backupValidator.isValid(CardDTO(result.data))) { + store.dispatchOnMain(BackupAction.ErrorInBackupCard) + } if (backupService.currentState == BackupService.State.Finished) { store.dispatchOnMain(BackupAction.FinishBackup()) } else { diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt index 61bee3be0f..1a400ea778 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletReducer.kt @@ -112,6 +112,7 @@ private object BackupReducer { } else { state.copy(backupStep = BackupStep.WriteBackupCard(action.cardNumber)) } + is BackupAction.ErrorInBackupCard -> state.copy(hasBackupError = true) is BackupAction.SkipBackup -> state.copy(backupStep = BackupStep.Finished) is BackupAction.FinishBackup -> state.copy(backupStep = BackupStep.Finished) BackupAction.OnAccessCodeDialogClosed -> state.copy(backupStep = BackupStep.AddBackupCards) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt index 0920fb4a9b..64b81fc771 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/redux/OnboardingWalletState.kt @@ -70,6 +70,7 @@ data class BackupState( val canSkipBackup: Boolean = true, val isInterruptedBackup: Boolean = false, val showBtnLoading: Boolean = false, + val hasBackupError: Boolean = false, ) enum class AccessCodeError { diff --git a/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt b/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt index 730ddb8d96..b1e1189c8e 100644 --- a/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt +++ b/app/src/test/kotlin/com/tangem/tap/domain/card/DefaultDerivationsRepositoryTest.kt @@ -37,6 +37,7 @@ internal class DefaultDerivationsRepositoryTest { cardsInWallet = setOf(), isMultiCurrency = false, scanResponse = ScanResponseMockFactory.create(cardConfig = GenericCardConfig(2), derivedKeys = emptyMap()), + hasBackupError = false, ) @Test diff --git a/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletBuilder.kt b/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletBuilder.kt index 182653ef00..325fb2efa7 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletBuilder.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/userwallets/UserWalletBuilder.kt @@ -11,6 +11,7 @@ class UserWalletBuilder( private val getCardImageUseCase: GetCardImageUseCase = GetCardImageUseCase(), ) { private var backupCardsIds: Set = emptySet() + private var hasBackupError: Boolean = false private val CardDTO.isBackupNotAllowed: Boolean get() = !this.settings.isBackupAllowed @@ -41,6 +42,13 @@ class UserWalletBuilder( } } + /** + * Sets if UserWallet has any backup errors (wrong curves etc). Use in onboarding + */ + fun hasBackupError(hasBackupError: Boolean) = this.apply { + this.hasBackupError = hasBackupError + } + suspend fun build(): UserWallet? { return with(scanResponse) { UserWalletIdBuilder.scanResponse(scanResponse) @@ -53,6 +61,7 @@ class UserWalletBuilder( cardsInWallet = backupCardsIds.plus(card.cardId), scanResponse = this, isMultiCurrency = cardTypesResolver.isMultiwalletAllowed(), + hasBackupError = hasBackupError, ) } } diff --git a/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt b/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt index 8863fe8a03..ff2b5be1d0 100644 --- a/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt +++ b/domain/models/src/main/kotlin/com/tangem/domain/models/scan/CardDTO.kt @@ -303,7 +303,7 @@ data class CardDTO( data class Active(val cardCount: Int) : BackupStatus() - object NoBackup : BackupStatus() + data object NoBackup : BackupStatus() val isActive: Boolean get() = this is Active diff --git a/domain/wallets/models/src/main/java/com/tangem/domain/wallets/models/UserWallet.kt b/domain/wallets/models/src/main/java/com/tangem/domain/wallets/models/UserWallet.kt index 710566e799..4904076698 100644 --- a/domain/wallets/models/src/main/java/com/tangem/domain/wallets/models/UserWallet.kt +++ b/domain/wallets/models/src/main/java/com/tangem/domain/wallets/models/UserWallet.kt @@ -20,6 +20,7 @@ data class UserWallet( val artworkUrl: String, val cardsInWallet: Set, val isMultiCurrency: Boolean, + val hasBackupError: Boolean, val scanResponse: ScanResponse, // TODO: Replace with [com.tangem.domain.models.scan.CardDTO] ) { diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt index 2717ca2dfa..0b2b604294 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/WalletScreenAnalyticsEvent.kt @@ -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", @@ -45,8 +45,8 @@ sealed class WalletScreenAnalyticsEvent { params: Map = 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", @@ -58,37 +58,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") } } \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt index 899dd5a09a..e80fc87a24 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/analytics/utils/WalletWarningsAnalyticsSender.kt @@ -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, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/BackupValidator.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/BackupValidator.kt new file mode 100644 index 0000000000..caa4c9fd87 --- /dev/null +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/BackupValidator.kt @@ -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 + } +} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt index 7de96e0c75..9fceb87f55 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetMultiWalletWarningsFactory.kt @@ -14,6 +14,7 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.tokens.model.NetworkGroup import com.tangem.domain.tokens.model.TokenList import com.tangem.domain.tokens.repository.PromoRepository +import com.tangem.domain.wallets.models.UserWallet import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification @@ -36,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 @@ -64,7 +66,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( buildList { addSwapPromoNotification(shouldShowPromo, promoBanner, clickIntents) - addCriticalNotifications(cardTypesResolver) + addCriticalNotifications(userWallet) addInformationalNotifications(cardTypesResolver, maybeTokenList, clickIntents) @@ -92,7 +94,13 @@ internal class GetMultiWalletWarningsFactory @Inject constructor( ) } - private fun MutableList.addCriticalNotifications(cardTypesResolver: CardTypesResolver) { + private fun MutableList.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(), diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt index e7c5e885c4..da66d2d54c 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/state/model/WalletNotification.kt @@ -27,15 +27,20 @@ sealed class WalletNotification(val config: NotificationConfig) { ), ) { - object DevCard : Critical( + data object DevCard : Critical( title = resourceReference(id = R.string.warning_developer_card_title), subtitle = resourceReference(id = R.string.warning_developer_card_message), ) - object FailedCardValidation : Critical( + data object FailedCardValidation : Critical( 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(