From 15d8fde8ad89cf08ac937c2166b3df5edb707b2c Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 18 Jun 2026 21:51:32 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tangem/tap/di/domain/CardDomainModule.kt | 12 -- features/tokendetails/impl/build.gradle.kts | 1 - .../domain/GetWalletCardWarningsUseCase.kt | 77 -------- .../tokendetails/domain/WalletCardWarning.kt | 24 --- .../model/TokenDetailsClickIntents.kt | 12 -- .../tokendetails/model/TokenDetailsModel.kt | 48 +---- .../UpdateWalletCardWarningsTransformer.kt | 131 -------------- .../GetWalletCardWarningsUseCaseTest.kt | 169 ------------------ .../domain/GetSingleWalletWarningsFactory.kt | 1 - .../domain/GetWalletNotificationsFactory.kt | 1 - .../HasSingleWalletSignedHashesUseCase.kt | 14 +- 11 files changed, 11 insertions(+), 479 deletions(-) delete mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/domain/GetWalletCardWarningsUseCase.kt delete mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/domain/WalletCardWarning.kt delete mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/transformer/UpdateWalletCardWarningsTransformer.kt delete mode 100644 features/tokendetails/impl/src/test/kotlin/com/tangem/feature/tokendetails/domain/GetWalletCardWarningsUseCaseTest.kt rename {domain/wallets/src/main/java/com/tangem/domain/wallets/usecase => features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain}/HasSingleWalletSignedHashesUseCase.kt (86%) diff --git a/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt index 9477d6c380..cef5171d26 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/CardDomainModule.kt @@ -55,18 +55,6 @@ internal object CardDomainModule { return IsNeedToBackupUseCase(userWalletsListRepository = userWalletsListRepository) } - @Provides - @Singleton - fun provideHasSingleWalletSignedHashesUseCase( - cardRepository: CardRepository, - walletManagersFacade: WalletManagersFacade, - ): HasSingleWalletSignedHashesUseCase { - return HasSingleWalletSignedHashesUseCase( - cardRepository = cardRepository, - walletManagersFacade = walletManagersFacade, - ) - } - @Provides @Singleton fun provideGetExtendedPublicKeyForCurrencyUseCase( diff --git a/features/tokendetails/impl/build.gradle.kts b/features/tokendetails/impl/build.gradle.kts index 6a8211f32c..a2bcd8d884 100644 --- a/features/tokendetails/impl/build.gradle.kts +++ b/features/tokendetails/impl/build.gradle.kts @@ -69,7 +69,6 @@ dependencies { implementation(projects.domain.dynamicAddresses) implementation(projects.domain.dynamicAddresses.models) implementation(projects.domain.feedback) - implementation(projects.domain.feedback.models) implementation(projects.domain.markets.models) implementation(projects.domain.models) implementation(projects.domain.notifications.models) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/domain/GetWalletCardWarningsUseCase.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/domain/GetWalletCardWarningsUseCase.kt deleted file mode 100644 index 97f5e2c457..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/domain/GetWalletCardWarningsUseCase.kt +++ /dev/null @@ -1,77 +0,0 @@ -package com.tangem.feature.tokendetails.domain - -import com.tangem.domain.card.IsWalletBackupProblematicUseCase -import com.tangem.domain.card.common.util.cardTypesResolver -import com.tangem.domain.demo.IsDemoCardUseCase -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.wallets.usecase.HasSingleWalletSignedHashesUseCase -import com.tangem.utils.coroutines.CoroutineDispatcherProvider -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.map -import javax.inject.Inject - -/** - * Produces card/wallet-level warnings for the Token Details screen. - * - * These banners mirror the ones the main screen shows via `GetWalletNotificationsFactory`, but they only apply to - * a single-currency cold wallet (a multi-currency wallet keeps them on the main screen only). - */ -internal class GetWalletCardWarningsUseCase @Inject constructor( - private val isDemoCardUseCase: IsDemoCardUseCase, - private val hasSingleWalletSignedHashesUseCase: HasSingleWalletSignedHashesUseCase, - private val isWalletBackupProblematicUseCase: IsWalletBackupProblematicUseCase, - private val dispatchers: CoroutineDispatcherProvider, -) { - - operator fun invoke(userWallet: UserWallet, network: Network): Flow> { - if (userWallet !is UserWallet.Cold || userWallet.isMultiCurrency) { - return flowOf(emptySet()) - } - - return hasSingleWalletSignedHashesUseCase(userWallet, network) - .map { hasIncorrectSignedHashes -> - buildWarnings( - userWallet = userWallet, - hasIncorrectSignedHashes = hasIncorrectSignedHashes, - ) - } - .flowOn(dispatchers.io) - } - - private fun buildWarnings(userWallet: UserWallet.Cold, hasIncorrectSignedHashes: Boolean): Set { - val cardTypesResolver = userWallet.cardTypesResolver - - return buildSet { - if (isWalletBackupProblematicUseCase(userWallet)) { - add(WalletCardWarning.BackupError) - } - if (!cardTypesResolver.isReleaseFirmwareType()) { - add(WalletCardWarning.DevCard) - } - if (cardTypesResolver.isReleaseFirmwareType() && cardTypesResolver.isAttestationFailed()) { - add(WalletCardWarning.FailedCardValidation) - } - cardTypesResolver.getRemainingSignatures()?.let { remainingSignatures -> - if (remainingSignatures <= MAX_REMAINING_SIGNATURES_COUNT) { - add(WalletCardWarning.LowSignatures(count = remainingSignatures)) - } - } - if (isDemoCardUseCase(cardId = cardTypesResolver.getCardId())) { - add(WalletCardWarning.DemoCard) - } - if (cardTypesResolver.isTestCard()) { - add(WalletCardWarning.TestnetCard) - } - if (hasIncorrectSignedHashes) { - add(WalletCardWarning.NumberOfSignedHashesIncorrect) - } - } - } - - private companion object { - const val MAX_REMAINING_SIGNATURES_COUNT = 10 - } -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/domain/WalletCardWarning.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/domain/WalletCardWarning.kt deleted file mode 100644 index afc9f50393..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/domain/WalletCardWarning.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.tangem.feature.tokendetails.domain - -/** - * Card/wallet-level warnings that are shown on the main screen for a single-currency wallet and must also be - * displayed in Token Details (redesign), since single-currency wallets now have a Token Details screen. - * - * Currency-level warnings are produced separately by [GetCurrencyWarningsUseCase]. - */ -internal sealed interface WalletCardWarning { - - data object BackupError : WalletCardWarning - - data object DevCard : WalletCardWarning - - data object FailedCardValidation : WalletCardWarning - - data object TestnetCard : WalletCardWarning - - data class LowSignatures(val count: Int) : WalletCardWarning - - data object NumberOfSignedHashesIncorrect : WalletCardWarning - - data object DemoCard : WalletCardWarning -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt index 319472b5ea..fff85000be 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsClickIntents.kt @@ -78,14 +78,6 @@ interface TokenDetailsClickIntents { fun onYieldInfoClick() - // region Wallet card warnings - - fun onSupportClick() - - fun onCloseSignedHashesWarning() - - // endregion Wallet card warnings - // region Clore migration // TODO: Remove after 2025-04-01 when Clore migration ends ([REDACTED_TASK_KEY]) @@ -169,10 +161,6 @@ internal class EmptyTokenDetailsClickIntents : TokenDetailsClickIntents { override fun onCloseRentInfoNotification() { /* no op */ } - override fun onSupportClick() { /* no op */ } - - override fun onCloseSignedHashesWarning() { /* no op */ } - override fun onRetryIncompleteTransactionClick() { /* no op */ } override fun onOpenTrustlineClick() { /* no op */ } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt index 8c9f7b835c..d86bc04a23 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/model/TokenDetailsModel.kt @@ -63,10 +63,6 @@ import com.tangem.domain.models.account.Account import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.network.NetworkAddress -import com.tangem.domain.card.SetCardWasScannedUseCase -import com.tangem.domain.feedback.GetWalletMetaInfoUseCase -import com.tangem.domain.feedback.SendFeedbackEmailUseCase -import com.tangem.domain.feedback.models.FeedbackEmailType import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.UserWalletId import com.tangem.domain.offramp.GetOfframpUrlUseCase @@ -102,7 +98,6 @@ import com.tangem.domain.yield.supply.models.YieldSupplyRewardBalance import com.tangem.domain.yield.supply.usecase.YieldSupplyGetRewardsBalanceUseCase import com.tangem.feature.tokendetails.deeplink.TokenDetailsDeepLinkActionListener import com.tangem.feature.tokendetails.domain.GetCurrencyWarningsUseCase -import com.tangem.feature.tokendetails.domain.GetWalletCardWarningsUseCase import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter import com.tangem.feature.tokendetails.presentation.tokendetails.analytics.TokenDetailsCurrencyStatusAnalyticsSender import com.tangem.feature.tokendetails.presentation.tokendetails.analytics.TokenDetailsNotificationsAnalyticsSender @@ -128,7 +123,6 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.transform import com.tangem.feature.tokendetails.presentation.tokendetails.state.transformer.ToggleBalanceTypeTransformer import com.tangem.feature.tokendetails.presentation.tokendetails.state.transformer.UpdateStakingNotificationTransformer import com.tangem.feature.tokendetails.presentation.tokendetails.state.transformer.UpdateNotificationsTransformer -import com.tangem.feature.tokendetails.presentation.tokendetails.state.transformer.UpdateWalletCardWarningsTransformer import com.tangem.feature.tokendetails.presentation.tokendetails.state.transformer.UpdateTopBarMenuTransformer import com.tangem.features.tokendetails.ExpressTransactionsEvent import com.tangem.features.tokendetails.ExpressTransactionsEventListener @@ -161,10 +155,6 @@ internal class TokenDetailsModel @Inject constructor( private val isCryptoCurrencyCouldHideUseCase: IsCryptoCurrencyCouldHideUseCase, private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase, private val getCurrencyWarningsUseCase: GetCurrencyWarningsUseCase, - private val getWalletCardWarningsUseCase: GetWalletCardWarningsUseCase, - private val setCardWasScannedUseCase: SetCardWasScannedUseCase, - private val getWalletMetaInfoUseCase: GetWalletMetaInfoUseCase, - private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase, private val getExplorerTransactionUrlUseCase: GetExplorerTransactionUrlUseCase, private val getExtendedPublicKeyForCurrencyUseCase: GetExtendedPublicKeyForCurrencyUseCase, private val getStakingEntryInfoUseCase: GetStakingEntryInfoUseCase, @@ -433,20 +423,13 @@ internal class TokenDetailsModel @Inject constructor( private fun updateWarnings(cryptoCurrencyStatus: CryptoCurrencyStatus) { modelScope.launch(dispatchers.main) { - combine( - flow = getCurrencyWarningsUseCase( - userWalletId = userWalletId, - currencyStatus = cryptoCurrencyStatus, - derivationPath = cryptoCurrency.network.derivationPath, - ), - flow2 = getWalletCardWarningsUseCase( - userWallet = userWallet, - network = cryptoCurrency.network, - ), - transform = ::Pair, + getCurrencyWarningsUseCase( + userWalletId = userWalletId, + currencyStatus = cryptoCurrencyStatus, + derivationPath = cryptoCurrency.network.derivationPath, ) .distinctUntilChanged() - .onEach { (warnings, cardWarnings) -> + .onEach { warnings -> val updatedState = stateFactory.getStateWithNotifications(warnings) notificationsAnalyticsSender.send(uiState.value, updatedState.notifications) uiState.value = updatedState @@ -457,12 +440,6 @@ internal class TokenDetailsModel @Inject constructor( clickIntents = this@TokenDetailsModel, ), ) - redesignStateController.update( - UpdateWalletCardWarningsTransformer( - walletCardWarnings = cardWarnings, - clickIntents = this@TokenDetailsModel, - ), - ) } .launchIn(modelScope) .saveIn(warningsJobHolder) @@ -1032,21 +1009,6 @@ internal class TokenDetailsModel @Inject constructor( uiState.value = stateFactory.getStateWithRemovedRentNotification() } - override fun onSupportClick() { - modelScope.launch { - val metaInfo = getWalletMetaInfoUseCase(userWalletId).getOrNull() ?: return@launch - sendFeedbackEmailUseCase(type = FeedbackEmailType.DirectUserRequest(walletMetaInfo = metaInfo)) - } - } - - override fun onCloseSignedHashesWarning() { - modelScope.launch { - (userWallet as? UserWallet.Cold)?.let { coldWallet -> - setCardWasScannedUseCase(cardId = coldWallet.cardId) - } - } - } - override fun onCopyAddress(): TextReference? { val networkAddress = cryptoCurrencyStatus?.value?.networkAddress ?: return null val addresses = networkAddress.availableAddresses.mapToAddressModels(cryptoCurrency).toImmutableList() diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/transformer/UpdateWalletCardWarningsTransformer.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/transformer/UpdateWalletCardWarningsTransformer.kt deleted file mode 100644 index 2f3bc9bc7e..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/transformer/UpdateWalletCardWarningsTransformer.kt +++ /dev/null @@ -1,131 +0,0 @@ -package com.tangem.feature.tokendetails.presentation.tokendetails.state.transformer - -import com.tangem.core.ui.R -import com.tangem.core.ui.ds.button.TangemButtonType -import com.tangem.core.ui.ds.image.TangemIconUM -import com.tangem.core.ui.ds.message.TangemMessageButtonUM -import com.tangem.core.ui.ds.message.TangemMessageEffect -import com.tangem.core.ui.ds.message.TangemMessageUM -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.wrappedList -import com.tangem.core.ui.res.TangemTheme -import com.tangem.feature.tokendetails.domain.WalletCardWarning -import com.tangem.feature.tokendetails.presentation.tokendetails.model.TokenDetailsClickIntents -import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsUM -import com.tangem.utils.transformer.Transformer -import kotlinx.collections.immutable.persistentListOf -import kotlinx.collections.immutable.toImmutableList -import com.tangem.core.res.R as CoreResR - -/** - * Maps card/wallet-level warnings (produced by `GetWalletCardWarningsUseCase` for a single-currency wallet) into - * Token Details notifications and prepends them to the existing currency-level notifications. - */ -internal class UpdateWalletCardWarningsTransformer( - private val walletCardWarnings: Set, - private val clickIntents: TokenDetailsClickIntents, -) : Transformer { - - override fun transform(prevState: TokenDetailsUM): TokenDetailsUM { - val others = prevState.notifications.filterNot { it.id in WALLET_CARD_WARNING_IDS } - val messages = walletCardWarnings.map(::mapWarning) - - return prevState.copy( - notifications = (messages + others).toImmutableList(), - ) - } - - @Suppress("LongMethod") - private fun mapWarning(warning: WalletCardWarning): TangemMessageUM { - return when (warning) { - WalletCardWarning.BackupError -> TangemMessageUM( - id = ID_BACKUP_ERROR, - title = resourceReference(CoreResR.string.warning_backup_errors_title), - subtitle = resourceReference(CoreResR.string.warning_backup_errors_message), - messageEffect = TangemMessageEffect.Warning, - iconUM = attentionIcon(), - buttonsUM = persistentListOf( - TangemMessageButtonUM( - text = resourceReference(CoreResR.string.common_contact_support), - type = TangemButtonType.Secondary, - onClick = clickIntents::onSupportClick, - ), - ), - ) - WalletCardWarning.DevCard -> TangemMessageUM( - id = ID_DEV_CARD, - title = resourceReference(CoreResR.string.warning_developer_card_title), - subtitle = resourceReference(CoreResR.string.warning_developer_card_message), - messageEffect = TangemMessageEffect.None, - iconUM = attentionIcon(), - ) - WalletCardWarning.FailedCardValidation -> TangemMessageUM( - id = ID_FAILED_CARD_VALIDATION, - title = resourceReference(CoreResR.string.warning_failed_to_verify_card_title), - subtitle = resourceReference(CoreResR.string.warning_failed_to_verify_card_message), - messageEffect = TangemMessageEffect.Warning, - iconUM = attentionIcon(), - ) - WalletCardWarning.TestnetCard -> TangemMessageUM( - id = ID_TESTNET_CARD, - title = resourceReference(CoreResR.string.warning_testnet_card_title), - subtitle = resourceReference(CoreResR.string.warning_testnet_card_message), - messageEffect = TangemMessageEffect.None, - iconUM = attentionIcon(), - ) - is WalletCardWarning.LowSignatures -> TangemMessageUM( - id = ID_LOW_SIGNATURES, - title = resourceReference(CoreResR.string.warning_low_signatures_title), - subtitle = resourceReference( - id = CoreResR.string.warning_low_signatures_message, - formatArgs = wrappedList(warning.count.toString()), - ), - messageEffect = TangemMessageEffect.None, - iconUM = attentionIcon(), - ) - WalletCardWarning.NumberOfSignedHashesIncorrect -> TangemMessageUM( - id = ID_NUMBER_OF_SIGNED_HASHES_INCORRECT, - title = resourceReference(CoreResR.string.warning_number_of_signed_hashes_incorrect_title), - subtitle = resourceReference(CoreResR.string.warning_number_of_signed_hashes_incorrect_message), - messageEffect = TangemMessageEffect.Warning, - iconUM = TangemIconUM.Icon( - iconRes = R.drawable.img_knight_shield_32, - tintReference = { TangemTheme.colors2.graphic.neutral.primary }, - ), - onCloseClick = clickIntents::onCloseSignedHashesWarning, - ) - WalletCardWarning.DemoCard -> TangemMessageUM( - id = ID_DEMO_CARD, - title = resourceReference(CoreResR.string.warning_demo_mode_title), - subtitle = resourceReference(CoreResR.string.warning_demo_mode_message), - messageEffect = TangemMessageEffect.None, - iconUM = attentionIcon(), - ) - } - } - - private fun attentionIcon(): TangemIconUM.Icon = TangemIconUM.Icon( - iconRes = R.drawable.ic_attention_default_24, - tintReference = { TangemTheme.colors2.graphic.neutral.primary }, - ) - - private companion object { - const val ID_BACKUP_ERROR = "BackupErrorNotification" - const val ID_DEV_CARD = "DevCardNotification" - const val ID_FAILED_CARD_VALIDATION = "FailedCardValidationNotification" - const val ID_TESTNET_CARD = "TestnetCardNotification" - const val ID_LOW_SIGNATURES = "LowSignaturesNotification" - const val ID_NUMBER_OF_SIGNED_HASHES_INCORRECT = "NumberOfSignedHashesIncorrectNotification" - const val ID_DEMO_CARD = "DemoCardNotification" - - val WALLET_CARD_WARNING_IDS = setOf( - ID_BACKUP_ERROR, - ID_DEV_CARD, - ID_FAILED_CARD_VALIDATION, - ID_TESTNET_CARD, - ID_LOW_SIGNATURES, - ID_NUMBER_OF_SIGNED_HASHES_INCORRECT, - ID_DEMO_CARD, - ) - } -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/test/kotlin/com/tangem/feature/tokendetails/domain/GetWalletCardWarningsUseCaseTest.kt b/features/tokendetails/impl/src/test/kotlin/com/tangem/feature/tokendetails/domain/GetWalletCardWarningsUseCaseTest.kt deleted file mode 100644 index 032327d98b..0000000000 --- a/features/tokendetails/impl/src/test/kotlin/com/tangem/feature/tokendetails/domain/GetWalletCardWarningsUseCaseTest.kt +++ /dev/null @@ -1,169 +0,0 @@ -package com.tangem.feature.tokendetails.domain - -import com.google.common.truth.Truth.assertThat -import com.tangem.domain.card.CardTypesResolver -import com.tangem.domain.card.IsWalletBackupProblematicUseCase -import com.tangem.domain.card.common.util.cardTypesResolver -import com.tangem.domain.demo.IsDemoCardUseCase -import com.tangem.domain.models.network.Network -import com.tangem.domain.models.wallet.UserWallet -import com.tangem.domain.wallets.usecase.HasSingleWalletSignedHashesUseCase -import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider -import io.mockk.clearMocks -import io.mockk.every -import io.mockk.mockk -import io.mockk.mockkStatic -import io.mockk.unmockkStatic -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -internal class GetWalletCardWarningsUseCaseTest { - - private val isDemoCardUseCase: IsDemoCardUseCase = mockk() - private val hasSingleWalletSignedHashesUseCase: HasSingleWalletSignedHashesUseCase = mockk() - private val isWalletBackupProblematicUseCase: IsWalletBackupProblematicUseCase = mockk() - private val network: Network = mockk(relaxed = true) - - private val useCase = GetWalletCardWarningsUseCase( - isDemoCardUseCase = isDemoCardUseCase, - hasSingleWalletSignedHashesUseCase = hasSingleWalletSignedHashesUseCase, - isWalletBackupProblematicUseCase = isWalletBackupProblematicUseCase, - dispatchers = TestingCoroutineDispatcherProvider(), - ) - - @BeforeEach - fun setup() { - clearMocks( - isDemoCardUseCase, - hasSingleWalletSignedHashesUseCase, - isWalletBackupProblematicUseCase, - ) - mockkStatic(UserWallet.Cold::cardTypesResolver) - - // Default: nothing flagged - every { isDemoCardUseCase(any()) } returns false - every { hasSingleWalletSignedHashesUseCase(any(), any()) } returns flowOf(false) - every { isWalletBackupProblematicUseCase(any()) } returns false - } - - @AfterEach - fun tearDown() { - unmockkStatic(UserWallet.Cold::cardTypesResolver) - } - - @Test - fun `GIVEN multi-currency cold wallet WHEN invoke THEN empty set`() = runTest { - // Arrange - val wallet = coldWallet(isMultiCurrency = true) - - // Act - val result = useCase(userWallet = wallet, network = network).first() - - // Assert - assertThat(result).isEmpty() - } - - @Test - fun `GIVEN hot wallet WHEN invoke THEN empty set`() = runTest { - // Arrange - val wallet = mockk(relaxed = true) - - // Act - val result = useCase(userWallet = wallet, network = network).first() - - // Assert - assertThat(result).isEmpty() - } - - @Test - fun `GIVEN single-currency cold wallet with clean card WHEN invoke THEN empty set`() = runTest { - // Arrange - val wallet = coldWallet(isMultiCurrency = false, resolver = cleanResolver()) - - // Act - val result = useCase(userWallet = wallet, network = network).first() - - // Assert - assertThat(result).isEmpty() - } - - @Test - fun `GIVEN single-currency dev card WHEN invoke THEN only dev card warning`() = runTest { - // Arrange - val resolver = cleanResolver().also { every { it.isReleaseFirmwareType() } returns false } - val wallet = coldWallet(isMultiCurrency = false, resolver = resolver) - - // Act - val result = useCase(userWallet = wallet, network = network).first() - - // Assert - assertThat(result).containsExactly(WalletCardWarning.DevCard) - } - - @Test - fun `GIVEN single-currency release card with every condition WHEN invoke THEN full warning set`() = runTest { - // Arrange - val resolver = cleanResolver().also { - every { it.isReleaseFirmwareType() } returns true - every { it.isAttestationFailed() } returns true - every { it.getRemainingSignatures() } returns LOW_SIGNATURES - every { it.isTestCard() } returns true - } - val wallet = coldWallet(isMultiCurrency = false, resolver = resolver) - every { isWalletBackupProblematicUseCase(any()) } returns true - every { isDemoCardUseCase(any()) } returns true - every { hasSingleWalletSignedHashesUseCase(any(), any()) } returns flowOf(true) - - // Act - val result = useCase(userWallet = wallet, network = network).first() - - // Assert - assertThat(result).containsExactly( - WalletCardWarning.BackupError, - WalletCardWarning.FailedCardValidation, - WalletCardWarning.TestnetCard, - WalletCardWarning.LowSignatures(count = LOW_SIGNATURES), - WalletCardWarning.DemoCard, - WalletCardWarning.NumberOfSignedHashesIncorrect, - ) - } - - @Test - fun `GIVEN single-currency cold wallet with backup problem WHEN invoke THEN backup error warning`() = runTest { - // Arrange - val wallet = coldWallet(isMultiCurrency = false, resolver = cleanResolver()) - every { isWalletBackupProblematicUseCase(any()) } returns true - - // Act - val result = useCase(userWallet = wallet, network = network).first() - - // Assert - assertThat(result).containsExactly(WalletCardWarning.BackupError) - } - - private fun coldWallet( - isMultiCurrency: Boolean, - resolver: CardTypesResolver = cleanResolver(), - ): UserWallet.Cold { - return mockk(relaxed = true) { - every { this@mockk.isMultiCurrency } returns isMultiCurrency - every { cardTypesResolver } returns resolver - } - } - - private fun cleanResolver(): CardTypesResolver = mockk { - every { isReleaseFirmwareType() } returns true - every { isAttestationFailed() } returns false - every { getRemainingSignatures() } returns null - every { isTestCard() } returns false - every { getCardId() } returns "card" - } - - private companion object { - const val LOW_SIGNATURES = 5 - } -} \ No newline at end of file diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt index b31d3c96a2..82596dbd03 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetSingleWalletWarningsFactory.kt @@ -16,7 +16,6 @@ import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.settings.IsReadyToShowRateAppUseCase import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.wallets.usecase.GetWalletsUseCase -import com.tangem.domain.wallets.usecase.HasSingleWalletSignedHashesUseCase import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetWalletNotificationsFactory.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetWalletNotificationsFactory.kt index 70eba8bafd..5ac471112e 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetWalletNotificationsFactory.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/GetWalletNotificationsFactory.kt @@ -20,7 +20,6 @@ import com.tangem.domain.models.currency.CryptoCurrency import com.tangem.domain.models.currency.CryptoCurrencyStatus import com.tangem.domain.models.wallet.UserWallet import com.tangem.domain.models.wallet.isMultiCurrency -import com.tangem.domain.wallets.usecase.HasSingleWalletSignedHashesUseCase import com.tangem.domain.wallets.usecase.IsNeedToBackupUseCase import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents import com.tangem.feature.wallet.impl.R diff --git a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/HasSingleWalletSignedHashesUseCase.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/HasSingleWalletSignedHashesUseCase.kt similarity index 86% rename from domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/HasSingleWalletSignedHashesUseCase.kt rename to features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/HasSingleWalletSignedHashesUseCase.kt index be6a4b0ddd..4f32140696 100644 --- a/domain/wallets/src/main/java/com/tangem/domain/wallets/usecase/HasSingleWalletSignedHashesUseCase.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/domain/HasSingleWalletSignedHashesUseCase.kt @@ -1,5 +1,6 @@ -package com.tangem.domain.wallets.usecase +package com.tangem.feature.wallet.presentation.wallet.domain +import com.tangem.core.decompose.di.ModelScoped import com.tangem.domain.card.common.util.cardTypesResolver import com.tangem.domain.card.repository.CardRepository import com.tangem.domain.demo.models.DemoConfig @@ -9,8 +10,10 @@ import com.tangem.domain.walletmanager.WalletManagersFacade import com.tangem.utils.logging.TangemLogger import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map +import javax.inject.Inject -class HasSingleWalletSignedHashesUseCase( +@ModelScoped +class HasSingleWalletSignedHashesUseCase @Inject constructor( private val cardRepository: CardRepository, private val walletManagersFacade: WalletManagersFacade, ) { @@ -25,16 +28,11 @@ class HasSingleWalletSignedHashesUseCase( return@map false } - val signedHashes = userWallet.scanResponse.card.wallets - .firstOrNull() - ?.totalSignedHashes - ?: 0 - return@map try { walletManagersFacade.validateSignatureCount( userWalletId = userWallet.walletId, network = network, - signedHashes = signedHashes, + signedHashes = userWallet.scanResponse.card.wallets.firstOrNull()?.totalSignedHashes ?: 0, ) .fold( ifLeft = { true },