Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-14 14:50:24 +03:00
commit 50fe9e603d
1919 changed files with 94940 additions and 15178 deletions

View file

@ -9,21 +9,19 @@ android {
}
dependencies {
/** AndroidX */
implementation(deps.androidx.fragment.ktx)
/** Project - Domain */
implementation(projects.domain.models)
implementation(projects.domain.visa.models)
api(projects.domain.models)
api(projects.domain.visa.models)
/** Tangem libraries */
implementation(tangemDeps.card.core)
api(tangemDeps.card.core)
/** Core */
implementation(projects.core.ui)
implementation(projects.core.decompose)
implementation(projects.common.ui)
api(projects.core.ui)
api(projects.core.decompose)
api(projects.common.ui)
/** Other */
api(deps.kotlin.coroutines)
implementation(deps.kotlin.immutable.collections)
}

View file

@ -7,8 +7,6 @@ package com.tangem.features.wallet.featuretoggles
*/
interface WalletFeatureToggles {
val isAddAndManageTokensEnabled: Boolean
val isAddFundsStage1Enabled: Boolean
val isManageFundsEnabled: Boolean

View file

@ -20,30 +20,29 @@ android {
dependencies {
/** AndroidX */
implementation(deps.androidx.activity.compose)
implementation(deps.androidx.annotation)
implementation(deps.androidx.appCompat)
implementation(deps.lifecycle.compose)
implementation(deps.material)
/** Compose */
implementation(deps.compose.accompanist.systemUiController)
implementation(deps.compose.coil)
implementation(deps.compose.constraintLayout)
implementation(deps.compose.foundation)
api(deps.compose.coil)
api(deps.compose.foundation)
implementation(deps.compose.material3)
implementation(deps.compose.paging)
implementation(deps.compose.reorderable)
implementation(deps.compose.reorderableV2)
implementation(deps.compose.shimmer)
implementation(deps.compose.ui)
implementation(deps.compose.ui.tooling)
/** Other libraries */
api(deps.kotlin.coroutines)
api(deps.kotlin.immutable.collections)
api(deps.kotlin.serialization.core)
implementation(deps.arrow.core)
implementation(deps.decompose.ext.compose)
implementation(deps.googlePlay.review)
implementation(deps.jodatime)
implementation(deps.kotlin.immutable.collections)
implementation(tangemDeps.hot.core)
implementation(tangemDeps.card.core)
api(tangemDeps.card.core)
implementation(tangemDeps.blockchain)
implementation(deps.firebase.perf) {
exclude(group = "com.google.firebase", module = "protolite-well-known-types")
@ -54,116 +53,109 @@ dependencies {
exclude(module = "activity")
exclude(module = "activity-ktx")
}
implementation(deps.haze.materials) {
exclude(module = "activity-compose")
exclude(module = "activity")
exclude(module = "activity-ktx")
}
runtimeOnly(deps.material)
/** DI */
implementation(deps.hilt.android)
kapt(deps.hilt.kapt)
/** Core modules */
implementation(projects.core.configToggles)
implementation(projects.core.navigation)
implementation(projects.core.ui)
implementation(projects.core.utils)
implementation(projects.core.analytics)
implementation(projects.core.analytics.models)
implementation(projects.core.decompose)
implementation(projects.core.datasource)
api(projects.core.analytics)
api(projects.core.analytics.models)
api(projects.core.configToggles)
api(projects.core.datasource)
api(projects.core.decompose)
api(projects.core.navigation)
api(projects.core.ui)
api(projects.core.utils)
implementation(projects.core.res)
implementation(projects.core.error)
implementation(projects.libs.crypto)
implementation(projects.libs.blockchainSdk)
/** Domain modules */
implementation(projects.domain.account)
implementation(projects.domain.account.status)
implementation(projects.domain.analytics)
implementation(projects.domain.appCurrency)
api(projects.domain.account)
api(projects.domain.account.status)
api(projects.domain.addressBook)
api(projects.domain.analytics)
api(projects.domain.appCurrency)
api(projects.domain.appTheme)
api(projects.domain.assetsdiscovery)
api(projects.domain.balanceHiding)
api(projects.domain.card)
api(projects.domain.common)
api(projects.domain.demo)
api(projects.domain.feedback)
api(projects.domain.hotWallet)
api(projects.domain.legacy)
api(projects.domain.models)
api(projects.domain.networks)
api(projects.domain.nft)
api(projects.domain.notifications)
api(projects.domain.offramp)
api(projects.domain.onramp)
api(projects.domain.pushNotificationPreferences)
api(projects.domain.qrScanning)
api(projects.domain.quotes)
api(projects.domain.settings)
api(projects.domain.staking)
api(projects.domain.stories)
api(projects.domain.tokens)
api(projects.domain.tokens.models)
api(projects.domain.transaction)
api(projects.domain.txhistory)
api(projects.domain.visa)
api(projects.domain.walletConnect)
api(projects.domain.walletManager)
api(projects.domain.wallets)
api(projects.domain.wallets.models)
api(projects.domain.yieldSupply)
implementation(projects.domain.appCurrency.models)
implementation(projects.domain.balanceHiding)
implementation(projects.domain.balanceHiding.models)
implementation(projects.domain.card)
implementation(projects.domain.walletManager)
implementation(projects.domain.demo)
implementation(projects.domain.feedback)
implementation(projects.domain.feedback.models)
implementation(projects.domain.legacy)
implementation(projects.domain.markets.models)
implementation(projects.domain.models)
implementation(projects.domain.networks)
implementation(projects.domain.qrScanning)
implementation(projects.domain.qrScanning.models)
implementation(projects.domain.walletConnect)
implementation(projects.domain.walletConnect.models)
implementation(projects.domain.nft)
implementation(projects.domain.nft.models)
implementation(projects.domain.hotWallet)
implementation(projects.domain.offramp)
implementation(projects.domain.onramp)
implementation(projects.domain.onramp.models)
implementation(projects.domain.stories)
implementation(projects.domain.stories.models)
implementation(projects.domain.quotes)
implementation(projects.domain.settings)
implementation(projects.domain.staking)
implementation(projects.domain.staking.models)
implementation(projects.domain.tokens)
implementation(projects.domain.tokens.models)
implementation(projects.domain.txhistory)
implementation(projects.domain.txhistory.models)
implementation(projects.domain.visa)
implementation(projects.domain.wallets)
implementation(projects.domain.wallets.models)
implementation(projects.domain.notifications)
implementation(projects.domain.pushNotificationPreferences)
implementation(projects.domain.transaction)
implementation(projects.domain.yieldSupply)
implementation(projects.domain.yieldSupply.models)
implementation(projects.domain.appTheme)
implementation(projects.domain.appTheme.models)
implementation(projects.domain.assetsdiscovery)
implementation(projects.domain.balanceHiding.models)
implementation(projects.domain.core)
implementation(projects.domain.demo.models)
implementation(projects.domain.feedback.models)
implementation(projects.domain.marketing)
implementation(projects.domain.markets.models)
implementation(projects.domain.nft.models)
implementation(projects.domain.onramp.models)
implementation(projects.domain.qrScanning.models)
implementation(projects.domain.staking.models)
implementation(projects.domain.stories.models)
implementation(projects.domain.txhistory.models)
implementation(projects.domain.visa.models)
implementation(projects.domain.walletConnect.models)
implementation(projects.domain.yieldSupply.models)
/** Feature Apis */
implementation(projects.features.commonFeatures.api)
implementation(projects.features.account.api)
implementation(projects.features.details.api)
implementation(projects.features.hotWallet.api)
implementation(projects.features.manageTokens.api)
implementation(projects.features.markets.api)
implementation(projects.features.onboardingV2.api)
implementation(projects.features.onramp.api)
implementation(projects.features.pushNotifications.api)
implementation(projects.features.pushNotificationSettings.api)
implementation(projects.features.swap.api)
implementation(projects.features.tester.api)
implementation(projects.features.tokendetails.api)
implementation(projects.features.wallet.api)
implementation(projects.features.walletSettings.api)
implementation(projects.features.biometry.api)
implementation(projects.features.nft.api)
implementation(projects.features.send.api)
implementation(projects.features.kyc.api)
implementation(projects.features.tokenRecieve.api)
implementation(projects.features.yieldSupply.api)
implementation(projects.features.feed.api)
implementation(projects.features.promoBanners.api)
implementation(projects.features.tangempay.main.api)
implementation(projects.features.tangempay.details.api)
implementation(projects.features.virtualAccounts.main.api)
api(projects.features.addressBook.api)
api(projects.features.biometry.api)
api(projects.features.commonFeatures.api)
api(projects.features.feed.api)
api(projects.features.hotWallet.api)
api(projects.features.promoBanners.api)
api(projects.features.pushNotifications.api)
api(projects.features.pushNotificationSettings.api)
api(projects.features.send.api)
api(projects.features.tangempay.details.api)
api(projects.features.tangempay.main.api)
api(projects.features.tokenRecieve.api)
api(projects.features.virtualAccounts.main.api)
api(projects.features.wallet.api)
api(projects.features.walletSettings.api)
api(projects.features.yieldSupply.api)
/** Common modules */
api(projects.common.routing)
api(projects.common.ui)
implementation(projects.common)
implementation(projects.common.routing)
implementation(projects.common.ui)
/** Test libraries */
testImplementation(deps.test.junit5)
testImplementation(deps.test.coroutine)
testImplementation(deps.test.truth)
testImplementation(deps.test.mockk)
testImplementation(deps.kotlin.coroutines)
testImplementation(projects.domain.core)
}

View file

@ -16,6 +16,7 @@ import com.tangem.core.ui.utils.parseBigDecimal
import com.tangem.datasource.local.appsflyer.AppsFlyerStore
import com.tangem.domain.account.status.usecase.IsAccountsModeEnabledUseCase
import com.tangem.domain.account.supplier.SingleAccountListSupplier
import com.tangem.domain.addressbook.usecase.SyncAddressBooksUseCase
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.apptheme.GetAppThemeModeUseCase
@ -23,6 +24,7 @@ import com.tangem.domain.apptheme.model.AppThemeMode
import com.tangem.domain.assetsdiscovery.usecase.StartAssetsDiscoveryUseCase
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
import com.tangem.domain.common.wallets.UserWalletsListRepository
import com.tangem.domain.marketing.WarmUpMarketingCampaignsUseCase
import com.tangem.domain.models.wallet.*
import com.tangem.domain.notifications.GetIsHuaweiDeviceWithoutGoogleServicesUseCase
import com.tangem.domain.notifications.repository.NotificationsRepository
@ -60,6 +62,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.*
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.KycRejectedCallbacks
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
import com.tangem.features.addressbook.AddressBookFeatureToggles
import com.tangem.features.biometry.AskBiometryComponent
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks
@ -126,7 +129,10 @@ internal class WalletModel @Inject constructor(
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
private val walletFeatureToggles: WalletFeatureToggles,
private val pushNotificationSettingsFeatureToggles: PushNotificationSettingsFeatureToggles,
private val addressBookFeatureToggles: AddressBookFeatureToggles,
private val startAssetsDiscoveryUseCase: StartAssetsDiscoveryUseCase,
private val syncAddressBooksUseCase: SyncAddressBooksUseCase,
private val warmUpMarketingCampaignsUseCase: WarmUpMarketingCampaignsUseCase,
val screenLifecycleProvider: ScreenLifecycleProvider,
val innerWalletRouter: InnerWalletRouter,
) : Model() {
@ -151,6 +157,7 @@ internal class WalletModel @Inject constructor(
maybeMigrateNames()
maybeSetWalletFirstTimeUsage()
preloadPushNotificationPreferences()
warmUpMarketingCampaigns()
updateYieldSupplyApy()
subscribeToUserWalletsUpdates()
subscribeOnBalanceHiding()
@ -162,6 +169,7 @@ internal class WalletModel @Inject constructor(
subscribeToMainScreenQrScanning()
enableNotificationsIfNeeded()
applyPendingAssetsDiscovery()
syncAddressBooksIfNeeded()
clickIntents.initialize(innerWalletRouter, modelScope)
@ -198,6 +206,12 @@ internal class WalletModel @Inject constructor(
}
}
private fun warmUpMarketingCampaigns() {
modelScope.launch(dispatchers.io) {
warmUpMarketingCampaignsUseCase()
}
}
private fun preloadPushNotificationPreferences() {
if (!pushNotificationSettingsFeatureToggles.isPushNotificationSettingsEnabled) return
getWalletsUseCase()
@ -644,7 +658,9 @@ internal class WalletModel @Inject constructor(
}
private fun addWallet(action: WalletsUpdateActionResolver.Action.AddWallet) {
fetchWalletContent(userWallet = action.selectedWallet)
// Force update: a re-added wallet reuses the same id, so a stale (completed) fetch job from a previous
// session would otherwise make the fetcher skip loading, leaving the screen stuck on infinite loading.
fetchWalletContent(userWallet = action.selectedWallet, forceUpdate = true)
stateHolder.update(
AddWalletTransformer(
@ -767,7 +783,7 @@ internal class WalletModel @Inject constructor(
}
}
private fun fetchWalletContent(userWallet: UserWallet) {
private fun fetchWalletContent(userWallet: UserWallet, forceUpdate: Boolean = false) {
if (userWallet.isLocked) return
/*
@ -775,7 +791,7 @@ internal class WalletModel @Inject constructor(
* so the coroutine is launched in the current context
*/
modelScope.launch {
walletContentFetcher(userWalletId = userWallet.walletId)
walletContentFetcher(userWalletId = userWallet.walletId, forceUpdate = forceUpdate)
}
}
@ -877,7 +893,18 @@ internal class WalletModel @Inject constructor(
}
}
private fun syncAddressBooksIfNeeded() {
if (addressBookFeatureToggles.isAddressBookEnabled) {
modelScope.launch {
syncAddressBooksUseCase()
.onLeft { TangemLogger.e("Failed to sync address books: $it") }
}
}
}
private fun enableNotificationsIfNeeded() {
// New first-activation owns auto-enable when the feature is on; skip the legacy path.
if (pushNotificationSettingsFeatureToggles.isPushNotificationSettingsEnabled) return
modelScope.launch {
val isUserAllowToEnableNotifications = notificationsRepository.isUserAllowToSubscribeOnPushNotifications()
if (isUserAllowToEnableNotifications) {

View file

@ -42,6 +42,8 @@ internal interface TangemPayIntents {
fun openDetails(status: AccountStatus.Payment)
fun onSelectPlanClicked(status: AccountStatus.Payment)
fun onKycProgressClicked(userWalletId: UserWalletId)
fun onKycRejectedClicked(userWalletId: UserWalletId, customerId: String)
@ -114,6 +116,10 @@ internal class TangemPayClickIntentsImplementor @Inject constructor(
router.openTangemPayDetails(status = status)
}
override fun onSelectPlanClicked(status: AccountStatus.Payment) {
router.openTangemPaySelectPlan(status = status)
}
override fun onKycProgressClicked(userWalletId: UserWalletId) {
val cancelKycConfirmDialogMessage = DialogMessage(
title = resourceReference(R.string.tangempay_kyc_confirm_cancellation_alert_title),

View file

@ -37,7 +37,6 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.CloseBot
import com.tangem.feature.wallet.presentation.wallet.state.transformers.OpenBottomSheetTransformer
import com.tangem.feature.wallet.presentation.wallet.state.transformers.converter.MultiWalletCurrencyActionsConverter
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.flow.collectLatest
@ -114,7 +113,6 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
private val yieldSupplySetShouldShowMainPromoUseCase: YieldSupplySetShouldShowMainPromoUseCase,
private val tokenListAnalyticsSender: TokenListAnalyticsSender,
private val uiMessageSender: UiMessageSender,
private val walletFeatureToggles: WalletFeatureToggles,
) : BaseWalletClickIntents(), WalletContentClickIntents {
override fun onDetailsClick() {
@ -123,12 +121,8 @@ internal class WalletContentClickIntentsImplementor @Inject constructor(
override fun onOrganizeTokensClick() {
val userWalletId = stateHolder.getSelectedWalletId()
if (walletFeatureToggles.isAddAndManageTokensEnabled) {
analyticsEventHandler.send(PortfolioAnalyticsEvent.ButtonAddManage())
router.openAddAndManageBottomSheet(userWalletId = userWalletId)
} else {
router.openOrganizeTokensScreen(userWalletId = userWalletId)
}
analyticsEventHandler.send(PortfolioAnalyticsEvent.ButtonAddManage())
router.openAddAndManageBottomSheet(userWalletId = userWalletId)
}
override fun onDismissMarketsTooltip() {

View file

@ -43,6 +43,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
import com.tangem.features.pushnotifications.api.analytics.PushNotificationAnalyticEvents
import com.tangem.features.pushnotificationsettings.PushNotificationSettingsFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.logging.TangemLogger
import kotlinx.coroutines.async
@ -120,6 +121,7 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
private val notificationsRepository: NotificationsRepository,
private val setNotificationsEnabledUseCase: SetNotificationsEnabledUseCase,
private val getWalletsListForEnablingUseCase: GetWalletsForAutomaticallyPushEnablingUseCase,
private val pushNotificationSettingsFeatureToggles: PushNotificationSettingsFeatureToggles,
private val uiMessageSender: UiMessageSender,
private val reviewManager: ReviewManager,
private val closeHotWalletUpgradeBannerUseCase: CloseHotWalletUpgradeBannerUseCase,
@ -373,6 +375,8 @@ internal class WalletWarningsClickIntentsImplementor @Inject constructor(
}
private suspend fun enableNotificationsIfNeeded() {
// New first-activation owns auto-enable when the feature is on; skip the legacy path.
if (pushNotificationSettingsFeatureToggles.isPushNotificationSettingsEnabled) return
val alreadyEnabledWallets = notificationsRepository.getWalletAutomaticallyEnabledList().map {
UserWalletId(it)
}

View file

@ -9,9 +9,6 @@ internal class DefaultWalletFeatureToggles @Inject constructor(
private val featureToggles: FeatureTogglesManager,
) : WalletFeatureToggles {
override val isAddAndManageTokensEnabled: Boolean
get() = featureToggles.isFeatureEnabled(FeatureToggles.ADD_AND_MANAGE_TOKENS_ENABLED)
override val isAddFundsStage1Enabled: Boolean
get() = featureToggles.isFeatureEnabled(FeatureToggles.AND_15310_ADD_FUNDS_STAGE1)

View file

@ -158,6 +158,10 @@ internal class DefaultWalletRouter @Inject constructor(
router.push(AppRoute.TangemPayDetails(status = status))
}
override fun openTangemPaySelectPlan(status: AccountStatus.Payment) {
// TODO v_rodionov: [REDACTED_TASK_KEY] Tiers Onboarding - part 2
}
override fun openYieldSupplyBottomSheet(
cryptoCurrency: CryptoCurrency,
tokenAction: TokenAction,

View file

@ -84,6 +84,8 @@ internal interface InnerWalletRouter {
fun openTangemPayDetails(status: AccountStatus.Payment)
fun openTangemPaySelectPlan(status: AccountStatus.Payment)
/** Open BS abput yield supply active and all money deposited in AAVE */
fun openYieldSupplyBottomSheet(
cryptoCurrency: CryptoCurrency,

View file

@ -26,6 +26,8 @@ internal class WalletTangemPayAnalyticsEventSender @Inject constructor(
PaymentAccountStatusValue.Loading,
PaymentAccountStatusValue.NotCreated,
is PaymentAccountStatusValue.UnderReview,
is PaymentAccountStatusValue.AwaitingPlanSelection,
is PaymentAccountStatusValue.Inactive,
is PaymentAccountStatusValue.Deactivated,
-> return
}

View file

@ -39,7 +39,6 @@ import com.tangem.feature.wallet.presentation.account.AccountDependencies
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotification
import com.tangem.features.hotwallet.HotWalletFeatureToggles
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
import com.tangem.hot.sdk.model.HotWalletId
import com.tangem.lib.crypto.BlockchainUtils
import com.tangem.utils.annotations.RemoveWithToggle
@ -70,7 +69,6 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
private val shouldShowYieldBoostMainBannerUseCase: ShouldShowYieldBoostMainBannerUseCase,
private val yieldSupplyGetShouldShowMainPromoUseCase: YieldSupplyGetShouldShowMainPromoUseCase,
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
private val designFeatureToggles: DesignFeatureToggles,
private val walletFeatureToggles: WalletFeatureToggles,
) {
@ -208,7 +206,6 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
clickIntents: WalletClickIntents,
) {
if (!shouldShowLocal) return
if (!yieldSupplyFeatureToggles.isYieldPromoEnabled) return
if (designFeatureToggles.isRedesignEnabled) return
val shouldShow = shouldShowYieldBoostMainBannerUseCase(userWallet.walletId).getOrNull() == true
if (!shouldShow) return
@ -239,6 +236,8 @@ internal class GetMultiWalletWarningsFactory @Inject constructor(
is PaymentAccountStatusValue.Error.CardIssueFailed,
is PaymentAccountStatusValue.Error.ExposedDevice,
is PaymentAccountStatusValue.IssuingCard,
is PaymentAccountStatusValue.AwaitingPlanSelection,
is PaymentAccountStatusValue.Inactive,
is PaymentAccountStatusValue.Loaded,
is PaymentAccountStatusValue.Loading,
is PaymentAccountStatusValue.UnderReview,

View file

@ -15,7 +15,6 @@ import com.tangem.domain.yield.supply.promo.usecase.ShouldShowYieldBoostMainBann
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetShouldShowMainPromoUseCase
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotificationUM
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
import com.tangem.utils.extensions.addIf
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@ -38,7 +37,6 @@ internal class GetWalletNotificationsCarouselFactory @Inject constructor(
private val notificationsRepository: NotificationsRepository,
private val shouldShowYieldBoostMainBannerUseCase: ShouldShowYieldBoostMainBannerUseCase,
private val yieldSupplyGetShouldShowMainPromoUseCase: YieldSupplyGetShouldShowMainPromoUseCase,
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles,
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier,
) {
fun create(userWallet: UserWallet, clickIntents: WalletClickIntents): Flow<ImmutableList<WalletNotificationUM>> {
@ -86,7 +84,6 @@ internal class GetWalletNotificationsCarouselFactory @Inject constructor(
clickIntents: WalletClickIntents,
) {
if (!shouldShowLocal) return
if (!yieldSupplyFeatureToggles.isYieldPromoEnabled) return
val shouldShow = shouldShowYieldBoostMainBannerUseCase(userWallet.walletId).getOrNull() == true
if (!shouldShow) return
add(

View file

@ -284,6 +284,8 @@ internal class GetWalletNotificationsFactory @Inject constructor(
is PaymentAccountStatusValue.Error.CardIssueFailed,
is PaymentAccountStatusValue.Error.ExposedDevice,
is PaymentAccountStatusValue.IssuingCard,
is PaymentAccountStatusValue.AwaitingPlanSelection,
is PaymentAccountStatusValue.Inactive,
is PaymentAccountStatusValue.Loaded,
is PaymentAccountStatusValue.Loading,
is PaymentAccountStatusValue.UnderReview,

View file

@ -27,7 +27,6 @@ internal class SetTokenListTransformer(
private val shouldShowMainPromo: Boolean,
private val isAccountsModeEnabled: Boolean,
private val isRedesignEnabled: Boolean,
private val isAddAndManageTokensEnabled: Boolean,
private val isMultipleCardsEnabled: Boolean,
) : WalletStateTransformer(userWallet.walletId) {
@ -123,7 +122,6 @@ internal class SetTokenListTransformer(
yieldModuleApyMap = yieldSupplyApyMap,
stakingAvailabilityMap = stakingAvailabilityMap,
shouldShowMainPromo = shouldShowMainPromo,
isAddAndManageTokensEnabled = isAddAndManageTokensEnabled,
).convert(value = this)
}
@ -167,7 +165,6 @@ internal class SetTokenListTransformer(
shouldShowMainPromo = shouldShowMainPromo,
isAccountsModeEnabled = isAccountsModeEnabled,
expandedAccounts = params.expandedAccounts,
isAddAndManageTokensEnabled = isAddAndManageTokensEnabled,
).convert(value = params.accountList)
}
}

View file

@ -35,6 +35,12 @@ internal class TangemPayMainBlockConverter(
is PaymentAccountStatusValue.IssuingCard -> TangemPayMainUM.IssuingCard(
onClick = { tangemPayClickIntents.onIssuingCardClicked() },
)
is PaymentAccountStatusValue.AwaitingPlanSelection -> TangemPayMainUM.SelectPlan(
onClick = { tangemPayClickIntents.onSelectPlanClicked(value) },
)
is PaymentAccountStatusValue.Inactive -> TangemPayMainUM.IssuingCard(
onClick = { tangemPayClickIntents.openDetails(value) },
)
is PaymentAccountStatusValue.UnderReview -> TangemPayMainUM.UnderReview(
subtitle = when (statusValue.kycStatus) {
KycStatus.REJECTED -> TextReference.Res(R.string.tangempay_kyc_has_failed)

View file

@ -8,7 +8,6 @@ import com.tangem.core.ui.components.tokenlist.state.PortfolioTokensListItemUM
import com.tangem.core.ui.components.tokenlist.state.TokensListItemUM
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.account.models.AccountStatusList
import com.tangem.domain.account.models.hasMultiCurrencyAccount
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.card.common.util.cardTypesResolver
import com.tangem.domain.models.TotalFiatBalance
@ -42,7 +41,6 @@ internal class TokenListStateConverter(
private val yieldModuleApyMap: Map<String, BigDecimal>,
private val stakingAvailabilityMap: Map<CryptoCurrency, StakingAvailability>,
shouldShowMainPromo: Boolean,
private val isAddAndManageTokensEnabled: Boolean,
) : Converter<WalletTokensListState, WalletTokensListState> {
private val yieldSupplyPromoBannerConverter = YieldSupplyPromoBannerConverter(
@ -170,8 +168,7 @@ internal class TokenListStateConverter(
}
private fun getOrganizeTokensButtonStateV2(accountList: AccountStatusList): WalletOrganizeTokensButtonConfig? {
val shouldShowOrganizeIfOldButton = accountList.hasMultiCurrencyAccount() || isAddAndManageTokensEnabled
return if (shouldShowOrganizeIfOldButton && !isSingleCurrencyWalletWithToken()) {
return if (!isSingleCurrencyWalletWithToken()) {
WalletOrganizeTokensButtonConfig(
textRes = organizeButtonTextRes(),
iconRes = organizeButtonIconRes(),
@ -183,17 +180,9 @@ internal class TokenListStateConverter(
}
}
private fun organizeButtonTextRes(): Int = if (isAddAndManageTokensEnabled) {
R.string.main_add_and_manage_tokens
} else {
R.string.organize_tokens_title
}
private fun organizeButtonTextRes(): Int = R.string.main_add_and_manage_tokens
private fun organizeButtonIconRes(): Int = if (isAddAndManageTokensEnabled) {
R.drawable.ic_filter_default_24
} else {
R.drawable.ic_filter_24
}
private fun organizeButtonIconRes(): Int = R.drawable.ic_filter_default_24
private fun isSingleCurrencyWalletWithToken(): Boolean {
return selectedWallet is UserWallet.Cold &&

View file

@ -38,7 +38,6 @@ internal class WalletTokensListUMConverter(
private val isAccountsModeEnabled: Boolean,
private val expandedAccounts: Set<AccountId>,
private val stakingAvailabilityMap: Map<CryptoCurrency, StakingAvailability>,
private val isAddAndManageTokensEnabled: Boolean,
shouldShowMainPromo: Boolean,
) : Converter<AccountStatusList, WalletTokensListUM> {
@ -161,16 +160,8 @@ internal class WalletTokensListUMConverter(
}
private fun getOrganizeButtonUM(accountList: AccountStatusList): TangemButtonUM? {
val textRes = if (isAddAndManageTokensEnabled) {
R.string.main_add_and_manage_tokens
} else {
R.string.organize_tokens_title
}
val iconRes = if (isAddAndManageTokensEnabled) {
R.drawable.ic_filter_default_24
} else {
R.drawable.ic_filter_24
}
val textRes = R.string.main_add_and_manage_tokens
val iconRes = R.drawable.ic_filter_default_24
return if (accountList.flattenCurrencies().isNotEmpty() && !selectedWallet.isSingleCurrency()) {
TangemButtonUM(
text = resourceReference(textRes),

View file

@ -13,7 +13,6 @@ import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.account.AccountDependencies
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.features.tangempay.TangemPayFeatureToggles
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import com.tangem.utils.coroutines.combine7
import com.tangem.utils.logging.TangemLogger
import dagger.assisted.Assisted
@ -39,13 +38,9 @@ internal class AccountListSubscriber @AssistedInject constructor(
private val stakingAvailabilityListUseCase: StakingAvailabilityListUseCase,
private val yieldSupplyGetShouldShowMainPromoUseCase: YieldSupplyGetShouldShowMainPromoUseCase,
private val designFeatureToggles: DesignFeatureToggles,
private val walletFeatureToggles: WalletFeatureToggles,
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
) : BasicAccountListSubscriber() {
override val isAddAndManageTokensEnabled: Boolean
get() = walletFeatureToggles.isAddAndManageTokensEnabled
override fun create(coroutineScope: CoroutineScope): Flow<*> {
val walletId = userWallet.walletId.stringValue
TangemLogger.i("$TAG[$walletId]: create() called, building combine7")

View file

@ -34,7 +34,6 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
abstract val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase
abstract val stateController: WalletStateController
abstract val clickIntents: WalletClickIntents
abstract val isAddAndManageTokensEnabled: Boolean
override val singleAccountStatusListSupplier: SingleAccountStatusListSupplier
get() = accountDependencies.singleAccountStatusListSupplier
@ -107,7 +106,6 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
shouldShowMainPromo = shouldShowMainPromo,
isAccountsModeEnabled = isAccountMode,
isRedesignEnabled = true,
isAddAndManageTokensEnabled = isAddAndManageTokensEnabled,
isMultipleCardsEnabled = isMultipleCardsEnabled,
),
)
@ -172,7 +170,6 @@ internal abstract class BasicAccountListSubscriber : BasicWalletSubscriber() {
shouldShowMainPromo = shouldShowMainPromo,
isAccountsModeEnabled = false,
isRedesignEnabled = false,
isAddAndManageTokensEnabled = isAddAndManageTokensEnabled,
isMultipleCardsEnabled = false,
),
)

View file

@ -6,7 +6,6 @@ import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.account.AccountDependencies
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.features.tangempay.TangemPayFeatureToggles
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@ -22,13 +21,9 @@ internal class SingleWalletSubscriber @AssistedInject constructor(
override val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
override val stateController: WalletStateController,
override val clickIntents: WalletClickIntents,
private val walletFeatureToggles: WalletFeatureToggles,
private val tangemPayFeatureToggles: TangemPayFeatureToggles,
) : BasicAccountListSubscriber() {
override val isAddAndManageTokensEnabled: Boolean
get() = walletFeatureToggles.isAddAndManageTokensEnabled
override fun create(coroutineScope: CoroutineScope): Flow<Unit> = combine(
flow = getAccountStatusListFlow(),
flow2 = getAppCurrencyFlow(),

View file

@ -5,7 +5,6 @@ import com.tangem.domain.models.wallet.UserWallet
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.account.AccountDependencies
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import com.tangem.utils.annotations.RemoveWithToggle
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
@ -22,12 +21,8 @@ internal class SingleWalletWithTokenSubscriberLegacy @AssistedInject constructor
override val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
override val stateController: WalletStateController,
override val clickIntents: WalletClickIntents,
private val walletFeatureToggles: WalletFeatureToggles,
) : BasicAccountListSubscriber() {
override val isAddAndManageTokensEnabled: Boolean
get() = walletFeatureToggles.isAddAndManageTokensEnabled
override fun create(coroutineScope: CoroutineScope): Flow<Unit> = combine(
flow = getAccountStatusListFlow(),
flow2 = getAppCurrencyFlow(),

View file

@ -74,7 +74,6 @@ class SetTokenListTransformerTest {
shouldShowMainPromo = false,
isAccountsModeEnabled = false,
isRedesignEnabled = true,
isAddAndManageTokensEnabled = false,
isMultipleCardsEnabled = false,
)
}

View file

@ -6,7 +6,6 @@ import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import io.mockk.every
import io.mockk.mockk
import io.mockk.slot
@ -21,7 +20,6 @@ internal class WalletContentClickIntentsAnalyticsTest {
private val stateHolder: WalletStateController = mockk(relaxed = true)
private val analyticsEventHandler: AnalyticsEventHandler = mockk(relaxed = true)
private val walletFeatureToggles: WalletFeatureToggles = mockk(relaxed = true)
private val router: InnerWalletRouter = mockk(relaxed = true)
private val userWalletId = UserWalletId(stringValue = "0123456789ABCDEF")
@ -45,16 +43,14 @@ internal class WalletContentClickIntentsAnalyticsTest {
yieldSupplySetShouldShowMainPromoUseCase = mockk(relaxed = true),
tokenListAnalyticsSender = mockk(relaxed = true),
uiMessageSender = mockk(relaxed = true),
walletFeatureToggles = walletFeatureToggles,
)
implementor.initialize(router = router, coroutineScope = TestScope())
return implementor
}
@Test
fun `GIVEN add and manage toggle enabled WHEN onOrganizeTokensClick THEN sends ButtonAddManage event and opens bottom sheet`() =
fun `WHEN onOrganizeTokensClick THEN sends ButtonAddManage event and opens bottom sheet`() =
runTest {
every { walletFeatureToggles.isAddAndManageTokensEnabled } returns true
val implementor = createImplementor()
val captured = slot<AnalyticsEvent>()
@ -67,17 +63,4 @@ internal class WalletContentClickIntentsAnalyticsTest {
verify(exactly = 1) { router.openAddAndManageBottomSheet(userWalletId = userWalletId) }
verify(exactly = 0) { router.openOrganizeTokensScreen(any()) }
}
@Test
fun `GIVEN add and manage toggle disabled WHEN onOrganizeTokensClick THEN does not send analytics and opens organize screen`() =
runTest {
every { walletFeatureToggles.isAddAndManageTokensEnabled } returns false
val implementor = createImplementor()
implementor.onOrganizeTokensClick()
verify(exactly = 0) { analyticsEventHandler.send(any<AnalyticsEvent>()) }
verify(exactly = 1) { router.openOrganizeTokensScreen(userWalletId = userWalletId) }
verify(exactly = 0) { router.openAddAndManageBottomSheet(any()) }
}
}

View file

@ -24,8 +24,8 @@ import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.networks.multi.MultiNetworkStatusSupplier
import com.tangem.domain.tokens.MultiWalletCryptoCurrenciesSupplier
import com.tangem.domain.wallets.PromoCodeActivationResult
import com.tangem.domain.wallets.models.GetUserWalletError
import com.tangem.domain.wallets.models.errors.ActivatePromoCodeError
import com.tangem.domain.wallets.models.errors.GetUserWalletError
import com.tangem.domain.wallets.usecase.ActivateBitcoinPromocodeUseCase
import com.tangem.domain.wallets.usecase.BindRefcodeWithWalletUseCase
import com.tangem.domain.wallets.usecase.GetSelectedWalletSyncUseCase
@ -82,7 +82,6 @@ class DefaultPromoDeeplinkHandlerTest {
every { analyticsEventHandler.send(any()) } returns Unit
messages = mutableListOf()
every { uiMessageSender.send(capture(messages)) } just runs
}
@Test
@ -499,13 +498,21 @@ class DefaultPromoDeeplinkHandlerTest {
)
coEvery { multiNetworkStatusSupplier.invoke(any()) } returns flowOf(setOf(btcStatusCard, btcStatusCustom))
val btcCoinCustom = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
val btcCoinCard = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
val btcCoinCustom =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
val btcCoinCard =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
coEvery { multiWalletCryptoCurrenciesSupplier.getSyncOrNull(any()) } returns setOf(
btcCoinCustom,
btcCoinCard,
)
coEvery { activateBitcoinPromocodeUseCase.invoke(any(), "bc1qcustom", promoCode) } returns Either.Right("ok")
coEvery {
activateBitcoinPromocodeUseCase.invoke(
any(),
"bc1qcustom",
promoCode
)
} returns Either.Right("ok")
val dispatcherProvider = testDispatcherProvider(testScheduler)
@ -556,7 +563,8 @@ class DefaultPromoDeeplinkHandlerTest {
)
coEvery { multiNetworkStatusSupplier.invoke(any()) } returns flowOf(setOf(btcStatusCard, btcStatusCustom))
val btcCoinCard = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
val btcCoinCard =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
coEvery { multiWalletCryptoCurrenciesSupplier.getSyncOrNull(any()) } returns setOf(btcCoinCard)
coEvery { activateBitcoinPromocodeUseCase.invoke(any(), "bc1qcard", promoCode) } returns Either.Right("ok")
@ -643,7 +651,7 @@ class DefaultPromoDeeplinkHandlerTest {
Truth.assertThat(sent.title).isEqualTo(resourceReference(R.string.bitcoin_promo_no_address_title))
Truth.assertThat(sent.message).isEqualTo(resourceReference(R.string.bitcoin_promo_no_address))
coVerify(exactly = 0) { activateBitcoinPromocodeUseCase.invoke(any(),any(), any()) }
coVerify(exactly = 0) { activateBitcoinPromocodeUseCase.invoke(any(), any(), any()) }
verify(
exactly = 1,
@ -673,8 +681,10 @@ class DefaultPromoDeeplinkHandlerTest {
)
coEvery { multiNetworkStatusSupplier.invoke(any()) } returns flowOf(setOf(btcStatusCard))
val btcCoinCustom = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
val btcCoinCard = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
val btcCoinCustom =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
val btcCoinCard =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
coEvery { multiWalletCryptoCurrenciesSupplier.getSyncOrNull(any()) } returns setOf(
btcCoinCustom,
btcCoinCard,
@ -732,7 +742,8 @@ class DefaultPromoDeeplinkHandlerTest {
)
coEvery { multiNetworkStatusSupplier.invoke(any()) } returns flowOf(setOf(btcStatusCustom))
val btcCoinCard = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
val btcCoinCard =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCard)
coEvery { multiWalletCryptoCurrenciesSupplier.getSyncOrNull(any()) } returns setOf(btcCoinCard)
val dispatcherProvider = testDispatcherProvider(testScheduler)
@ -787,7 +798,8 @@ class DefaultPromoDeeplinkHandlerTest {
)
coEvery { multiNetworkStatusSupplier.invoke(any()) } returns flowOf(setOf(btcStatusCard))
val btcCoinCustom = buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
val btcCoinCustom =
buildCryptoCurrency(rawNetworkId = Blockchain.Bitcoin.toNetworkId(), derivationPath = dpCustom)
coEvery { multiWalletCryptoCurrenciesSupplier.getSyncOrNull(any()) } returns setOf(btcCoinCustom)
val dispatcherProvider = testDispatcherProvider(testScheduler)

View file

@ -21,7 +21,6 @@ import com.tangem.domain.yield.supply.promo.usecase.ShouldShowYieldBoostMainBann
import com.tangem.domain.yield.supply.usecase.YieldSupplyGetShouldShowMainPromoUseCase
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletNotificationUM
import com.tangem.features.yield.supply.api.YieldSupplyFeatureToggles
import io.mockk.clearMocks
import io.mockk.coEvery
import io.mockk.every
@ -48,7 +47,6 @@ internal class GetWalletNotificationsCarouselFactoryTest {
private val notificationsRepository: NotificationsRepository = mockk()
private val shouldShowYieldBoostMainBannerUseCase: ShouldShowYieldBoostMainBannerUseCase = mockk()
private val yieldSupplyGetShouldShowMainPromoUseCase: YieldSupplyGetShouldShowMainPromoUseCase = mockk()
private val yieldSupplyFeatureToggles: YieldSupplyFeatureToggles = mockk()
private val singleAccountStatusListSupplier: SingleAccountStatusListSupplier = mockk(relaxed = true)
private val clickIntents: WalletClickIntents = mockk(relaxed = true)
private val userWallet: UserWallet.Hot = mockk(relaxed = true)
@ -59,7 +57,6 @@ internal class GetWalletNotificationsCarouselFactoryTest {
notificationsRepository = notificationsRepository,
shouldShowYieldBoostMainBannerUseCase = shouldShowYieldBoostMainBannerUseCase,
yieldSupplyGetShouldShowMainPromoUseCase = yieldSupplyGetShouldShowMainPromoUseCase,
yieldSupplyFeatureToggles = yieldSupplyFeatureToggles,
singleAccountStatusListSupplier = singleAccountStatusListSupplier,
)
@ -71,7 +68,6 @@ internal class GetWalletNotificationsCarouselFactoryTest {
notificationsRepository,
shouldShowYieldBoostMainBannerUseCase,
yieldSupplyGetShouldShowMainPromoUseCase,
yieldSupplyFeatureToggles,
singleAccountStatusListSupplier,
clickIntents,
userWallet,
@ -83,7 +79,6 @@ internal class GetWalletNotificationsCarouselFactoryTest {
every { isReadyToShowRateAppUseCase() } returns flowOf(false)
every { getWalletsUseCase() } returns flowOf(emptyList())
every { yieldSupplyGetShouldShowMainPromoUseCase() } returns flowOf(true)
every { yieldSupplyFeatureToggles.isYieldPromoEnabled } returns true
coEvery { shouldShowYieldBoostMainBannerUseCase(any()) } returns Either.Right(true)
// Balance is loaded by default, so banners gated on balance are not suppressed.
every {
@ -100,7 +95,6 @@ internal class GetWalletNotificationsCarouselFactoryTest {
@MethodSource("provideTestModels")
fun `GIVEN gating conditions WHEN create THEN yield boost banner visibility matches`(model: Model) = runTest {
// Arrange
every { yieldSupplyFeatureToggles.isYieldPromoEnabled } returns model.toggleEnabled
every { yieldSupplyGetShouldShowMainPromoUseCase() } returns flowOf(model.shouldShowLocal)
coEvery { shouldShowYieldBoostMainBannerUseCase(WALLET_ID) } returns model.mainBanner
@ -206,19 +200,16 @@ internal class GetWalletNotificationsCarouselFactoryTest {
)
internal data class Model(
val toggleEnabled: Boolean,
val shouldShowLocal: Boolean,
val mainBanner: Either<Throwable, Boolean>,
val expectedShown: Boolean,
)
private fun provideTestModels() = listOf(
Model(toggleEnabled = true, shouldShowLocal = true, mainBanner = Either.Right(true), expectedShown = true),
Model(toggleEnabled = false, shouldShowLocal = true, mainBanner = Either.Right(true), expectedShown = false),
Model(toggleEnabled = true, shouldShowLocal = false, mainBanner = Either.Right(true), expectedShown = false),
Model(toggleEnabled = true, shouldShowLocal = true, mainBanner = Either.Right(false), expectedShown = false),
Model(shouldShowLocal = true, mainBanner = Either.Right(true), expectedShown = true),
Model(shouldShowLocal = false, mainBanner = Either.Right(true), expectedShown = false),
Model(shouldShowLocal = true, mainBanner = Either.Right(false), expectedShown = false),
Model(
toggleEnabled = true,
shouldShowLocal = true,
mainBanner = Either.Left(RuntimeException("boom")),
expectedShown = false,

View file

@ -67,7 +67,6 @@ internal class WalletTokensListUMConverterTest {
isAccountsModeEnabled = false,
expandedAccounts = emptySet(),
stakingAvailabilityMap = emptyMap(),
isAddAndManageTokensEnabled = true,
shouldShowMainPromo = false,
)