Skip to content

Commit

Permalink
CLI-663 Vault deposit/withdraw screen (#233)
Browse files Browse the repository at this point in the history
![Screenshot_1727802557](https://github.com/user-attachments/assets/696d385b-09e9-4733-acc1-6c7fd5951631)

![Screenshot_1727802554](https://github.com/user-attachments/assets/f829bc5c-879d-4ac3-9ab7-1592b1cde8c3)

---------

Co-authored-by: Prashan Dharmasena <163016611+prashanDYDX@users.noreply.github.com>
  • Loading branch information
ruixhuang and prashanDYDX authored Oct 2, 2024
1 parent 51df9fb commit 62871d3
Show file tree
Hide file tree
Showing 30 changed files with 1,800 additions and 53 deletions.
2 changes: 1 addition & 1 deletion v4/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ ext {
compileSdkVersion = 34

// App dependencies
abacusVersion = '1.12.7'
abacusVersion = '1.12.14'
carteraVersion = '0.1.15'
kollectionsVersion = '2.0.16'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,5 @@ object VaultRoutes {
const val main = "vault"
const val deposit = "vault/deposit"
const val withdraw = "vault/withdraw"
const val confirmation = "vault/confirmation"
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ object DydxReceiptView : DydxComponent {
TransferDuration,
Slippage,
PositionMargin,
LiquidationPrice;
LiquidationPrice,
}

data class ViewState(
Expand Down
18 changes: 18 additions & 0 deletions v4/feature/shared/src/main/res/drawable/icon_right_arrow_2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="28dp"
android:height="28dp"
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:pathData="M9.226,18.77C9.088,18.627 9.013,18.435 9.017,18.236C9.02,18.038 9.103,17.848 9.246,17.71L13.184,14L9.246,10.29C9.172,10.223 9.112,10.141 9.07,10.05C9.027,9.959 9.004,9.861 9,9.76C8.997,9.66 9.014,9.56 9.05,9.466C9.086,9.372 9.14,9.287 9.21,9.215C9.279,9.142 9.363,9.085 9.455,9.045C9.547,9.006 9.647,8.985 9.747,8.985C9.847,8.984 9.947,9.004 10.039,9.043C10.132,9.082 10.216,9.139 10.286,9.21L14.786,13.46C14.859,13.53 14.916,13.614 14.956,13.707C14.995,13.8 15.016,13.9 15.016,14C15.016,14.101 14.995,14.201 14.956,14.294C14.916,14.387 14.859,14.47 14.786,14.54L10.286,18.79C10.143,18.928 9.951,19.003 9.752,19C9.553,18.996 9.364,18.913 9.226,18.77Z"
android:strokeAlpha="0.3"
android:fillColor="#807E98"
android:fillType="evenOdd"
android:fillAlpha="0.3"/>
<path
android:pathData="M15.242,18.77C15.104,18.627 15.029,18.435 15.032,18.236C15.036,18.038 15.119,17.848 15.262,17.71L19.2,14L15.262,10.29C15.187,10.223 15.127,10.141 15.085,10.05C15.043,9.959 15.019,9.861 15.016,9.76C15.013,9.66 15.029,9.56 15.065,9.466C15.101,9.372 15.156,9.287 15.225,9.215C15.295,9.142 15.378,9.085 15.471,9.045C15.563,9.006 15.662,8.985 15.763,8.985C15.863,8.984 15.962,9.004 16.055,9.043C16.148,9.082 16.232,9.139 16.302,9.21L20.802,13.46C20.874,13.53 20.932,13.614 20.972,13.707C21.011,13.8 21.031,13.9 21.031,14C21.031,14.101 21.011,14.201 20.972,14.294C20.932,14.387 20.874,14.47 20.802,14.54L16.302,18.79C16.159,18.928 15.966,19.003 15.768,19C15.569,18.996 15.38,18.913 15.242,18.77Z"
android:strokeAlpha="0.6"
android:fillColor="#807E98"
android:fillType="evenOdd"
android:fillAlpha="0.6"/>
</vector>
79 changes: 79 additions & 0 deletions v4/feature/shared/src/main/res/drawable/vault_account_token.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<group>
<clip-path
android:pathData="M0,0h32v32h-32z"/>
<path
android:pathData="M16,32C24.837,32 32,24.837 32,16C32,7.163 24.837,0 16,0C7.163,0 0,7.163 0,16C0,24.837 7.163,32 16,32Z"
android:fillColor="#101018"/>
<group>
<clip-path
android:pathData="M4.5,9.675h23.001v12.65h-23.001z"/>
<path
android:pathData="M19.014,9.675L10.25,22.324H12.941L21.75,9.675H19.014Z"
android:fillColor="#FAFAFD"/>
<path
android:pathData="M13.107,9.675L15.8,13.402L14.455,15.435L10.36,9.675H13.107Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="12.605"
android:startY="10.466"
android:endX="16.329"
android:endY="14.928"
android:type="linear">
<item android:offset="0" android:color="#FFFFFFFF"/>
<item android:offset="1" android:color="#8CFFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M19.046,22.325L16.301,18.202L17.647,16.226L21.736,22.325H19.046Z">
<aapt:attr name="android:fillColor">
<gradient
android:startX="19.777"
android:startY="21.365"
android:endX="15.198"
android:endY="15.238"
android:type="linear">
<item android:offset="0" android:color="#FF6966FF"/>
<item android:offset="1" android:color="#5B6966FF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M21.4,12.153L22.687,10.316L27.5,13.686L27.5,13.687H27.5V18.3H27.5L22.698,21.663L21.411,19.826L25.257,17.133V14.854L21.4,12.153Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="24.504"
android:startY="10.811"
android:endX="22.673"
android:endY="23.606"
android:type="linear">
<item android:offset="0" android:color="#FFFFFFFF"/>
<item android:offset="1" android:color="#00FFFFFF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M10.595,12.153L9.308,10.316L4.495,13.686L4.496,13.687H4.495V18.3H4.495L9.297,21.663L10.584,19.826L6.738,17.133V14.854L10.595,12.153Z"
android:fillType="evenOdd">
<aapt:attr name="android:fillColor">
<gradient
android:startX="5.805"
android:startY="9.71"
android:endX="7.285"
android:endY="21.041"
android:type="linear">
<item android:offset="0" android:color="#00FFFFFF"/>
<item android:offset="1" android:color="#FFFFFFFF"/>
</gradient>
</aapt:attr>
</path>
</group>
</group>
</vector>
16 changes: 16 additions & 0 deletions v4/feature/shared/src/main/res/drawable/vault_cross_token.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<group>
<clip-path
android:pathData="M0,0h32v32h-32z"/>
<path
android:pathData="M16,32C24.837,32 32,24.837 32,16C32,7.163 24.837,0 16,0C7.163,0 0,7.163 0,16C0,24.837 7.163,32 16,32Z"
android:fillColor="#101018"/>
<path
android:pathData="M16.199,22.176C12.903,22.176 10.711,19.808 10.711,16.224C10.711,12.656 12.967,10.24 16.279,10.24C18.887,10.24 20.887,11.792 21.319,14.16H19.639C19.207,12.656 17.911,11.744 16.231,11.744C13.895,11.744 12.359,13.504 12.359,16.208C12.359,18.912 13.895,20.672 16.231,20.672C17.927,20.672 19.271,19.76 19.703,18.336H21.367C20.871,20.64 18.807,22.176 16.199,22.176Z"
android:fillColor="#C8C7D8"/>
</group>
</vector>
16 changes: 16 additions & 0 deletions v4/feature/shared/src/main/res/drawable/vault_usdc_token.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<group>
<clip-path
android:pathData="M0,0h32v32h-32z"/>
<path
android:pathData="M16,32C24.837,32 32,24.837 32,16C32,7.163 24.837,0 16,0C7.163,0 0,7.163 0,16C0,24.837 7.163,32 16,32Z"
android:fillColor="#366EDD"/>
<path
android:pathData="M16,26.667C10.108,26.667 5.333,21.892 5.333,16C5.333,10.108 10.108,5.333 16,5.333C21.892,5.333 26.667,10.108 26.667,16C26.667,18.829 25.543,21.542 23.543,23.542C21.542,25.543 18.829,26.667 16,26.667ZM15.365,12.042C14.781,12.071 14.229,12.317 13.818,12.732C13.406,13.147 13.165,13.7 13.141,14.284C13.141,15.383 13.812,16.1 15.238,16.399L16.236,16.635C17.208,16.862 17.607,17.189 17.607,17.743C17.607,18.297 16.908,18.841 16,18.841C15.678,18.871 15.354,18.809 15.064,18.663C14.776,18.517 14.533,18.292 14.366,18.015C14.316,17.91 14.238,17.821 14.14,17.758C14.042,17.696 13.929,17.662 13.812,17.661H13.277C13.236,17.669 13.196,17.684 13.161,17.707C13.126,17.73 13.096,17.76 13.072,17.794C13.049,17.829 13.032,17.868 13.024,17.909C13.015,17.95 13.015,17.992 13.023,18.033C13.153,18.566 13.456,19.04 13.885,19.382C14.314,19.723 14.844,19.913 15.392,19.922V20.684C15.392,20.854 15.459,21.017 15.579,21.137C15.699,21.257 15.862,21.324 16.032,21.324C16.202,21.324 16.365,21.257 16.485,21.137C16.604,21.017 16.672,20.854 16.672,20.684V19.913C17.292,19.906 17.884,19.657 18.323,19.219C18.763,18.782 19.014,18.19 19.023,17.57C19.023,16.417 18.36,15.755 16.79,15.419L15.882,15.219C14.974,14.992 14.548,14.693 14.548,14.184C14.548,13.676 15.092,13.113 16,13.113C16.286,13.083 16.574,13.137 16.831,13.267C17.087,13.398 17.3,13.6 17.444,13.848C17.502,13.973 17.594,14.078 17.71,14.152C17.826,14.226 17.96,14.265 18.097,14.266H18.524C18.621,14.242 18.705,14.182 18.757,14.097C18.81,14.012 18.827,13.91 18.805,13.812C18.682,13.321 18.407,12.88 18.019,12.554C17.631,12.228 17.15,12.033 16.645,11.997V11.37C16.645,11.2 16.577,11.038 16.457,10.918C16.337,10.798 16.174,10.73 16.005,10.73C15.835,10.73 15.672,10.798 15.552,10.918C15.432,11.038 15.365,11.2 15.365,11.37V12.042ZM8.002,16C8.003,17.672 8.53,19.302 9.507,20.659C10.484,22.015 11.863,23.031 13.449,23.562H13.576C13.685,23.562 13.789,23.519 13.865,23.442C13.942,23.366 13.985,23.262 13.985,23.153V22.963C13.985,22.794 13.935,22.628 13.842,22.488C13.748,22.347 13.614,22.238 13.458,22.173C12.223,21.674 11.165,20.818 10.421,19.714C9.676,18.61 9.278,17.309 9.278,15.977C9.278,14.646 9.676,13.344 10.421,12.24C11.165,11.136 12.223,10.28 13.458,9.781C13.614,9.718 13.747,9.61 13.84,9.471C13.934,9.332 13.985,9.168 13.985,9.001V8.792C13.985,8.731 13.971,8.67 13.943,8.615C13.916,8.561 13.875,8.514 13.825,8.478C13.775,8.442 13.718,8.419 13.657,8.411C13.596,8.402 13.534,8.408 13.476,8.429C11.884,8.955 10.498,9.97 9.516,11.33C8.533,12.689 8.003,14.323 8.002,16ZM23.998,16C23.995,14.329 23.468,12.702 22.49,11.347C21.513,9.991 20.135,8.977 18.551,8.447H18.415C18.302,8.447 18.193,8.492 18.113,8.572C18.033,8.652 17.988,8.761 17.988,8.874V9.01C17.992,9.185 18.046,9.355 18.144,9.5C18.243,9.645 18.381,9.759 18.542,9.827C19.774,10.327 20.829,11.183 21.572,12.286C22.315,13.389 22.711,14.688 22.711,16.018C22.711,17.348 22.315,18.647 21.572,19.75C20.829,20.853 19.774,21.709 18.542,22.209C18.384,22.278 18.249,22.391 18.152,22.534C18.056,22.677 18.002,22.845 17.997,23.017V23.171C17.998,23.239 18.015,23.305 18.046,23.365C18.077,23.424 18.122,23.476 18.177,23.514C18.232,23.553 18.295,23.579 18.362,23.589C18.428,23.598 18.496,23.593 18.56,23.571C20.146,23.038 21.524,22.021 22.499,20.662C23.475,19.303 23.999,17.673 23.998,16Z"
android:fillColor="#FAFAFD"/>
</group>
</vector>
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package exchange.dydx.trading.feature.transfer

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import exchange.dydx.abacus.protocols.LocalizerProtocol
import exchange.dydx.platformui.components.tabgroups.PlatformPillTextGroup
Expand Down Expand Up @@ -81,6 +83,7 @@ object DydxTransferSectionsView : DydxComponent {
selectedItemStyle = TextStyle.dydxDefault
.themeColor(ThemeColor.SemanticColor.text_primary)
.themeFont(fontType = ThemeFont.FontType.book, fontSize = ThemeFont.FontSize.large),
padding = PaddingValues(horizontal = 14.dp, vertical = 8.dp),
currentSelection = state.selections.indexOf(state.currentSelection),
scrollingEnabled = true,
onSelectionChanged = { index ->
Expand Down
1 change: 1 addition & 0 deletions v4/feature/vault/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ dependencies {

api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion"
implementation project(':v4:integration:cosmos')
implementation project(':v4:feature:receipt')


kapt "com.google.dagger:hilt-compiler:$hiltVersion"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import androidx.compose.ui.Modifier
import androidx.navigation.NavGraphBuilder
import exchange.dydx.trading.common.navigation.DydxRouter
import exchange.dydx.trading.common.navigation.VaultRoutes
import exchange.dydx.trading.common.navigation.VaultRoutes.confirmation
import exchange.dydx.trading.common.navigation.dydxComposable
import exchange.dydx.trading.feature.shared.bottombar.DydxBottomBarScaffold
import exchange.dydx.trading.feature.vault.DydxVaultView
import exchange.dydx.trading.feature.vault.depositwithdraw.DydxVaultDepositWithdrawView
import exchange.dydx.trading.feature.vault.depositwithdraw.confirmation.DydxVaultConfirmationView
import exchange.dydx.utilities.utils.Logging

fun NavGraphBuilder.vaultGraph(
Expand All @@ -29,18 +31,22 @@ fun NavGraphBuilder.vaultGraph(
route = VaultRoutes.deposit,
deepLinks = appRouter.deeplinks(VaultRoutes.deposit),
) { navBackStackEntry ->
DydxBottomBarScaffold(Modifier) {
DydxVaultDepositWithdrawView.Content(Modifier, type = DydxVaultDepositWithdrawView.DepositWithdrawType.DEPOSIT)
}
DydxVaultDepositWithdrawView.Content(Modifier, type = DydxVaultDepositWithdrawView.DepositWithdrawType.DEPOSIT)
}

dydxComposable(
router = appRouter,
route = VaultRoutes.withdraw,
deepLinks = appRouter.deeplinks(VaultRoutes.withdraw),
) { navBackStackEntry ->
DydxBottomBarScaffold(Modifier) {
DydxVaultDepositWithdrawView.Content(Modifier, type = DydxVaultDepositWithdrawView.DepositWithdrawType.WITHDRAW)
}
DydxVaultDepositWithdrawView.Content(Modifier, type = DydxVaultDepositWithdrawView.DepositWithdrawType.WITHDRAW)
}

dydxComposable(
router = appRouter,
route = VaultRoutes.confirmation,
deepLinks = appRouter.deeplinks(VaultRoutes.confirmation),
) { navBackStackEntry ->
DydxVaultConfirmationView.Content(Modifier)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ object DydxVaultView : DydxComponent {
}
stickyHeader(key = "positions_header") {
DydxVaultPositionsHeaderView.Content(
Modifier,
DydxVaultPositionsHeaderView.ViewState(
modifier = Modifier
.fillParentMaxWidth()
.themeColor(ThemeColor.SemanticColor.layer_2),
state = DydxVaultPositionsHeaderView.ViewState(
localizer = state.localizer,
positionCount = state.items.count(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import javax.inject.Inject
import kotlin.math.absoluteValue
import kotlin.math.sign

@HiltViewModel
class DydxVaultViewModel @Inject constructor(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package exchange.dydx.trading.feature.vault

import dagger.hilt.android.scopes.ActivityRetainedScoped
import exchange.dydx.abacus.functional.vault.VaultDepositWithdrawFormValidator
import exchange.dydx.abacus.functional.vault.VaultFormAccountData
import exchange.dydx.abacus.functional.vault.VaultFormAction
import exchange.dydx.abacus.functional.vault.VaultFormData
import exchange.dydx.abacus.functional.vault.VaultFormValidationResult
import exchange.dydx.dydxstatemanager.AbacusStateManagerProtocol
import indexer.models.chain.OnChainVaultDepositWithdrawSlippageResponse
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import javax.inject.Inject

enum class VaultInputType {
DEPOSIT,
WITHDRAW
}

enum class VaultInputStage {
EDIT,
CONFIRM,
SUBMIT
}

@ActivityRetainedScoped
class VaultInputState @Inject constructor(
private val abacusStateManager: AbacusStateManagerProtocol,
) {
val type: MutableStateFlow<VaultInputType?> = MutableStateFlow(null)
val amount: MutableStateFlow<Double?> = MutableStateFlow(null)
val stage: MutableStateFlow<VaultInputStage> = MutableStateFlow(VaultInputStage.EDIT)
val slippageAcked: MutableStateFlow<Boolean> = MutableStateFlow(false)
val slippageResponse: MutableStateFlow<OnChainVaultDepositWithdrawSlippageResponse?> = MutableStateFlow(null)

private val vaultFormData: Flow<VaultFormData?> =
combine(
type,
amount,
stage,
slippageAcked,
) { type, amount, stage, slippageAcked ->
val type = type ?: return@combine null
val amount = amount ?: return@combine null
VaultFormData(
action = when (type) {
VaultInputType.DEPOSIT -> VaultFormAction.DEPOSIT
VaultInputType.WITHDRAW -> VaultFormAction.WITHDRAW
},
amount = amount,
acknowledgedSlippage = slippageAcked,
inConfirmationStep = stage == VaultInputStage.CONFIRM,
)
}
.distinctUntilChanged()

private val vaultFormAccountData: Flow<VaultFormAccountData?> =
abacusStateManager.state.selectedSubaccount
.map {
VaultFormAccountData(
marginUsage = it?.marginUsage?.current,
freeCollateral = it?.freeCollateral?.current,
canViewAccount = it != null,
)
}
.distinctUntilChanged()

val result: Flow<VaultFormValidationResult?> =
combine(
vaultFormData,
vaultFormAccountData,
abacusStateManager.state.vault.map { it?.account },
slippageResponse,
) { formData, accountData, account, slippageResponse ->
val formData = formData ?: return@combine null
VaultDepositWithdrawFormValidator.validateVaultForm(
formData = formData,
accountData = accountData,
vaultAccount = account,
slippageResponse = slippageResponse,
)
}
.distinctUntilChanged()

fun reset() {
type.value = null
amount.value = null
stage.value = VaultInputStage.EDIT
slippageAcked.value = false
slippageResponse.value = null
}
}
Loading

0 comments on commit 62871d3

Please sign in to comment.