Skip to content

Commit

Permalink
TRCL-3672 Static Typing: TradeInputValidator (and its child validator…
Browse files Browse the repository at this point in the history
…s) (#580)

Co-authored-by: mobile-build-bot-git <[email protected]>
  • Loading branch information
ruixhuang and mobile-build-bot authored Aug 22, 2024
1 parent 3d39658 commit f3bc02f
Show file tree
Hide file tree
Showing 29 changed files with 2,284 additions and 558 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,10 @@ internal class TradeInputOptionsCalculator(
}

private fun trailingPercentField(): Map<String, Any> {
return mapOf("field" to "price.trailingPercent", "type" to "double")
return mapOf(
"field" to "price.trailingPercent",
"type" to "double",
)
}

private fun reduceOnlyField(): Map<String, Any>? {
Expand Down
42 changes: 30 additions & 12 deletions src/commonMain/kotlin/exchange.dydx.abacus/output/input/Input.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,40 +48,58 @@ data class Input(
): Input? {
Logger.d { "creating Input\n" }

data?.let {
if (staticTyping || data != null) {
val current = if (staticTyping) {
internalState?.input?.currentType
} else {
InputType.invoke(parser.asString(data["current"]))
InputType.invoke(parser.asString(data?.get("current")))
}

val trade = if (staticTyping) {
TradeInput.create(state = internalState?.input?.trade)
} else {
TradeInput.create(existing?.trade, parser, parser.asMap(data["trade"]))
TradeInput.create(existing?.trade, parser, parser.asMap(data?.get("trade")))
}
val closePosition =
ClosePositionInput.create(existing?.closePosition, parser, parser.asMap(data["closePosition"]))
ClosePositionInput.create(existing?.closePosition, parser, parser.asMap(data?.get("closePosition")))

val transfer =
TransferInput.create(existing?.transfer, parser, parser.asMap(data["transfer"]), environment, internalState?.transfer)
TransferInput.create(existing?.transfer, parser, parser.asMap(data?.get("transfer")), environment, internalState?.transfer)

val triggerOrders =
TriggerOrdersInput.create(existing?.triggerOrders, parser, parser.asMap(data["triggerOrders"]))
TriggerOrdersInput.create(existing?.triggerOrders, parser, parser.asMap(data?.get("triggerOrders")))

val adjustIsolatedMargin =
AdjustIsolatedMarginInput.create(existing?.adjustIsolatedMargin, parser, parser.asMap(data["adjustIsolatedMargin"]))
AdjustIsolatedMarginInput.create(
existing?.adjustIsolatedMargin,
parser,
parser.asMap(
data?.get("adjustIsolatedMargin"),
),
)

val errors =
ValidationError.create(existing?.errors, parser, parser.asList(data["errors"]))
val errors = if (staticTyping) {
internalState?.input?.errors?.toIList()
} else {
ValidationError.create(existing?.errors, parser, parser.asList(data?.get("errors")))
}

val childSubaccountErrors =
ValidationError.create(existing?.childSubaccountErrors, parser, parser.asList(data["childSubaccountErrors"]))
val childSubaccountErrors = if (staticTyping) {
internalState?.input?.childSubaccountErrors?.toIList()
} else {
ValidationError.create(
existing?.childSubaccountErrors,
parser,
parser.asList(
data?.get("childSubaccountErrors"),
),
)
}

val receiptLines = if (staticTyping) {
internalState?.input?.receiptLines?.toIList()
} else {
ReceiptLine.create(parser, parser.asList(data["receiptLines"]))
ReceiptLine.create(parser, parser.asList(data?.get("receiptLines")))
}

return if (existing?.current !== current ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import kollections.iListOf
import kollections.iMutableListOf
import kollections.toIList
import kotlinx.serialization.Serializable
import kotlin.time.Duration
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes

@JsExport
@Serializable
Expand Down Expand Up @@ -595,6 +599,20 @@ data class TradeInputGoodUntil(
val duration: Double?,
val unit: String?,
) {
internal val timeInterval: Duration?
get() =
if (duration != null && unit != null) {
when (unit) {
"M" -> duration.minutes
"H" -> duration.hours
"D" -> duration.days
"W" -> (duration * 7).days
else -> null
}
} else {
null
}

companion object {
internal fun create(
existing: TradeInputGoodUntil?,
Expand Down Expand Up @@ -735,7 +753,7 @@ enum class OrderType(val rawValue: String) {

companion object {
operator fun invoke(rawValue: String?) =
OrderType.values().firstOrNull { it.rawValue == rawValue }
entries.firstOrNull { it.rawValue == rawValue }
}
}

Expand Down Expand Up @@ -837,7 +855,7 @@ data class TradeInput(
fee = state.fee,
marginMode = state.marginMode ?: MarginMode.Cross,
targetLeverage = state.targetLeverage ?: 1.0,
bracket = state.bracket,
bracket = state.brackets,
marketOrder = state.marketOrder,
options = TradeInputOptions.create(state.options),
summary = TradeInputSummary.create(state.summary),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ enum class ErrorType(val rawValue: String) {

companion object {
operator fun invoke(rawValue: String) =
ErrorType.values().firstOrNull { it.rawValue == rawValue }
entries.firstOrNull { it.rawValue == rawValue }
}
}

Expand All @@ -154,7 +154,7 @@ enum class ErrorAction(val rawValue: String) {

companion object {
operator fun invoke(rawValue: String) =
ErrorAction.values().firstOrNull { it.rawValue == rawValue }
entries.firstOrNull { it.rawValue == rawValue }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,15 @@ internal val TradeInputField.valueAction: ((InternalTradeInputState) -> Any?)?
TradeInputField.reduceOnly -> { state -> state.reduceOnly }
TradeInputField.postOnly -> { state -> state.postOnly }

TradeInputField.bracketsStopLossPrice -> { state -> state.bracket?.stopLoss?.triggerPrice }
TradeInputField.bracketsStopLossPercent -> { state -> state.bracket?.stopLoss?.percent }
TradeInputField.bracketsStopLossReduceOnly -> { state -> state.bracket?.stopLoss?.reduceOnly }
TradeInputField.bracketsTakeProfitPrice -> { state -> state.bracket?.takeProfit?.triggerPrice }
TradeInputField.bracketsTakeProfitPercent -> { state -> state.bracket?.takeProfit?.percent }
TradeInputField.bracketsTakeProfitReduceOnly -> { state -> state.bracket?.takeProfit?.reduceOnly }
TradeInputField.bracketsGoodUntilDuration -> { state -> state.bracket?.goodTil?.duration }
TradeInputField.bracketsGoodUntilUnit -> { state -> state.bracket?.goodTil?.unit }
TradeInputField.bracketsExecution -> { state -> state.bracket?.execution }
TradeInputField.bracketsStopLossPrice -> { state -> state.brackets?.stopLoss?.triggerPrice }
TradeInputField.bracketsStopLossPercent -> { state -> state.brackets?.stopLoss?.percent }
TradeInputField.bracketsStopLossReduceOnly -> { state -> state.brackets?.stopLoss?.reduceOnly }
TradeInputField.bracketsTakeProfitPrice -> { state -> state.brackets?.takeProfit?.triggerPrice }
TradeInputField.bracketsTakeProfitPercent -> { state -> state.brackets?.takeProfit?.percent }
TradeInputField.bracketsTakeProfitReduceOnly -> { state -> state.brackets?.takeProfit?.reduceOnly }
TradeInputField.bracketsGoodUntilDuration -> { state -> state.brackets?.goodTil?.duration }
TradeInputField.bracketsGoodUntilUnit -> { state -> state.brackets?.goodTil?.unit }
TradeInputField.bracketsExecution -> { state -> state.brackets?.execution }
}

// Returns the write action to update value for the trade input field
Expand Down Expand Up @@ -110,29 +110,29 @@ internal val TradeInputField.updateValueAction: ((InternalTradeInputState, Strin
}

TradeInputField.bracketsStopLossPrice -> { trade, value, parser ->
val braket = TradeInputBracket.safeCreate(trade.bracket)
val braket = TradeInputBracket.safeCreate(trade.brackets)
val stopLoss = TradeInputBracketSide.safeCreate(braket.stopLoss)
trade.bracket =
trade.brackets =
braket.copy(stopLoss = stopLoss.copy(triggerPrice = parser.asDouble(value)))
}

TradeInputField.bracketsStopLossPercent -> { trade, value, parser ->
val braket = TradeInputBracket.safeCreate(trade.bracket)
val braket = TradeInputBracket.safeCreate(trade.brackets)
val stopLoss = TradeInputBracketSide.safeCreate(braket.stopLoss)
trade.bracket = braket.copy(stopLoss = stopLoss.copy(percent = parser.asDouble(value)))
trade.brackets = braket.copy(stopLoss = stopLoss.copy(percent = parser.asDouble(value)))
}

TradeInputField.bracketsTakeProfitPrice -> { trade, value, parser ->
val braket = TradeInputBracket.safeCreate(trade.bracket)
val braket = TradeInputBracket.safeCreate(trade.brackets)
val takeProfit = TradeInputBracketSide.safeCreate(braket.takeProfit)
trade.bracket =
trade.brackets =
braket.copy(takeProfit = takeProfit.copy(triggerPrice = parser.asDouble(value)))
}

TradeInputField.bracketsTakeProfitPercent -> { trade, value, parser ->
val braket = TradeInputBracket.safeCreate(trade.bracket)
val braket = TradeInputBracket.safeCreate(trade.brackets)
val takeProfit = TradeInputBracketSide.safeCreate(braket.takeProfit)
trade.bracket =
trade.brackets =
braket.copy(takeProfit = takeProfit.copy(percent = parser.asDouble(value)))
}

Expand All @@ -149,8 +149,8 @@ internal val TradeInputField.updateValueAction: ((InternalTradeInputState, Strin
}

TradeInputField.bracketsGoodUntilUnit -> { trade, value, parser ->
val braket = TradeInputBracket.safeCreate(trade.bracket)
trade.bracket = braket.copy(
val braket = TradeInputBracket.safeCreate(trade.brackets)
trade.brackets = braket.copy(
goodTil = TradeInputGoodUntil.safeCreate(braket.goodTil).copy(unit = value),
)
}
Expand All @@ -160,7 +160,7 @@ internal val TradeInputField.updateValueAction: ((InternalTradeInputState, Strin
}

TradeInputField.bracketsExecution -> { trade, value, parser ->
trade.bracket = TradeInputBracket.safeCreate(trade.bracket).copy(execution = value)
trade.brackets = TradeInputBracket.safeCreate(trade.brackets).copy(execution = value)
}

TradeInputField.goodTilDuration -> { trade, value, parser ->
Expand All @@ -169,8 +169,8 @@ internal val TradeInputField.updateValueAction: ((InternalTradeInputState, Strin
}

TradeInputField.bracketsGoodUntilDuration -> { trade, value, parser ->
val braket = TradeInputBracket.safeCreate(trade.bracket)
trade.bracket = braket.copy(
val braket = TradeInputBracket.safeCreate(trade.brackets)
trade.brackets = braket.copy(
goodTil = TradeInputGoodUntil.safeCreate(braket.goodTil)
.copy(duration = parser.asDouble(value)),
)
Expand All @@ -185,16 +185,16 @@ internal val TradeInputField.updateValueAction: ((InternalTradeInputState, Strin
}

TradeInputField.bracketsStopLossReduceOnly -> { trade, value, parser ->
val braket = TradeInputBracket.safeCreate(trade.bracket)
val braket = TradeInputBracket.safeCreate(trade.brackets)
val stopLoss = TradeInputBracketSide.safeCreate(braket.stopLoss)
trade.bracket =
trade.brackets =
braket.copy(stopLoss = stopLoss.copy(reduceOnly = parser.asBool(value) ?: false))
}

TradeInputField.bracketsTakeProfitReduceOnly -> { trade, value, parser ->
val braket = TradeInputBracket.safeCreate(trade.bracket)
val braket = TradeInputBracket.safeCreate(trade.brackets)
val takeProfit = TradeInputBracketSide.safeCreate(braket.takeProfit)
trade.bracket = braket.copy(
trade.brackets = braket.copy(
takeProfit = takeProfit.copy(
reduceOnly = parser.asBool(value) ?: false,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import exchange.dydx.abacus.output.input.TradeInputGoodUntil
import exchange.dydx.abacus.output.input.TradeInputMarketOrder
import exchange.dydx.abacus.output.input.TradeInputPrice
import exchange.dydx.abacus.output.input.TradeInputSize
import exchange.dydx.abacus.output.input.ValidationError
import exchange.dydx.abacus.state.manager.HistoricalTradingRewardsPeriod
import exchange.dydx.abacus.utils.NUM_PARENT_SUBACCOUNTS
import indexer.codegen.IndexerHistoricalBlockTradingReward
Expand All @@ -54,9 +55,20 @@ internal data class InternalState(

internal data class InternalInputState(
var trade: InternalTradeInputState = InternalTradeInputState(),
var currentType: InputType? = null,
var receiptLines: List<ReceiptLine>? = null,
)
var errors: List<ValidationError>? = null,
var childSubaccountErrors: List<ValidationError>? = null,
) {
var currentType: InputType? = null
set(value) {
if (field != value) {
receiptLines = null
errors = null
childSubaccountErrors = null
field = value
}
}
}

internal data class InternalTradeInputState(
var marketId: String? = null,
Expand All @@ -73,7 +85,7 @@ internal data class InternalTradeInputState(
var reduceOnly: Boolean = false,
var postOnly: Boolean = false,
var fee: Double? = null,
var bracket: TradeInputBracket? = null,
var brackets: TradeInputBracket? = null,
var options: InternalTradeInputOptions = InternalTradeInputOptions(),
var marketOrder: TradeInputMarketOrder? = null,
var summary: InternalTradeInputSummary? = null,
Expand Down Expand Up @@ -179,6 +191,8 @@ internal data class InternalUserState(
var takerFeeRate: Double? = null,
var makerVolume30D: Double? = null,
var takerVolume30D: Double? = null,

var restricted: Boolean = false, // TODO: Not being used
)

internal data class InternalAccountState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ enum class TradeInputField(val rawValue: String) {

companion object {
operator fun invoke(rawValue: String?) =
TradeInputField.values().firstOrNull { it.rawValue == rawValue }
entries.firstOrNull { it.rawValue == rawValue }
}

internal val tradeDataOption: String?
Expand Down
Loading

0 comments on commit f3bc02f

Please sign in to comment.