Updated on 2026-08-14

This commit is contained in:
Tangem 2025-05-30 14:08:42 +03:00
parent e33bd4d849
commit b98b0f659c
138 changed files with 686 additions and 346 deletions

View file

@ -22,6 +22,7 @@ import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.models.isMultiCurrency
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
@ -243,7 +244,7 @@ internal class WalletModel @Inject constructor(
deepLinksRegistry.register(
ReferralDeepLink(
onReceive = {
if (userWallet.cardTypesResolver.isTangemWallet()) {
if (userWallet !is UserWallet.Cold || userWallet.cardTypesResolver.isTangemWallet()) {
appRouter.push(
AppRoute.ReferralProgram(userWalletId = userWallet.walletId),
)
@ -517,7 +518,7 @@ internal class WalletModel @Inject constructor(
}
private fun fetchIfSingleWallet(userWallet: UserWallet) {
if (userWallet.scanResponse.cardTypesResolver.isSingleWallet()) {
if (userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isSingleWallet()) {
modelScope.launch {
fetchCurrencyStatusUseCase(userWalletId = userWallet.walletId)
.onLeft { Timber.e(it.toString()) }

View file

@ -5,6 +5,7 @@ import com.tangem.core.decompose.di.ModelScoped
import com.tangem.domain.common.util.getCardsCount
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.models.isLocked
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.feature.wallet.presentation.wallet.state.model.NOT_INITIALIZED_WALLET_INDEX
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
@ -175,6 +176,7 @@ internal class WalletsUpdateActionResolver @Inject constructor(
}
private fun isSelectedWalletCardsCountChanged(state: WalletScreenState, selectedWallet: UserWallet): Boolean {
if (selectedWallet !is UserWallet.Cold) return false
val prevSelectedWallet = state.getPrevSelectedWallet()
return prevSelectedWallet is WalletCardState.Content &&
prevSelectedWallet.cardCount != selectedWallet.getCardsCount()

View file

@ -10,6 +10,7 @@ import com.tangem.domain.feedback.models.FeedbackEmailType
import com.tangem.domain.visa.GetVisaCurrencyUseCase
import com.tangem.domain.visa.GetVisaTxDetailsUseCase
import com.tangem.domain.visa.model.VisaTxDetails
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.BalancesAndLimitsBottomSheetConverter
@ -100,7 +101,9 @@ internal class VisaWalletIntentsImplementor @Inject constructor(
val userWalletId = stateController.getSelectedWalletId()
val userWallet = getUserWalletsUseCase.invokeSync()
.firstOrNull { it.walletId == userWalletId } ?: return@launch
val cardInfo = getCardInfoUseCase.invoke(userWallet.scanResponse).getOrNull() ?: return@launch
val cardInfo = getCardInfoUseCase.invoke(
userWallet.requireColdWallet().scanResponse,
).getOrNull() ?: return@launch
sendFeedbackEmailUseCase(
FeedbackEmailType.Visa.Dispute(

View file

@ -8,6 +8,7 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.domain.card.DeleteSavedAccessCodesUseCase
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.usecase.DeleteWalletUseCase
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
@ -86,8 +87,10 @@ internal class WalletCardClickIntentsImplementor @Inject constructor(
return@launch
}
deleteSavedAccessCodesUseCase(cardId = walletToDelete.cardId).onLeft {
Timber.e("Unable to delete user wallet access code: $it")
if (walletToDelete is UserWallet.Cold) {
deleteSavedAccessCodesUseCase(cardId = walletToDelete.cardId).onLeft {
Timber.e("Unable to delete user wallet access code: $it")
}
}
if (hasUserWallets) {

View file

@ -11,6 +11,7 @@ import com.tangem.domain.tokens.FetchCardTokenListUseCase
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
import com.tangem.domain.tokens.FetchTokenListUseCase
import com.tangem.domain.tokens.FetchTokenListUseCase.RefreshMode
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
import com.tangem.domain.wallets.usecase.SelectWalletUseCase
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
@ -126,7 +127,10 @@ internal class WalletClickIntents @Inject constructor(
)
modelScope.launch {
val maybeFetchResult = if (userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
val maybeFetchResult = if (
userWallet is UserWallet.Cold &&
userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
) {
fetchCardTokenListUseCase(userWalletId = userWallet.walletId, refresh = true)
} else {
fetchTokenListUseCase(userWalletId = userWallet.walletId, mode = RefreshMode.FULL)

View file

@ -14,6 +14,7 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.TokenActionsState
import com.tangem.domain.txhistory.usecase.GetExplorerTransactionUrlUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.isLocked
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.feature.wallet.presentation.wallet.domain.OnrampStatusFactory
import com.tangem.feature.wallet.presentation.wallet.domain.unwrap

View file

@ -48,6 +48,7 @@ import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.AVAILABLE
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent.Companion.toReasonAnalyticsText
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.usecase.GetExploreUrlUseCase
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
@ -561,9 +562,9 @@ internal class WalletCurrencyActionsClickIntentsImplementor @Inject constructor(
}
private fun showErrorIfDemoModeOrElse(action: () -> Unit) {
val cardId = getSelectedWalletSyncUseCase.unwrap()?.cardId ?: return
val selectedWallet = getSelectedWalletSyncUseCase.unwrap() ?: return
if (isDemoCardUseCase(cardId = cardId)) {
if (selectedWallet is UserWallet.Cold && isDemoCardUseCase(cardId = selectedWallet.cardId)) {
stateHolder.update(CloseBottomSheetTransformer(userWalletId = stateHolder.getSelectedWalletId()))
walletEventSender.send(

View file

@ -24,6 +24,7 @@ import com.tangem.domain.tokens.model.analytics.TokenSwapPromoAnalyticsEvent
import com.tangem.domain.wallets.legacy.UserWalletsListManager.Lockable.UnlockType
import com.tangem.domain.wallets.models.UnlockWalletsError
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.domain.wallets.usecase.SeedPhraseNotificationUseCase
import com.tangem.domain.wallets.usecase.UnlockWalletsUseCase
@ -113,7 +114,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
private fun prepareAndStartOnboardingProcess() {
modelScope.launch(dispatchers.main) {
getSelectedUserWallet()?.let {
getSelectedUserWallet()?.requireColdWallet()?.let {
router.openOnboardingScreen(
scanResponse = it.scanResponse,
continueBackup = true,
@ -126,7 +127,9 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
modelScope.launch(dispatchers.main) {
val userWallet = getSelectedUserWallet() ?: return@launch
setCardWasScannedUseCase(cardId = userWallet.cardId)
if (userWallet is UserWallet.Cold) {
setCardWasScannedUseCase(cardId = userWallet.cardId)
}
}
}
@ -234,7 +237,8 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
modelScope.launch(dispatchers.main) {
neverToSuggestRateAppUseCase()
val scanResponse = getSelectedUserWallet()?.scanResponse ?: return@launch
val scanResponse =
getSelectedUserWallet()?.requireColdWallet()?.scanResponse ?: return@launch // TODO [REDACTED_TASK_KEY]
val cardInfo = getCardInfoUseCase(scanResponse).getOrNull() ?: return@launch
sendFeedbackEmailUseCase(type = FeedbackEmailType.RateCanBeBetter(cardInfo = cardInfo))
@ -275,7 +279,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
}
override fun onSupportClick() {
val scanResponse = getSelectedUserWallet()?.scanResponse ?: return
val scanResponse = getSelectedUserWallet()?.requireColdWallet()?.scanResponse ?: return // TODO [REDACTED_TASK_KEY]
val cardInfo = getCardInfoUseCase(scanResponse).getOrNull() ?: return
modelScope.launch {

View file

@ -11,6 +11,7 @@ import com.tangem.domain.tokens.GetCryptoCurrencyUseCase
import com.tangem.domain.tokens.model.analytics.TokenScreenAnalyticsEvent
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.models.isMultiCurrency
import com.tangem.features.onramp.OnrampFeatureToggles
import com.tangem.utils.coroutines.launchOnCancellation
import kotlinx.coroutines.CoroutineScope

View file

@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.analytics.utils
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.isLocked
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent
import javax.inject.Inject

View file

@ -17,6 +17,7 @@ import com.tangem.domain.tokens.model.TokenList
import com.tangem.domain.tokens.model.TotalFiatBalance
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.models.isMultiCurrency
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.Basic
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState

View file

@ -41,7 +41,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
@Suppress("MagicNumber", "MaximumLineLength")
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow<ImmutableList<WalletNotification>> {
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
val cardTypesResolver = (userWallet as? UserWallet.Cold)?.scanResponse?.cardTypesResolver
return combine(
flow = tokenListStore.getOrThrow(userWallet.walletId),
@ -94,6 +94,10 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
seedPhraseIssueStatus: SeedPhraseNotificationsStatus,
clickIntents: WalletClickIntents,
) {
if (userWallet !is UserWallet.Cold) {
return
}
addSeedNotificationIfNeeded(userWallet, seedPhraseIssueStatus, clickIntents)
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
@ -121,7 +125,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
}
private fun MutableList<WalletNotification>.addSeedNotificationIfNeeded(
userWallet: UserWallet,
userWallet: UserWallet.Cold,
seedPhraseIssueStatus: SeedPhraseNotificationsStatus,
clickIntents: WalletClickIntents,
) {
@ -154,13 +158,13 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
}
private fun MutableList<WalletNotification>.addInformationalNotifications(
cardTypesResolver: CardTypesResolver,
cardTypesResolver: CardTypesResolver?,
maybeTokenList: Lce<TokenListError, TokenList>,
clickIntents: WalletClickIntents,
) {
addIf(
element = WalletNotification.Informational.DemoCard,
condition = isDemoCardUseCase(cardId = cardTypesResolver.getCardId()),
condition = cardTypesResolver != null && isDemoCardUseCase(cardId = cardTypesResolver.getCardId()),
)
addMissingAddressesNotification(maybeTokenList, clickIntents)
@ -194,7 +198,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
}
private fun MutableList<WalletNotification>.addReferralPromoNotification(
cardTypesResolver: CardTypesResolver,
cardTypesResolver: CardTypesResolver?,
clickIntents: WalletClickIntents,
shouldShowPromo: Boolean,
) {
@ -203,12 +207,12 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
onCloseClick = { clickIntents.onClosePromoClick(promoId = PromoId.Referral) },
onClick = { clickIntents.onPromoClick(promoId = PromoId.Referral) },
),
condition = shouldShowPromo && cardTypesResolver.isTangemWallet(),
condition = shouldShowPromo && (cardTypesResolver == null || cardTypesResolver.isTangemWallet()),
)
}
private fun MutableList<WalletNotification>.addWarningNotifications(
cardTypesResolver: CardTypesResolver,
cardTypesResolver: CardTypesResolver?,
tokenList: Lce<TokenListError, TokenList>,
isNeedToBackup: Boolean,
clickIntents: WalletClickIntents,
@ -222,7 +226,7 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
addIf(
element = WalletNotification.Warning.TestNetCard,
condition = cardTypesResolver.isTestCard(),
condition = cardTypesResolver?.isTestCard() == true,
)
addIf(

View file

@ -33,6 +33,9 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
private var readyForRateAppNotification = false
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow<ImmutableList<WalletNotification>> {
if (userWallet !is UserWallet.Cold) {
return flowOf(emptyList<WalletNotification>().toImmutableList())
}
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
return combine(
@ -107,10 +110,11 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
cardTypesResolver: CardTypesResolver,
clickIntents: WalletClickIntents,
) {
val userHasWalletOrWallet2 = userWallets.any {
val userHasWalletOrWallet2 = userWallets.filterIsInstance<UserWallet.Cold>().any {
val typesResolver = it.scanResponse.cardTypesResolver
typesResolver.isTangemWallet() || typesResolver.isWallet2()
}
addIf(
element = WalletNotification.NoteMigration(
onClick = { clickIntents.onNoteMigrationButtonClick(NOTE_MIGRATION_URL) },
@ -125,7 +129,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
}
private suspend fun MutableList<WalletNotification>.addWarningNotifications(
userWallet: UserWallet,
userWallet: UserWallet.Cold,
cardTypesResolver: CardTypesResolver,
maybePrimaryCurrencyStatus: Either<CurrencyStatusError, CryptoCurrencyStatus>,
isNeedToBackup: Boolean,
@ -174,7 +178,7 @@ internal class GetSingleWalletWarningsFactory @Inject constructor(
}
private suspend fun hasSignedHashes(
selectedWallet: UserWallet,
selectedWallet: UserWallet.Cold,
cryptoCurrencyStatus: CryptoCurrencyStatus?,
): Boolean {
return cryptoCurrencyStatus?.currency?.network?.let {

View file

@ -17,7 +17,7 @@ class HasSingleWalletSignedHashesUseCase @Inject constructor(
private val walletManagersFacade: WalletManagersFacade,
) {
operator fun invoke(userWallet: UserWallet, network: Network): Flow<Boolean> {
operator fun invoke(userWallet: UserWallet.Cold, network: Network): Flow<Boolean> {
return cardRepository.wasCardScanned(cardId = userWallet.cardId)
.map { wasCardScanned ->
if (wasCardScanned || !userWallet.isCorrectCardType()) return@map false
@ -42,7 +42,7 @@ class HasSingleWalletSignedHashesUseCase @Inject constructor(
}
}
private fun UserWallet.isCorrectCardType(): Boolean {
private fun UserWallet.Cold.isCorrectCardType(): Boolean {
return with(scanResponse.cardTypesResolver) {
!DemoConfig().isDemoCardId(cardId) && isReleaseFirmwareType() && !isMultiwalletAllowed() && !isTangemTwins()
}

View file

@ -7,7 +7,7 @@ import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemSdkError
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.wallets.builder.UserWalletBuilder
import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
import javax.inject.Inject
@ -15,7 +15,7 @@ import javax.inject.Inject
internal class ScanCardToUnlockWalletClickHandler @Inject constructor(
private val scanCardProcessor: ScanCardProcessor,
private val saveWalletUseCase: SaveWalletUseCase,
private val userWalletBuilderFactory: UserWalletBuilder.Factory,
private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory,
) {
private var scanFailsCounter = 0
@ -33,7 +33,7 @@ internal class ScanCardToUnlockWalletClickHandler @Inject constructor(
scanFailsCounter = 0
// If card's public key is null then user wallet will be null
val scannedWallet = userWalletBuilderFactory.create(scanResponse = result.data).build()
val scannedWallet = coldUserWalletBuilderFactory.create(scanResponse = result.data).build()
ensure(walletId == scannedWallet?.walletId) {
ScanCardToUnlockWalletError.WrongCardIsScanned

View file

@ -9,6 +9,8 @@ import com.tangem.core.ui.format.bigdecimal.format
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.common.util.getCardsCount
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.isLocked
import com.tangem.domain.wallets.models.isMultiCurrency
import com.tangem.feature.wallet.impl.R
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAdditionalInfo
import java.math.BigDecimal
@ -29,14 +31,19 @@ internal object WalletAdditionalInfoFactory {
* @param currencyAmount amount of currency
*/
fun resolve(wallet: UserWallet, currencyAmount: BigDecimal? = null): WalletAdditionalInfo {
return if (wallet.isMultiCurrency) {
wallet.resolveMultiCurrencyInfo()
} else {
wallet.resolveSingleCurrencyInfo(currencyAmount)
return when (wallet) {
is UserWallet.Cold -> {
if (wallet.isMultiCurrency) {
wallet.resolveMultiCurrencyInfo()
} else {
wallet.resolveSingleCurrencyInfo(currencyAmount)
}
}
is UserWallet.Hot -> TODO("[REDACTED_TASK_KEY]")
}
}
private fun UserWallet.resolveMultiCurrencyInfo(): WalletAdditionalInfo {
private fun UserWallet.Cold.resolveMultiCurrencyInfo(): WalletAdditionalInfo {
return if (isLocked) {
WalletAdditionalInfo(
hideable = false,
@ -54,7 +61,7 @@ internal object WalletAdditionalInfoFactory {
}
}
private fun UserWallet.resolveWallet2Info(): WalletAdditionalInfo {
private fun UserWallet.Cold.resolveWallet2Info(): WalletAdditionalInfo {
return if (isImported) {
WalletAdditionalInfo(
hideable = false,
@ -93,7 +100,7 @@ internal object WalletAdditionalInfoFactory {
)
}
private fun UserWallet.resolveSingleCurrencyInfo(currencyAmount: BigDecimal?): WalletAdditionalInfo {
private fun UserWallet.Cold.resolveSingleCurrencyInfo(currencyAmount: BigDecimal?): WalletAdditionalInfo {
return if (isLocked) {
WalletAdditionalInfo(hideable = false, content = TextReference.Res(R.string.common_locked))
} else {

View file

@ -24,7 +24,7 @@ internal class WalletImageResolver @Inject constructor(
/** Get a specified wallet [userWallet] image */
@Suppress("CyclomaticComplexMethod")
@DrawableRes
fun resolve(userWallet: UserWallet): Int? {
fun resolve(userWallet: UserWallet.Cold): Int? {
val cardTypesResolver = userWallet.scanResponse.cardTypesResolver
val cobrandImage = Wallet2CobrandImage.entries.firstOrNull {
@ -52,30 +52,30 @@ internal class WalletImageResolver @Inject constructor(
}
}
private fun UserWallet.isRing(): Boolean {
private fun UserWallet.Cold.isRing(): Boolean {
return scanResponse.cardTypesResolver.isRing() ||
runBlocking { walletsRepository.isWalletWithRing(userWalletId = this@isRing.walletId) }
}
private fun UserWallet.resolveWalletWithRing(): Int? {
private fun UserWallet.Cold.resolveWalletWithRing(): Int? {
return resolveWallet2(
oneBackupResId = R.drawable.ill_card_with_ring_120_106,
twoBackupResId = R.drawable.ill_card2_with_ring_120_106,
)
}
private fun UserWallet.resolveWallet2Cobrand(image: Wallet2CobrandImage): Int? {
private fun UserWallet.Cold.resolveWallet2Cobrand(image: Wallet2CobrandImage): Int? {
return resolveWallet2(oneBackupResId = image.cards2ResId, twoBackupResId = image.cards3ResId)
}
private fun UserWallet.resolveShibaWallet(): Int? {
private fun UserWallet.Cold.resolveShibaWallet(): Int? {
return resolveWallet2(
oneBackupResId = R.drawable.ill_shiba_card2_120_106,
twoBackupResId = R.drawable.ill_shiba_card3_120_106,
)
}
private fun UserWallet.resolveWallet2(
private fun UserWallet.Cold.resolveWallet2(
@DrawableRes oneBackupResId: Int = R.drawable.ill_wallet2_cards2_120_106,
@DrawableRes twoBackupResId: Int = R.drawable.ill_wallet2_cards3_120_106,
): Int? {
@ -90,7 +90,7 @@ internal class WalletImageResolver @Inject constructor(
}
}
private fun UserWallet.resolveWallet1(): Int? {
private fun UserWallet.Cold.resolveWallet1(): Int? {
return resolveWalletWithBackups { count ->
when (count) {
WALLET_WITHOUT_BACKUP_COUNT -> R.drawable.ill_wallet1_cards1_120_106
@ -101,7 +101,7 @@ internal class WalletImageResolver @Inject constructor(
}
}
private fun UserWallet.resolveWalletWithBackups(resolve: (Int) -> Int?): Int? {
private fun UserWallet.Cold.resolveWalletWithBackups(resolve: (Int) -> Int?): Int? {
val count = getCardsCount()
return if (count != null) resolve(count) else null

View file

@ -1,6 +1,7 @@
package com.tangem.feature.wallet.presentation.wallet.domain
import com.tangem.domain.wallets.legacy.UserWalletsListManager
import com.tangem.domain.wallets.models.copy
import com.tangem.domain.wallets.repository.WalletNamesMigrationRepository
import timber.log.Timber

View file

@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.loaders
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.isMultiCurrency
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.wallet.loaders.implementors.*
import javax.inject.Inject
@ -24,10 +25,10 @@ internal class WalletContentLoaderFactory @Inject constructor(
userWallet.isMultiCurrency -> {
multiWalletContentLoaderFactory.create(userWallet, clickIntents)
}
userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken() -> {
userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken() -> {
singleWalletWithTokenContentLoaderFactory.create(userWallet, clickIntents)
}
userWallet.scanResponse.cardTypesResolver.isVisaWallet() -> {
userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isVisaWallet() -> {
visaWalletContentLoaderFactory.create(userWallet, clickIntents, isRefresh)
}
!userWallet.isMultiCurrency -> {

View file

@ -3,6 +3,7 @@ package com.tangem.feature.wallet.presentation.wallet.loaders
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.models.isLocked
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.CoroutineScope

View file

@ -2,6 +2,8 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.isLocked
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
import com.tangem.feature.wallet.presentation.wallet.state.model.*
@ -53,6 +55,8 @@ internal class InitializeWalletsTransformer(
}
private fun createLockedState(userWallet: UserWallet): WalletState {
userWallet.requireColdWallet()
return userWallet.createStateByWalletType(
multiCurrencyCreator = {
WalletState.MultiCurrency.Locked(
@ -83,7 +87,7 @@ internal class InitializeWalletsTransformer(
)
}
private fun UserWallet.toLockedWalletCardState(): WalletCardState {
private fun UserWallet.Cold.toLockedWalletCardState(): WalletCardState {
return WalletCardState.LockedContent(
id = walletId,
title = name,
@ -94,7 +98,8 @@ internal class InitializeWalletsTransformer(
}
private fun createMultiWalletEnabledButtons(userWallet: UserWallet): PersistentList<WalletManageButton> {
val isSingleWalletWithToken = userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
val isSingleWalletWithToken = userWallet is UserWallet.Cold &&
userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
if (isSingleWalletWithToken) return persistentListOf()
return persistentListOf(

View file

@ -99,7 +99,7 @@ internal class SetCryptoCurrencyActionsTransformer(
}
private fun List<TokenActionsState.ActionState>.filterIfS2C(): List<TokenActionsState.ActionState> {
return if (userWallet.scanResponse.cardTypesResolver.isStart2Coin()) {
return if (userWallet is UserWallet.Cold && userWallet.scanResponse.cardTypesResolver.isStart2Coin()) {
filterNot { it is TokenActionsState.ActionState.Buy || it is TokenActionsState.ActionState.Sell }
} else {
this

View file

@ -6,6 +6,7 @@ import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.common.util.getCardsCount
import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
@ -56,6 +57,8 @@ internal class SetTokenListErrorTransformer(
}
private fun WalletCardState.toLoadedState(): WalletCardState {
selectedWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
return WalletCardState.Content(
id = id,
title = title,

View file

@ -1,5 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.blockchain.common.Blockchain
import com.tangem.core.ui.components.transactions.state.TxHistoryState
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.models.network.TxInfo
@ -19,7 +20,11 @@ internal class SetTxHistoryCountErrorTransformer(
) : WalletStateTransformer(userWallet.walletId) {
private val txHistoryItemConverter by lazy {
val blockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain()
val blockchain = when (userWallet) {
is UserWallet.Cold -> userWallet.scanResponse.cardTypesResolver.getBlockchain()
is UserWallet.Hot -> Blockchain.Unknown
}
TxHistoryItemStateConverter(
symbol = blockchain.currency,
decimals = blockchain.decimals(),

View file

@ -13,6 +13,7 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.visa.exception.RefreshTokenExpiredException
import com.tangem.domain.visa.model.VisaCurrency
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.feature.wallet.presentation.wallet.state.model.BalancesAndLimitsBlockState
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletAdditionalInfo
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
@ -75,6 +76,8 @@ internal class SetVisaInfoTransformer(
}
private fun getContentWalletCardState(prevState: WalletCardState, visaCurrency: VisaCurrency): WalletCardState {
userWallet.requireColdWallet() // TODO [REDACTED_TASK_KEY]
return with(prevState) {
WalletCardState.Content(
id = id,

View file

@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.wallet.state.transformers
import com.tangem.domain.common.util.getCardsCount
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
@ -39,8 +40,8 @@ internal class UpdateWalletCardsCountTransformer(
return when (this) {
is WalletCardState.Content -> copy(
additionalInfo = WalletAdditionalInfoFactory.resolve(wallet = userWallet),
imageResId = walletImageResolver.resolve(userWallet = userWallet),
cardCount = userWallet.getCardsCount(),
imageResId = walletImageResolver.resolve(userWallet = userWallet.requireColdWallet()), // TODO [REDACTED_TASK_KEY]
cardCount = userWallet.requireColdWallet().getCardsCount(), // TODO [REDACTED_TASK_KEY]
)
else -> this
}

View file

@ -7,6 +7,7 @@ import com.tangem.domain.common.util.getCardsCount
import com.tangem.domain.models.StatusSource
import com.tangem.domain.tokens.model.TotalFiatBalance
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
import com.tangem.utils.converter.Converter
@ -47,6 +48,8 @@ internal class MultiWalletCardStateConverter(
}
private fun WalletCardState.toWalletCardState(fiatBalance: TotalFiatBalance.Loaded): WalletCardState {
selectedWallet.requireColdWallet()
return WalletCardState.Content(
id = id,
title = title,

View file

@ -30,7 +30,9 @@ internal class MultiWalletCurrencyActionsConverter(
}
private fun List<TokenActionsState.ActionState>.filterIfSingleWithToken(): List<TokenActionsState.ActionState> {
return if (userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()) {
return if (userWallet is UserWallet.Cold &&
userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
) {
filter { it !is TokenActionsState.ActionState.HideToken }
} else {
this

View file

@ -7,6 +7,7 @@ import com.tangem.domain.common.util.getCardsCount
import com.tangem.domain.models.StatusSource
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletCardState
import com.tangem.utils.StringsSigns.DASH_SIGN
@ -63,7 +64,7 @@ internal class SingleWalletCardStateConverter(
imageResId = imageResId,
dropDownItems = dropDownItems,
balance = formatFiatAmount(status = status, appCurrency = appCurrency),
cardCount = selectedWallet.getCardsCount(),
cardCount = selectedWallet.requireColdWallet().getCardsCount(), // TODO [REDACTED_TASK_KEY]
isZeroBalance = status.fiatAmount?.isZero(),
isBalanceFlickering = (status as? CryptoCurrencyStatus.Loaded)?.sources?.total == StatusSource.CACHE,
)

View file

@ -95,6 +95,7 @@ internal class TokenListStateConverter(
}
private fun isSingleCurrencyWalletWithToken(): Boolean {
return selectedWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
return selectedWallet is UserWallet.Cold &&
selectedWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
}
}

View file

@ -4,7 +4,7 @@ import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletState
internal inline fun UserWallet.createStateByWalletType(
internal inline fun UserWallet.Cold.createStateByWalletType(
multiCurrencyCreator: () -> WalletState.MultiCurrency,
singleCurrencyCreator: () -> WalletState.SingleCurrency,
visaWalletCreator: () -> WalletState.Visa,
@ -14,10 +14,10 @@ internal inline fun UserWallet.createStateByWalletType(
else -> singleCurrencyCreator()
}
private fun UserWallet.isWalletWithTokens(): Boolean {
private fun UserWallet.Cold.isWalletWithTokens(): Boolean {
return isMultiCurrency || scanResponse.cardTypesResolver.isSingleWalletWithToken()
}
private fun UserWallet.isVisaWallet(): Boolean {
private fun UserWallet.Cold.isVisaWallet(): Boolean {
return scanResponse.cardTypesResolver.isVisaWallet()
}

View file

@ -6,6 +6,7 @@ import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
import com.tangem.core.ui.components.transactions.state.TxHistoryState
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.wallet.domain.WalletAdditionalInfoFactory
import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
@ -25,6 +26,8 @@ internal class WalletLoadingStateFactory(
) {
fun create(userWallet: UserWallet): WalletState {
userWallet.requireColdWallet()
return userWallet.createStateByWalletType(
multiCurrencyCreator = { createLoadingMultiCurrencyContent(userWallet) },
singleCurrencyCreator = { createLoadingSingleCurrencyContent(userWallet) },
@ -32,7 +35,7 @@ internal class WalletLoadingStateFactory(
)
}
private fun createLoadingMultiCurrencyContent(userWallet: UserWallet): WalletState.MultiCurrency.Content {
private fun createLoadingMultiCurrencyContent(userWallet: UserWallet.Cold): WalletState.MultiCurrency.Content {
return WalletState.MultiCurrency.Content(
pullToRefreshConfig = createPullToRefreshConfig(),
walletCardState = userWallet.toLoadingWalletCardState(),
@ -44,7 +47,7 @@ internal class WalletLoadingStateFactory(
)
}
private fun createLoadingSingleCurrencyContent(userWallet: UserWallet): WalletState.SingleCurrency.Content {
private fun createLoadingSingleCurrencyContent(userWallet: UserWallet.Cold): WalletState.SingleCurrency.Content {
val currencySymbol = userWallet.scanResponse.cardTypesResolver.getBlockchain().currency
return WalletState.SingleCurrency.Content(
pullToRefreshConfig = createPullToRefreshConfig(),
@ -63,7 +66,7 @@ internal class WalletLoadingStateFactory(
)
}
private fun createLoadingVisaWalletContent(userWallet: UserWallet): WalletState.Visa.Content {
private fun createLoadingVisaWalletContent(userWallet: UserWallet.Cold): WalletState.Visa.Content {
return WalletState.Visa.Content(
pullToRefreshConfig = createPullToRefreshConfig(),
walletCardState = userWallet.toLoadingWalletCardState(),
@ -86,7 +89,7 @@ internal class WalletLoadingStateFactory(
)
}
private fun UserWallet.toLoadingWalletCardState(): WalletCardState {
private fun UserWallet.Cold.toLoadingWalletCardState(): WalletCardState {
return WalletCardState.Loading(
id = walletId,
title = name,
@ -96,7 +99,7 @@ internal class WalletLoadingStateFactory(
)
}
private fun createMultiWalletActions(userWallet: UserWallet): PersistentList<WalletManageButton> {
private fun createMultiWalletActions(userWallet: UserWallet.Cold): PersistentList<WalletManageButton> {
val isSingleWalletWithToken = userWallet.scanResponse.cardTypesResolver.isSingleWalletWithToken()
if (isSingleWalletWithToken) return persistentListOf()

View file

@ -13,6 +13,7 @@ import com.tangem.domain.txhistory.models.TxHistoryStateError
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsCountUseCase
import com.tangem.domain.txhistory.usecase.GetTxHistoryItemsUseCase
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.wallet.domain.collectLatest
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
@ -96,7 +97,7 @@ internal class TxHistorySubscriber(
)
},
ifRight = { itemsFlow ->
val blockchain = userWallet.scanResponse.cardTypesResolver.getBlockchain()
val blockchain = userWallet.requireColdWallet().scanResponse.cardTypesResolver.getBlockchain()
val itemConverter = TxHistoryItemStateConverter(
symbol = blockchain.currency,
decimals = blockchain.decimals(),

View file

@ -22,6 +22,7 @@ import com.tangem.domain.tokens.error.TokenListError
import com.tangem.domain.tokens.model.TotalFiatBalance
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.domain.wallets.models.requireColdWallet
import com.tangem.domain.wallets.usecase.GetCardImageUseCase
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.features.wallet.utils.UserWalletsFetcher
@ -84,6 +85,7 @@ internal class DefaultUserWalletsFetcher @AssistedInject constructor(
return flow {
emit(hashMapOf()) // emits right away so the transform doesn't wait for the images' loading to finish
wallets.forEach { wallet ->
wallet.requireColdWallet()
val artwork = getCardImageUseCase(
cardId = wallet.cardId,
manufacturerName = wallet.scanResponse.card.manufacturer.name,