Skip to content

Commit

Permalink
Update FF logic to SL/TP trigger (#91)
Browse files Browse the repository at this point in the history
  • Loading branch information
ruixhuang authored May 1, 2024
1 parent 1115cfc commit 53bf64b
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import exchange.dydx.dydxstatemanager.AbacusStateManagerProtocol
import exchange.dydx.dydxstatemanager.MarketConfigsAndAsset
import exchange.dydx.dydxstatemanager.stopLossOrders
import exchange.dydx.dydxstatemanager.takeProfitOrders
import exchange.dydx.trading.common.BuildConfig
import exchange.dydx.trading.common.DydxViewModel
import exchange.dydx.trading.common.formatter.DydxFormatter
import exchange.dydx.trading.common.navigation.DydxRouter
Expand All @@ -33,12 +34,14 @@ class DydxMarketPositionButtonsViewModel @Inject constructor(
private val marketIdFlow = marketInfoStream.marketAndAsset
.mapNotNull { it?.market?.id }

private val includeLimitOrders = abacusStateManager.environment?.featureFlags?.isSlTpLimitOrdersEnabled == true || BuildConfig.DEBUG

val state: Flow<DydxMarketPositionButtonsView.ViewState?> =
combine(
marketIdFlow,
marketIdFlow.flatMapLatest { abacusStateManager.state.selectedSubaccountPositionOfMarket(it) },
marketIdFlow.flatMapLatest { abacusStateManager.state.takeProfitOrders(it) },
marketIdFlow.flatMapLatest { abacusStateManager.state.stopLossOrders(it) },
marketIdFlow.flatMapLatest { abacusStateManager.state.takeProfitOrders(it, includeLimitOrders) },
marketIdFlow.flatMapLatest { abacusStateManager.state.stopLossOrders(it, includeLimitOrders) },
abacusStateManager.state.configsAndAssetMap,
) { marketId, position, takeProfitOrders, stopLossOrders, configsAndAssetMap ->
createViewState(marketId, position, takeProfitOrders, stopLossOrders, configsAndAssetMap?.get(marketId))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import exchange.dydx.abacus.output.SubaccountPosition
import exchange.dydx.abacus.protocols.LocalizerProtocol
import exchange.dydx.dydxstatemanager.AbacusStateManagerProtocol
import exchange.dydx.trading.common.BuildConfig
import exchange.dydx.trading.common.DydxViewModel
import exchange.dydx.trading.common.featureflags.DydxFeatureFlag
import exchange.dydx.trading.common.featureflags.DydxFeatureFlags
Expand All @@ -26,6 +28,7 @@ class DydxMarketPositionViewModel @Inject constructor(
marketInfoStream: MarketInfoStreaming,
private val router: DydxRouter,
private val featureFlags: DydxFeatureFlags,
private val abacusStateManager: AbacusStateManagerProtocol,
) : ViewModel(), DydxViewModel {

val state: Flow<DydxMarketPositionView.ViewState?> =
Expand Down Expand Up @@ -63,7 +66,12 @@ class DydxMarketPositionViewModel @Inject constructor(
)
},
),
enableTrigger = featureFlags.isFeatureEnabled(DydxFeatureFlag.enable_sl_tp_trigger),
enableTrigger = if (BuildConfig.DEBUG) {
featureFlags.isFeatureEnabled(DydxFeatureFlag.enable_sl_tp_trigger)
} else {
featureFlags.isFeatureEnabled(DydxFeatureFlag.enable_sl_tp_trigger) &&
abacusStateManager.environment?.featureFlags?.isSlTpEnabled == true
},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import dagger.hilt.android.scopes.ActivityRetainedScoped
import exchange.dydx.dydxstatemanager.AbacusStateManagerProtocol
import exchange.dydx.dydxstatemanager.stopLossOrders
import exchange.dydx.dydxstatemanager.takeProfitOrders
import exchange.dydx.trading.common.BuildConfig
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.update
Expand Down Expand Up @@ -57,13 +60,16 @@ class TriggerOrderStream @Inject constructor(
private val marketIdFlow = abacusStateManager.state.triggerOrdersInput
.mapNotNull { it?.marketId }

private val includeLimitOrders = abacusStateManager.environment?.featureFlags?.isSlTpLimitOrdersEnabled == true || BuildConfig.DEBUG

override val isNewTriggerOrder: Flow<Boolean> =
combine(
marketIdFlow.flatMapLatest { abacusStateManager.state.takeProfitOrders(it) },
marketIdFlow.flatMapLatest { abacusStateManager.state.stopLossOrders(it) },
marketIdFlow.flatMapLatest { abacusStateManager.state.takeProfitOrders(it, includeLimitOrders).filterNotNull() },
marketIdFlow.flatMapLatest { abacusStateManager.state.stopLossOrders(it, includeLimitOrders).filterNotNull() },
) { takeProfitOrders, stopLossOrders ->
takeProfitOrders.isNullOrEmpty() && stopLossOrders.isNullOrEmpty()
takeProfitOrders.isEmpty() && stopLossOrders.isEmpty()
}
.distinctUntilChanged()

override fun updatesubmissionStatus(status: AbacusStateManagerProtocol.SubmissionStatus?) {
_submissionStatus.update { status }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ object DydxTriggerOrderInputView : DydxComponent {
val closeAction: (() -> Unit)? = null,
val backHandler: (() -> Unit)? = null,
val validationErrorSection: ValidationErrorSection = ValidationErrorSection.None,
val showLimitPrice: Boolean = true,
) {
companion object {
val preview = ViewState(
Expand Down Expand Up @@ -154,11 +155,13 @@ object DydxTriggerOrderInputView : DydxComponent {
)
}

DydxTriggerOrderLimitPriceSectionView.Content(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = ThemeShapes.HorizontalPadding),
)
if (state.showLimitPrice) {
DydxTriggerOrderLimitPriceSectionView.Content(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = ThemeShapes.HorizontalPadding),
)
}

DydxAnimation.AnimateExpandInOut(
visible = state.validationErrorSection == ValidationErrorSection.LimitPrice,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import exchange.dydx.abacus.state.model.TriggerOrdersInputField
import exchange.dydx.dydxstatemanager.AbacusStateManagerProtocol
import exchange.dydx.dydxstatemanager.stopLossOrders
import exchange.dydx.dydxstatemanager.takeProfitOrders
import exchange.dydx.trading.common.BuildConfig
import exchange.dydx.trading.common.DydxViewModel
import exchange.dydx.trading.common.di.CoroutineScopes
import exchange.dydx.trading.common.formatter.DydxFormatter
Expand All @@ -39,7 +40,9 @@ class DydxTriggerOrderInputViewModel @Inject constructor(
@CoroutineScopes.ViewModel private val viewModelScope: CoroutineScope,
) : ViewModel(), DydxViewModel {

private val marketId: String?
private val marketId: String? = savedStateHandle["marketId"]

private val includeLimitOrders = abacusStateManager.environment?.featureFlags?.isSlTpLimitOrdersEnabled == true || BuildConfig.DEBUG

val state: Flow<DydxTriggerOrderInputView.ViewState?> =
abacusStateManager.state.validationErrors
Expand All @@ -49,8 +52,6 @@ class DydxTriggerOrderInputViewModel @Inject constructor(
.distinctUntilChanged()

init {
marketId = savedStateHandle["marketId"]

if (marketId == null) {
router.navigateBack()
} else {
Expand All @@ -62,8 +63,8 @@ class DydxTriggerOrderInputViewModel @Inject constructor(

combine(
abacusStateManager.state.selectedSubaccountPositionOfMarket(marketId),
abacusStateManager.state.takeProfitOrders(marketId),
abacusStateManager.state.stopLossOrders(marketId),
abacusStateManager.state.takeProfitOrders(marketId, includeLimitOrders),
abacusStateManager.state.stopLossOrders(marketId, includeLimitOrders),
abacusStateManager.state.triggerOrdersInput,
) { position, takeProfitOrders, stopLossOrders, triggerOrdersInput ->
updateAbacusTriggerOrder(
Expand Down Expand Up @@ -118,6 +119,7 @@ class DydxTriggerOrderInputViewModel @Inject constructor(
DydxTriggerOrderInputView.ValidationErrorSection.None
}
} ?: DydxTriggerOrderInputView.ValidationErrorSection.None,
showLimitPrice = includeLimitOrders,
)
}

Expand Down Expand Up @@ -148,10 +150,12 @@ class DydxTriggerOrderInputViewModel @Inject constructor(
formatter.decimalLocaleAgnostic(order.triggerPrice),
TriggerOrdersInputField.takeProfitPrice,
)
abacusStateManager.triggerOrders(
formatter.decimalLocaleAgnostic(order.price),
TriggerOrdersInputField.takeProfitLimitPrice,
)
if (triggerOrdersInput?.takeProfitOrder?.type == OrderType.takeProfitLimit) {
abacusStateManager.triggerOrders(
formatter.decimalLocaleAgnostic(order.price),
TriggerOrdersInputField.takeProfitLimitPrice,
)
}
}
}
} else {
Expand Down Expand Up @@ -184,10 +188,12 @@ class DydxTriggerOrderInputViewModel @Inject constructor(
formatter.decimalLocaleAgnostic(order.triggerPrice),
TriggerOrdersInputField.stopLossPrice,
)
abacusStateManager.triggerOrders(
formatter.decimalLocaleAgnostic(order.price),
TriggerOrdersInputField.stopLossLimitPrice,
)
if (triggerOrdersInput?.stopLossOrder?.type == OrderType.stopLimit) {
abacusStateManager.triggerOrders(
formatter.decimalLocaleAgnostic(order.price),
TriggerOrdersInputField.stopLossLimitPrice,
)
}
}
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import exchange.dydx.trading.feature.trade.streams.MutableTriggerOrderStreaming
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.mapNotNull
import javax.inject.Inject
Expand All @@ -40,7 +41,7 @@ class DydxTriggerOrderSizeViewModel @Inject constructor(
abacusStateManager.state.triggerOrdersInput
.mapNotNull { it?.marketId }
.flatMapLatest {
abacusStateManager.state.selectedSubaccountPositionOfMarket(it)
abacusStateManager.state.selectedSubaccountPositionOfMarket(it).filterNotNull()
},
triggerOrderStream.isNewTriggerOrder,
abacusStateManager.state.triggerOrdersInput,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ class CosmosV4ClientWebview @Inject constructor(
function = functionName,
params = jsParams,
) { result ->
Log.d(TAG, "callNativeClient $functionName result: $result")
Log.d(TAG, "callNativeClient $functionName, params: $params, result: $result")
completion(result?.response)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,34 @@ fun AbacusState.triggerOrders(marketId: String): Flow<List<SubaccountOrder>?> =
}
.distinctUntilChanged()

fun AbacusState.takeProfitOrders(marketId: String): Flow<List<SubaccountOrder>?> =
fun AbacusState.takeProfitOrders(marketId: String, includeLimitOrders: Boolean): Flow<List<SubaccountOrder>?> =
combine(
selectedSubaccountPositionOfMarket(marketId),
triggerOrders(marketId),
) { position, orders ->
orders?.filter { order ->
position?.side?.current?.let { currentSide ->
(order.type == OrderType.takeProfitMarket || order.type == OrderType.takeProfitLimit) &&
(
order.type == OrderType.takeProfitMarket ||
(order.type == OrderType.takeProfitLimit && includeLimitOrders)
) &&
order.side.isOppositeOf(currentSide)
} ?: false
}
}
.distinctUntilChanged()

fun AbacusState.stopLossOrders(marketId: String): Flow<List<SubaccountOrder>?> =
fun AbacusState.stopLossOrders(marketId: String, includeLimitOrders: Boolean): Flow<List<SubaccountOrder>?> =
combine(
selectedSubaccountPositionOfMarket(marketId),
triggerOrders(marketId),
) { position, orders ->
orders?.filter { order ->
position?.side?.current?.let { currentSide ->
(order.type == OrderType.stopMarket || order.type == OrderType.stopLimit) &&
(
order.type == OrderType.stopMarket ||
(order.type == OrderType.stopLimit && includeLimitOrders)
) &&
order.side.isOppositeOf(currentSide)
} ?: false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Scaffold
import androidx.compose.material.Snackbar
import androidx.compose.material.SnackbarDefaults.backgroundColor
import androidx.compose.material.SnackbarDuration
import androidx.compose.material.SnackbarHost
import androidx.compose.material.SnackbarHostState
Expand All @@ -18,7 +17,6 @@ import exchange.dydx.platformui.designSystem.theme.color
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonNull.content

@Composable
fun PlatformInfoScaffold(
Expand Down

0 comments on commit 53bf64b

Please sign in to comment.