Skip to content

Commit ccccc58

Browse files
committed
chore: label cash reserves as USD Reserves; sort to the bottom when visible in lists
Signed-off-by: Brandon McAnsh <[email protected]>
1 parent f78447c commit ccccc58

File tree

10 files changed

+68
-40
lines changed

10 files changed

+68
-40
lines changed

apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/TokenBalanceRow.kt

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,25 @@ fun TokenBalanceRow(
5252
modifier: Modifier = Modifier,
5353
showName: Boolean = true,
5454
showFlag: Boolean = false,
55+
showLogo: Boolean = true,
5556
isSelected: Boolean? = null,
5657
formattedBalance: (Fiat) -> String = { it.formatted() },
5758
horizontalArrangement: Arrangement.Horizontal = Arrangement.SpaceBetween,
5859
sizing: TokenBalanceRowSizing = rememberTokenBalanceRowSizing(),
5960
contentPadding: PaddingValues = PaddingValues(vertical = CodeTheme.dimens.inset),
6061
onClick: (() -> Unit)? = null,
6162
) {
62-
val (token, balance) = tokenWithBalance
63+
val (token, balance, displayName) = tokenWithBalance
6364
TokenBalanceRow(
6465
token = token,
66+
displayName = displayName,
6567
balance = balance.nativeAmount,
6668
formattedBalance = formattedBalance,
6769
isSelected = isSelected,
6870
modifier = modifier,
6971
showName = showName,
7072
showFlag = showFlag,
73+
showLogo = showLogo,
7174
sizing = sizing,
7275
horizontalArrangement = horizontalArrangement,
7376
contentPadding = contentPadding,
@@ -89,9 +92,10 @@ fun TokenBalanceRow(
8992
contentPadding: PaddingValues = PaddingValues(vertical = CodeTheme.dimens.inset),
9093
onClick: (() -> Unit)? = null,
9194
) {
92-
val (token, balance) = tokenWithBalance
95+
val (token, balance, displayName) = tokenWithBalance
9396
TokenBalanceRow(
9497
token = token,
98+
displayName = displayName,
9599
balance = balance,
96100
showName = showName,
97101
showLogo = showLogo,
@@ -112,6 +116,7 @@ fun TokenBalanceRow(
112116
token: Token,
113117
balance: Fiat,
114118
modifier: Modifier = Modifier,
119+
displayName: String = token.name,
115120
showName: Boolean = true,
116121
showLogo: Boolean = true,
117122
showFlag: Boolean = false,
@@ -139,6 +144,7 @@ fun TokenBalanceRow(
139144
showLogo && showName -> {
140145
TokenIconWithName(
141146
token = token,
147+
displayName = { displayName },
142148
imageSize = sizing.iconSize,
143149
textStyle = sizing.nameTextStyle,
144150
textColor = CodeTheme.colors.textMain,
@@ -147,12 +153,10 @@ fun TokenBalanceRow(
147153
}
148154

149155
showName -> {
150-
TokenIconWithName(
151-
token = token,
152-
imageSize = sizing.iconSize,
153-
textStyle = sizing.nameTextStyle,
154-
textColor = CodeTheme.colors.textMain,
155-
spacing = CodeTheme.dimens.grid.x2,
156+
Text(
157+
text = displayName,
158+
style = sizing.nameTextStyle,
159+
color = CodeTheme.colors.textMain,
156160
)
157161
}
158162

apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/ui/TokenImageWithName.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ import com.getcode.ui.components.R
2525
fun TokenIconWithName(
2626
token: Token,
2727
imageSize: Dp,
28+
modifier: Modifier = Modifier,
29+
displayName: (Token) -> String = { it.name },
2830
textStyle: TextStyle = CodeTheme.typography.screenTitle,
2931
textColor: Color = CodeTheme.colors.textMain,
30-
modifier: Modifier = Modifier,
3132
spacing: Dp = 0.dp,
3233
) {
3334
Row(
@@ -40,7 +41,7 @@ fun TokenIconWithName(
4041
modifier = Modifier.size(imageSize)
4142
)
4243
Text(
43-
text = token.name,
44+
text = displayName(token),
4445
style = textStyle,
4546
color = textColor,
4647
)

apps/flipcash/core/src/main/res/values/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@
451451
<string name="label_blendModeColorDodge">Color Dodge</string>
452452
<string name="label_blendModePlusLighter">Plus Lighter</string>
453453

454-
<string name="title_cashReserves">Cash Reserves</string>
454+
<string name="title_cashReserves">USD Reserves</string>
455455
<string name="action_buyMore">Buy More</string>
456456
<string name="description_cashReserves">
457457
Your cash reserves are held in USDC, a fully backed digital dollar supported 1:1 by U.S. dollars. This ensures your funds retain the same value and stability as traditional USD, while benefiting from faster, more transparent transactions on modern financial infrastructure. You can deposit additional funds at any time, or withdraw your USDC for U.S. dollars whenever you like.

apps/flipcash/features/balance/src/main/kotlin/com/flipcash/app/balance/internal/BalanceScreenContent.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ private fun BalanceScreenContent(
121121
) {
122122
Text(
123123
text = stringResource(R.string.title_cashReserves),
124-
style = CodeTheme.typography.textMedium,
125-
color = CodeTheme.colors.textSecondary,
124+
style = CodeTheme.typography.screenTitle,
125+
color = CodeTheme.colors.textMain,
126126
)
127127

128128
Icon(
@@ -131,7 +131,7 @@ private fun BalanceScreenContent(
131131
.padding(start = CodeTheme.dimens.grid.x1),
132132
painter = painterResource(id = R.drawable.ic_chevron_right),
133133
contentDescription = null,
134-
tint = CodeTheme.colors.secondary,
134+
tint = CodeTheme.colors.textMain,
135135
)
136136

137137
Spacer(Modifier.weight(1f))

apps/flipcash/features/tokens/src/main/kotlin/com/flipcash/app/tokens/internal/TokenInfoScreen.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,11 @@ private fun BottomBar(state: TokenInfoViewModel.State, dispatch: (TokenInfoViewM
175175
CodeButton(
176176
modifier = Modifier.weight(1f),
177177
buttonState = ButtonState.FilledGreen,
178-
text = stringResource(R.string.action_buyMore),
178+
text = stringResource(R.string.action_withdraw),
179179
) {
180180
dispatch(
181181
TokenInfoViewModel.Event.OpenScreen(
182-
AppRoute.OnRamp.ProviderList(from = AppRoute.Token.Info(state.mint!!))
182+
AppRoute.Transfers.Withdrawal.Amount(state.mint!!)
183183
)
184184
)
185185
}

apps/flipcash/shared/tokens/src/main/kotlin/SelectTokenViewModel.kt

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@ import com.flipcash.services.internal.model.thirdparty.OnRampProvider
1111
import com.flipcash.services.internal.model.thirdparty.OnRampType
1212
import com.flipcash.services.user.AuthState
1313
import com.flipcash.services.user.UserManager
14+
import com.flipcash.shared.tokens.R
1415
import com.getcode.opencode.controllers.TokenController
1516
import com.getcode.opencode.exchange.Exchange
1617
import com.getcode.opencode.model.financial.Fiat
1718
import com.getcode.opencode.model.financial.LocalFiat
18-
import com.getcode.opencode.model.financial.Token
1919
import com.getcode.opencode.model.financial.TokenWithLocalizedBalance
2020
import com.getcode.opencode.model.financial.sum
2121
import com.getcode.opencode.model.financial.toFiat
2222
import com.getcode.solana.keys.Mint
23+
import com.getcode.util.resources.ResourceHelper
2324
import com.getcode.view.BaseViewModel2
2425
import dagger.hilt.android.lifecycle.HiltViewModel
2526
import kotlinx.coroutines.flow.combine
@@ -41,7 +42,8 @@ class SelectTokenViewModel @Inject constructor(
4142
exchange: Exchange,
4243
analytics: FlipcashAnalyticsService,
4344
featureFlags: FeatureFlagController,
44-
): BaseViewModel2<SelectTokenViewModel.State, SelectTokenViewModel.Event>(
45+
resources: ResourceHelper,
46+
) : BaseViewModel2<SelectTokenViewModel.State, SelectTokenViewModel.Event>(
4547
initialState = State(purpose = TokenPurpose.Balance),
4648
updateStateForEvent = updateStateForEvent
4749
) {
@@ -59,18 +61,18 @@ class SelectTokenViewModel @Inject constructor(
5961

6062
sealed interface Event {
6163
data class OnPreferredOnRampProviderChanged(val provider: OnRampProvider?) : Event
62-
data class OnReservesEnabled(val enabled: Boolean): Event
64+
data class OnReservesEnabled(val enabled: Boolean) : Event
6365

6466
data class OnPurposeChanged(val purpose: TokenPurpose) : Event
6567
data class OnTokensUpdated(val tokens: List<TokenWithLocalizedBalance>) : Event
6668

67-
data class OnTokenSelected(val mint: Mint, val fromUser: Boolean = true): Event
69+
data class OnTokenSelected(val mint: Mint, val fromUser: Boolean = true) : Event
6870

69-
data object OnTokenChanged: Event
71+
data object OnTokenChanged : Event
7072

71-
data object OnAddCashClicked: Event
72-
data object OpenOnRampAmountModal: Event
73-
data class OpenScreen(val route: AppRoute): Event
73+
data object OnAddCashClicked : Event
74+
data object OpenOnRampAmountModal : Event
75+
data class OpenScreen(val route: AppRoute) : Event
7476
}
7577

7678
init {
@@ -101,15 +103,25 @@ class SelectTokenViewModel @Inject constructor(
101103
TokenPurpose.Deposit -> exchange.observeEntryRate()
102104
}
103105
) { state, balances, rate ->
104-
balances.map {
105-
TokenWithLocalizedBalance(
106-
token = it.token,
107-
balance = LocalFiat(
108-
usdc = it.balance,
109-
nativeAmount = it.balance.convertingTo(rate),
106+
balances
107+
.map {
108+
TokenWithLocalizedBalance(
109+
token = it.token,
110+
displayName = if (it.token.address == Mint.usdc) {
111+
resources.getString(R.string.title_cashReserves)
112+
} else {
113+
it.token.name
114+
},
115+
balance = LocalFiat(
116+
usdc = it.balance,
117+
nativeAmount = it.balance.convertingTo(rate),
118+
)
110119
)
111-
)
112-
}.sortedByDescending { it.balance.nativeAmount }
120+
}
121+
.sortedWith(compareByDescending<TokenWithLocalizedBalance> { item ->
122+
if (state.reservesEnabled && item.isReserves) Fiat.MIN_VALUE
123+
else item.balance.nativeAmount
124+
})
113125
.filter {
114126
val baselineAmount = 0.01.toFiat(rate.currency)
115127
when (purpose) {
@@ -163,9 +175,11 @@ class SelectTokenViewModel @Inject constructor(
163175
is Event.OnPreferredOnRampProviderChanged -> { state ->
164176
state.copy(preferredOnRampProvider = event.provider)
165177
}
178+
166179
is Event.OnReservesEnabled -> { state ->
167180
state.copy(reservesEnabled = event.enabled)
168181
}
182+
169183
is Event.OnPurposeChanged -> { state -> state.copy(purpose = event.purpose) }
170184
is Event.OnTokensUpdated -> { state -> state.copy(tokens = event.tokens) }
171185
is Event.OnTokenSelected -> { state -> state.copy(selectedToken = event.mint) }

apps/flipcash/shared/tokens/src/main/kotlin/TokenInfoViewModel.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,23 @@ import androidx.compose.ui.Alignment
1010
import androidx.compose.ui.Modifier
1111
import androidx.compose.ui.graphics.Color
1212
import androidx.compose.ui.graphics.ColorFilter
13-
import androidx.compose.ui.graphics.painter.Painter
1413
import androidx.compose.ui.res.painterResource
15-
import androidx.compose.ui.res.stringResource
1614
import androidx.compose.ui.text.Placeholder
1715
import androidx.compose.ui.text.PlaceholderVerticalAlign
1816
import androidx.compose.ui.text.buildAnnotatedString
1917
import androidx.compose.ui.unit.dp
2018
import androidx.compose.ui.unit.sp
2119
import androidx.lifecycle.viewModelScope
22-
import cafe.adriel.voyager.core.registry.ScreenRegistry
2320
import com.flipcash.app.core.AppRoute
2421
import com.flipcash.app.core.extensions.onResult
2522
import com.flipcash.app.core.money.formatted
2623
import com.flipcash.app.core.tokens.TokenSwapPurpose
2724
import com.flipcash.app.featureflags.FeatureFlag
2825
import com.flipcash.app.featureflags.FeatureFlagController
2926
import com.flipcash.app.onramp.OnRampFlowTracker
30-
import com.flipcash.shared.tokens.R
3127
import com.flipcash.app.shareable.ShareSheetController
3228
import com.flipcash.app.shareable.Shareable
29+
import com.flipcash.shared.tokens.R
3330
import com.getcode.manager.BottomBarAction
3431
import com.getcode.manager.BottomBarManager
3532
import com.getcode.opencode.controllers.TokenController

apps/flipcash/shared/tokens/src/main/kotlin/TokenList.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ fun TokenList(
7676
.padding(horizontal = CodeTheme.dimens.inset),
7777
tokenWithBalance = item,
7878
showFlag = showFlags,
79+
showLogo = !item.isReserves,
7980
isSelected = (selectedToken == item.token.address).takeIf { showSelections },
8081
) { onTokenSelected(item.token) }
8182

services/opencode/src/main/kotlin/com/getcode/opencode/model/financial/Fiat.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ data class Fiat(
171171

172172
val Zero = Fiat(0, CurrencyCode.USD)
173173

174+
val MIN_VALUE = Fiat(Int.MIN_VALUE, CurrencyCode.USD)
175+
val MAX_VALUE = Fiat(Int.MAX_VALUE, CurrencyCode.USD)
176+
174177
private fun parseStringToDouble(stringAmount: String, decimalPlaces: Int = 6): Double {
175178
val formatter = DecimalFormat.getNumberInstance(Locale.US).apply {
176179
isParseIntegerOnly = false

services/opencode/src/main/kotlin/com/getcode/opencode/model/financial/MintMetadata.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,21 @@ import kotlin.time.Instant
1515

1616
data class TokenWithBalance(
1717
val token: Token,
18-
val balance: Fiat
19-
)
18+
val balance: Fiat,
19+
val displayName: String = token.name,
20+
) {
21+
val isReserves: Boolean
22+
get() = token.address == Mint.usdc
23+
}
2024

2125
data class TokenWithLocalizedBalance(
2226
val token: Token,
23-
val balance: LocalFiat
24-
)
27+
val balance: LocalFiat,
28+
val displayName: String = token.name,
29+
) {
30+
val isReserves: Boolean
31+
get() = token.address == Mint.usdc
32+
}
2533

2634
typealias Token = MintMetadata
2735

0 commit comments

Comments
 (0)