Skip to content

Commit 75aefa1

Browse files
committed
chore(deposit): move direct USDC deposit behind beta flag
Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent 0d2d125 commit 75aefa1

6 files changed

Lines changed: 69 additions & 21 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@
639639
<string name="description_withdrawUsdfAsUsdc">Your USDF will be converted 1:1 to Solana USDC on withdrawal</string>
640640
<string name="displayName_solanaUsdc">Solana USDC</string>
641641
<string name="displayName_usdc">USDC</string>
642+
<string name="displayName_usdf">USDF</string>
642643
<string name="label_withdrawalAmount">Withdrawal amount</string>
643644
<string name="label_lessFee">Less fee</string>
644645
<string name="label_netAmount">Net amount</string>

apps/flipcash/features/deposit/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ android {
99
dependencies {
1010
implementation(project(":libs:messaging"))
1111

12+
implementation(project(":apps:flipcash:shared:featureflags"))
1213
implementation(project(":services:flipcash"))
1314

1415
}

apps/flipcash/features/deposit/src/main/kotlin/com/flipcash/app/deposit/DepositFlowScreen.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import androidx.navigation3.runtime.entryProvider
1010
import com.flipcash.app.core.AppRoute
1111
import com.flipcash.app.core.deposit.DepositResult
1212
import com.flipcash.app.core.deposit.DepositStep
13+
import com.flipcash.app.featureflags.FeatureFlag
14+
import com.flipcash.app.featureflags.LocalFeatureFlags
1315
import com.flipcash.app.deposit.internal.DepositViewModel
1416
import com.flipcash.app.deposit.internal.UsdcDepositInformationScreen
1517
import com.flipcash.app.theme.FlipcashThemeWrapper
@@ -31,8 +33,16 @@ fun DepositFlowScreen(
3133
resultStateRegistry: NavResultStateRegistry,
3234
) {
3335
val outerNavigator = LocalCodeNavigator.current
36+
val featureFlags = LocalFeatureFlags.current
3437

35-
val initialStack = route.rememberInitialStack<DepositStep>()
38+
val initialStack = route.rememberInitialStack<DepositStep> { steps ->
39+
val directDeposit = featureFlags.observe(FeatureFlag.DepositUsdc).value
40+
if (!directDeposit && route.mint == Mint.usdf) {
41+
listOf(DepositStep.Destination(route.mint))
42+
} else {
43+
steps
44+
}
45+
}
3646

3747
FlowHost(
3848
initialStack = initialStack,

apps/flipcash/features/deposit/src/main/kotlin/com/flipcash/app/deposit/internal/DepositViewModel.kt

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import com.getcode.solana.keys.base58
1313
import com.getcode.util.resources.ResourceHelper
1414
import com.flipcash.libs.coroutines.DispatcherProvider
1515
import com.getcode.opencode.internal.solana.extensions.timelockSwapAccounts
16+
import com.flipcash.app.featureflags.FeatureFlag
17+
import com.flipcash.app.featureflags.FeatureFlagController
1618
import com.getcode.opencode.model.financial.Token
1719
import com.getcode.opencode.model.financial.usdf
1820
import com.getcode.view.BaseViewModel2
@@ -22,6 +24,7 @@ import kotlinx.coroutines.flow.filterIsInstance
2224
import kotlinx.coroutines.flow.launchIn
2325
import kotlinx.coroutines.flow.mapNotNull
2426
import kotlinx.coroutines.flow.onEach
27+
import kotlinx.coroutines.launch
2528
import javax.inject.Inject
2629
import kotlin.time.Duration.Companion.seconds
2730

@@ -32,6 +35,7 @@ internal class DepositViewModel @Inject constructor(
3235
clipboardManager: ClipboardManager,
3336
resources: ResourceHelper,
3437
dispatchers: DispatcherProvider,
38+
featureFlags: FeatureFlagController,
3539
) : BaseViewModel2<DepositViewModel.State, DepositViewModel.Event>(
3640
initialState = State(),
3741
updateStateForEvent = updateStateForEvent,
@@ -58,30 +62,37 @@ internal class DepositViewModel @Inject constructor(
5862
.mapNotNull { tokenController.getTokenMetadata(it.mint) }
5963
.onResult(
6064
onSuccess = { result ->
61-
val address = if (result.token.address == Mint.usdf) {
62-
val usdfSwapAccounts = userManager.accountCluster?.let {
63-
Token.usdf.timelockSwapAccounts(it.authorityPublicKey)
65+
viewModelScope.launch {
66+
val directDeposit = featureFlags.get(FeatureFlag.DepositUsdc)
67+
val address = if (result.token.address == Mint.usdf && directDeposit) {
68+
val usdfSwapAccounts = userManager.accountCluster?.let {
69+
Token.usdf.timelockSwapAccounts(it.authorityPublicKey)
70+
}
71+
usdfSwapAccounts?.ata?.publicKey?.base58()
72+
} else {
73+
userManager.accountCluster?.depositAddressFor(result.token)?.base58()
6474
}
65-
usdfSwapAccounts?.pda?.publicKey?.base58()
66-
} else {
67-
userManager.accountCluster?.depositAddressFor(result.token)?.base58()
68-
}
6975

70-
if (address == null) {
71-
BottomBarManager.showError(
72-
title = resources.getString(R.string.error_title_tokenNotFound),
73-
message = resources.getString(R.string.error_description_tokenNotFound),
74-
) {
75-
dispatchEvent(Event.Exit)
76+
if (address == null) {
77+
BottomBarManager.showError(
78+
title = resources.getString(R.string.error_title_tokenNotFound),
79+
message = resources.getString(R.string.error_description_tokenNotFound),
80+
) {
81+
dispatchEvent(Event.Exit)
82+
}
83+
return@launch
7684
}
77-
return@onResult
78-
}
79-
val tokenName = if (result.token.address == Mint.usdf) {
80-
resources.getString(R.string.displayName_usdc)
81-
} else {
82-
result.token.name
85+
val tokenName = when {
86+
directDeposit && result.token.address == Mint.usdf -> {
87+
resources.getString(R.string.displayName_usdc)
88+
}
89+
result.token.address == Mint.usdf -> {
90+
resources.getString(R.string.displayName_usdf)
91+
}
92+
else -> result.token.name
93+
}
94+
dispatchEvent(Event.OnTokenChanged(address, tokenName))
8395
}
84-
dispatchEvent(Event.OnTokenChanged(address, tokenName))
8596
},
8697
onError = {
8798
BottomBarManager.showError(

apps/flipcash/shared/featureflags/src/main/kotlin/com/flipcash/app/featureflags/FeatureFlag.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,15 @@ sealed interface FeatureFlag {
135135
override val persistLogOut: Boolean = false
136136
}
137137

138+
@FeatureFlagMarker
139+
data object DepositUsdc: FeatureFlag {
140+
override val key: String = "deposit_usdc_enabled"
141+
override val default: Boolean = false
142+
override val launched: Boolean = false
143+
override val visible: Boolean = true
144+
override val persistLogOut: Boolean = false
145+
}
146+
138147
companion object {
139148
val entries: List<FeatureFlag>
140149
get() = FeatureFlagEntries.entries
@@ -162,6 +171,7 @@ val FeatureFlag.title: String
162171
FeatureFlag.TokenDiscovery -> "Token Discovery"
163172
FeatureFlag.CurrencyCreator -> "Currency Creator"
164173
FeatureFlag.BillTextures -> "Bill Textures"
174+
FeatureFlag.DepositUsdc -> "Deposit USDC"
165175
}
166176

167177
val FeatureFlag.message: String
@@ -180,6 +190,7 @@ val FeatureFlag.message: String
180190
FeatureFlag.TokenDiscovery -> "When enabled, you'll gain access to leaderboards for tokens and discovery"
181191
FeatureFlag.CurrencyCreator -> "When enabled, you'll gain access to create new currencies"
182192
FeatureFlag.BillTextures -> "When enabled, you'll gain the ability to select textures for bills during currency creation"
193+
FeatureFlag.DepositUsdc -> "When enabled, you'll gain the ability to deposit USDC directly from any external wallet app instead of purchasing a currency first and sell"
183194
}
184195

185196

ui/navigation/src/main/kotlin/com/getcode/navigation/flow/FlowRoute.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,17 @@ inline fun <reified S : FlowStep> FlowRoute.rememberInitialStack(): List<S> {
3939
initialStack as List<S>
4040
}
4141
}
42+
43+
/**
44+
* Remembers the [FlowRoute.initialStack] cast to the concrete [FlowStep] type,
45+
* applying [transform] to modify the stack before it is remembered.
46+
*/
47+
@Composable
48+
inline fun <reified S : FlowStep> FlowRoute.rememberInitialStack(
49+
noinline transform: (List<S>) -> List<S>,
50+
): List<S> {
51+
return remember(this) {
52+
@Suppress("UNCHECKED_CAST")
53+
transform(initialStack as List<S>)
54+
}
55+
}

0 commit comments

Comments
 (0)