Skip to content

Commit 797d16d

Browse files
committed
feat: rebrand USDC as Cash Reserves in Wallet (behind beta flag)
Signed-off-by: Brandon McAnsh <[email protected]>
1 parent 6e0217c commit 797d16d

File tree

13 files changed

+279
-67
lines changed

13 files changed

+279
-67
lines changed

apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/onramp/deeplinks/WalletDeeplinkConnectionResult.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import com.flipcash.app.core.AppRoute
55
import com.getcode.ed25519.Ed25519
66
import com.getcode.opencode.model.core.ID
77
import com.getcode.opencode.utils.base64
8+
import com.getcode.solana.keys.Mint
89
import com.getcode.solana.keys.PublicKey
910
import com.getcode.solana.keys.base58
1011
import com.getcode.utils.base58
@@ -40,6 +41,9 @@ sealed class OnRampDeeplinkOrigin: Parcelable {
4041
@Parcelize
4142
data object Wallet: OnRampDeeplinkOrigin()
4243

44+
@Parcelize
45+
data object Reserves: OnRampDeeplinkOrigin()
46+
4347
@Parcelize
4448
data class PoolWithId(val id: ID) : OnRampDeeplinkOrigin()
4549

@@ -51,8 +55,9 @@ sealed class OnRampDeeplinkOrigin: Parcelable {
5155
is PoolWithId -> "pool-id_${id.base58}"
5256
is PoolWithRendezvous -> "pool-seed_${keyPair.seed.base64}"
5357
Menu -> "menu"
54-
is Give -> "give-${tokenAddress?.base58()}"
58+
is Give -> "give-${tokenAddress.base58()}"
5559
Wallet -> "wallet"
60+
Reserves -> "reserves"
5661
}.lowercase()
5762
}
5863

@@ -66,6 +71,9 @@ sealed class OnRampDeeplinkOrigin: Parcelable {
6671
route.poolId?.let { id -> PoolWithId(id) }
6772
}
6873
is AppRoute.Sheets.Wallet -> Wallet
74+
is AppRoute.Token.Info -> {
75+
if (route.mint == Mint.usdc) Reserves else null
76+
}
6977

7078
else -> null
7179
}
@@ -82,6 +90,7 @@ sealed class OnRampDeeplinkOrigin: Parcelable {
8290
Give(mint)
8391
}
8492
value == "wallet" -> Wallet
93+
value == "reserves" -> Reserves
8594
value?.startsWith("pool-") == true -> {
8695
val idStringWithPrefix = value.removePrefix("pool-")
8796
val splits = idStringWithPrefix.split("_")

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,12 @@
448448
<string name="label_blendModeColorDodge">Color Dodge</string>
449449
<string name="label_blendModePlusLighter">Plus Lighter</string>
450450

451+
<string name="title_cashReserves">Cash Reserves</string>
452+
<string name="action_buyMore">Buy More</string>
453+
<string name="description_cashReserves">
454+
Your cash reserves are held in USDF, 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 USDF for U.S. dollars whenever you like.
455+
</string>
456+
451457

452458

453459

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import androidx.compose.foundation.background
44
import androidx.compose.foundation.layout.Arrangement
55
import androidx.compose.foundation.layout.Box
66
import androidx.compose.foundation.layout.Column
7+
import androidx.compose.foundation.layout.Row
8+
import androidx.compose.foundation.layout.Spacer
79
import androidx.compose.foundation.layout.fillMaxWidth
810
import androidx.compose.foundation.layout.padding
11+
import androidx.compose.material.Icon
912
import androidx.compose.material.Text
1013
import androidx.compose.runtime.Composable
1114
import androidx.compose.runtime.CompositionLocalProvider
@@ -15,11 +18,13 @@ import androidx.compose.runtime.remember
1518
import androidx.compose.ui.Alignment
1619
import androidx.compose.ui.Modifier
1720
import androidx.compose.ui.platform.LocalContext
21+
import androidx.compose.ui.res.painterResource
1822
import androidx.compose.ui.res.stringResource
1923
import androidx.compose.ui.text.style.TextAlign
2024
import androidx.compose.ui.tooling.preview.Preview
2125
import com.flipcash.app.balance.internal.components.BalanceHeader
2226
import com.flipcash.app.core.AppRoute
27+
import com.flipcash.app.core.money.formatted
2328
import com.flipcash.app.core.tokens.TokenPurpose
2429
import com.flipcash.app.onramp.AddCashRow
2530
import com.flipcash.app.theme.FlipcashDesignSystem
@@ -31,6 +36,7 @@ import com.getcode.opencode.compose.LocalExchange
3136
import com.getcode.opencode.model.financial.CurrencyCode
3237
import com.getcode.opencode.model.financial.Rate
3338
import com.getcode.theme.CodeTheme
39+
import com.getcode.ui.core.rememberedClickable
3440

3541
@Composable
3642
internal fun BalanceScreen(
@@ -73,6 +79,7 @@ private fun BalanceScreenContent(
7379

7480
TokenList(
7581
modifier = Modifier.weight(1f),
82+
reservesEnabled = tokenState.reservesEnabled,
7683
emptyState = {
7784
Box(
7885
modifier = Modifier
@@ -96,6 +103,46 @@ private fun BalanceScreenContent(
96103
}
97104
}
98105
},
106+
footer = { mint, reserves ->
107+
Row(
108+
modifier = Modifier
109+
.fillMaxWidth()
110+
.rememberedClickable {
111+
dispatchEvent(
112+
BalanceViewModel.Event.OpenScreen(
113+
AppRoute.Token.Info(mint)
114+
)
115+
)
116+
}
117+
.padding(
118+
vertical = CodeTheme.dimens.grid.x3,
119+
horizontal = CodeTheme.dimens.inset),
120+
verticalAlignment = Alignment.CenterVertically,
121+
) {
122+
Text(
123+
text = stringResource(R.string.title_cashReserves),
124+
style = CodeTheme.typography.textMedium,
125+
color = CodeTheme.colors.textSecondary,
126+
)
127+
128+
Icon(
129+
modifier = Modifier
130+
.padding(vertical = CodeTheme.dimens.grid.x1)
131+
.padding(start = CodeTheme.dimens.grid.x1),
132+
painter = painterResource(id = R.drawable.ic_chevron_right),
133+
contentDescription = null,
134+
tint = CodeTheme.colors.secondary,
135+
)
136+
137+
Spacer(Modifier.weight(1f))
138+
139+
Text(
140+
text = reserves.formatted(),
141+
style = CodeTheme.typography.screenTitle,
142+
color = CodeTheme.colors.textMain,
143+
)
144+
}
145+
},
99146
tokens = tokens,
100147
onTokenSelected = {
101148
dispatchEvent(

apps/flipcash/features/scanner/src/main/kotlin/com/flipcash/app/scanner/internal/NavigationStateRestorer.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import com.flipcash.app.core.navigation.DeeplinkType
66
import com.flipcash.app.core.onramp.deeplinks.OnRampDeeplinkOrigin
77
import com.flipcash.app.core.verification.email.EmailDeeplinkOrigin
88
import com.getcode.navigation.core.CodeNavigator
9+
import com.getcode.solana.keys.Mint
910
import com.getcode.ui.core.scaled
1011
import kotlinx.coroutines.delay
1112

@@ -42,6 +43,7 @@ class NavigationStateRestorer(
4243
is OnRampDeeplinkOrigin.PoolWithRendezvous -> buildOnRampScreenFlow(AppRoute.Pool.Details(rendezvous = origin.keyPair))
4344
is OnRampDeeplinkOrigin.Give -> buildOnRampScreenFlow(AppRoute.Main.Give(origin.tokenAddress))
4445
OnRampDeeplinkOrigin.Wallet -> buildOnRampScreenFlow(AppRoute.Sheets.Wallet)
46+
OnRampDeeplinkOrigin.Reserves -> buildOnRampScreenFlow(AppRoute.Token.Info(Mint.usdc))
4547
} + ScreenRegistry.get(AppRoute.OnRamp.AmountEntry)
4648

4749
navigator.show(screens)
@@ -101,7 +103,9 @@ class NavigationStateRestorer(
101103
}
102104
}
103105

104-
private fun buildOnRampScreenFlow(origin: AppRoute) = listOf(
105-
ScreenRegistry.get(origin),
106-
ScreenRegistry.get(AppRoute.OnRamp.ProviderList(origin)),
107-
)
106+
private fun buildOnRampScreenFlow(origin: List<AppRoute>) =
107+
origin.dropLast(1).map { ScreenRegistry.get(it) } +
108+
ScreenRegistry.get(AppRoute.OnRamp.ProviderList(origin.last())
109+
)
110+
111+
private fun buildOnRampScreenFlow(origin: AppRoute) = buildOnRampScreenFlow(listOf(origin))

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import androidx.compose.runtime.LaunchedEffect
88
import androidx.compose.runtime.getValue
99
import androidx.compose.ui.Alignment
1010
import androidx.compose.ui.Modifier
11+
import androidx.compose.ui.res.stringResource
1112
import androidx.lifecycle.compose.collectAsStateWithLifecycle
1213
import cafe.adriel.voyager.core.registry.ScreenRegistry
1314
import cafe.adriel.voyager.core.screen.ScreenKey
1415
import cafe.adriel.voyager.core.screen.uniqueScreenKey
1516
import cafe.adriel.voyager.hilt.getViewModel
1617
import com.flipcash.app.core.ui.TokenIconWithName
1718
import com.flipcash.app.tokens.internal.TokenInfoScreen
19+
import com.flipcash.features.tokens.R
1820
import com.getcode.navigation.core.LocalCodeNavigator
1921
import com.getcode.navigation.modal.ModalScreen
2022
import com.getcode.solana.keys.Mint
@@ -47,20 +49,26 @@ class TokenInfoScreen(private val mint: Mint) : ModalScreen, Parcelable {
4749
isInModal = true,
4850
title = {
4951
state.token?.let { token ->
50-
TokenIconWithName(
51-
token = token,
52-
imageSize = CodeTheme.dimens.staticGrid.x5,
53-
spacing = CodeTheme.dimens.grid.x1,
54-
)
52+
if (state.isCashReserve && state.cashReservesEnabled) {
53+
AppBarDefaults.Title(text = stringResource(R.string.title_cashReserves))
54+
} else {
55+
TokenIconWithName(
56+
token = token,
57+
imageSize = CodeTheme.dimens.staticGrid.x5,
58+
spacing = CodeTheme.dimens.grid.x1,
59+
)
60+
}
5561
}
5662
},
5763
titleAlignment = Alignment.CenterHorizontally,
5864
leftIcon = {
5965
AppBarDefaults.UpNavigation { navigator.pop() }
6066
},
6167
rightContents = {
62-
AppBarDefaults.Share {
63-
viewModel.dispatchEvent(TokenInfoViewModel.Event.Share)
68+
if (state.isCashReserve && state.cashReservesEnabled) {
69+
AppBarDefaults.Share {
70+
viewModel.dispatchEvent(TokenInfoViewModel.Event.Share)
71+
}
6472
}
6573
},
6674
)

0 commit comments

Comments
 (0)