From 27b2bfbbc9951ce2a5310a4b0d92caef732a0498 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Sun, 27 Sep 2026 11:35:07 -0400 Subject: [PATCH] fix(tokens): don't gate Convert on holding a second currency Tapping Convert on the currency info screen showed "No Balance Yet" unless the user also held a displayable balance in some other currency. A user with $11.04 of Moony and no USDF couldn't convert it. Converting only spends the source currency; SwapViewModel resolves a destination the user doesn't hold through its token metadata. iOS opens the Convert flow without a check, and both platforms already show the tile only for a held currency, so drop the check. canSell had no other caller and goes with it. --- .../app/tokens/ui/TokenInfoViewModel.kt | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/TokenInfoViewModel.kt b/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/TokenInfoViewModel.kt index 23bcc6f29a..6899611489 100644 --- a/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/TokenInfoViewModel.kt +++ b/apps/flipcash/shared/tokens/src/main/kotlin/com/flipcash/app/tokens/ui/TokenInfoViewModel.kt @@ -72,9 +72,6 @@ class TokenInfoViewModel @Inject constructor( /** Bounded per-token recent activity preview (newest first) for the v2 currency-info screen. */ val transactions: List = emptyList(), ) { - val canSell: Boolean - get() = balance.underlyingTokenAmount.valueNonZero() - /** True when the user holds a displayable balance in some token other than [mint], which could fund a buy of it. */ val hasFundableBalance: Boolean get() = fundableBalanceMints.any { it != mint } @@ -331,23 +328,8 @@ class TokenInfoViewModel @Inject constructor( .filterIsInstance() .onEach { val mint = stateFlow.value.mint ?: return@onEach - // Converting spends this currency and lands in another, so it needs both a - // balance here and somewhere for it to go. - if (!stateFlow.value.canSell || !stateFlow.value.hasFundableBalance) { - BottomBarManager.showInfo( - title = resources.getString(R.string.title_noBalanceYet), - message = resources.getString(R.string.description_noBalanceYetToBuy), - actions = listOf( - BottomBarAction( - text = resources.getString(R.string.action_addMoney) - ) { - dispatchEvent(Event.PresentDepositOptions) - }, - ), - showCancel = true, - ) - return@onEach - } + // No gate, matching iOS: the tile only shows for a held currency, and the + // destination needs no balance of its own. // Dollars is the default landing spot; when Dollars *is* the source the swap // view model substitutes the user's largest other holding.