Skip to content

Commit

Permalink
v1.7.38: Handle channel_batch_data for v4_parent_subaccount (#370)
Browse files Browse the repository at this point in the history
Co-authored-by: mike-dydx <[email protected]>
Co-authored-by: Rui <[email protected]>
Co-authored-by: mobile-build-bot-git <[email protected]>
Co-authored-by: mike-dydx <[email protected]>
  • Loading branch information
5 people authored and yogurtandjam committed May 31, 2024
1 parent 50b68fc commit 2b8834c
Show file tree
Hide file tree
Showing 23 changed files with 175 additions and 111 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ allprojects {
}

group = "exchange.dydx.abacus"
version = "1.7.38"
version = "1.7.39"

repositories {
google()
Expand Down
106 changes: 48 additions & 58 deletions integration/iOS/Pods/Pods.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import exchange.dydx.abacus.calculator.SlippageConstants.STOP_MARKET_ORDER_SLIPP
import exchange.dydx.abacus.calculator.SlippageConstants.STOP_MARKET_ORDER_SLIPPAGE_BUFFER_MAJOR_MARKET
import exchange.dydx.abacus.calculator.SlippageConstants.TAKE_PROFIT_MARKET_ORDER_SLIPPAGE_BUFFER
import exchange.dydx.abacus.calculator.SlippageConstants.TAKE_PROFIT_MARKET_ORDER_SLIPPAGE_BUFFER_MAJOR_MARKET
import exchange.dydx.abacus.output.input.MarginMode
import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.state.manager.EnvironmentFeatureFlags
import exchange.dydx.abacus.utils.Numeric
Expand Down Expand Up @@ -363,12 +364,9 @@ internal class TradeInputCalculator(
when (marginMode) {
"ISOLATED" -> {
// TODO: When the collateral of child subaccounts is implemented, return from here. The below code is the CROSS implementation.
val currentNotionalTotal =
parser.asDouble(parser.value(position, "notionalTotal.current"))
val postOrderNotionalTotal =
parser.asDouble(parser.value(position, "notionalTotal.postOrder"))
val mmf =
parser.asDouble(parser.value(market, "configs.maintenanceMarginFraction"))
val currentNotionalTotal = parser.asDouble(parser.value(position, "notionalTotal.current"))
val postOrderNotionalTotal = parser.asDouble(parser.value(position, "notionalTotal.postOrder"))
val mmf = parser.asDouble(parser.value(market, "configs.maintenanceMarginFraction"))
if (currentNotionalTotal != null && mmf != null) {
if (postOrderNotionalTotal != null) {
return postOrderNotionalTotal.times(mmf)
Expand Down Expand Up @@ -874,14 +872,24 @@ internal class TradeInputCalculator(
): List<Any>? {
val type = parser.asString(trade["type"])
return when (type) {
"MARKET" ->
listOf(
sizeField(),
leverageField(),
bracketsField(),
marginModeField(market, account, subaccount),
reduceOnlyField(),
).filterNotNull()
"MARKET" -> {
val marginMode = parser.asString(trade["marginMode"])
return when (MarginMode.invoke(marginMode)) {
MarginMode.isolated -> listOf(
sizeField(),
bracketsField(),
marginModeField(market, account, subaccount),
reduceOnlyField(),
).filterNotNull()
else -> listOf(
sizeField(),
leverageField(),
bracketsField(),
marginModeField(market, account, subaccount),
reduceOnlyField(),
).filterNotNull()
}
}

"LIMIT" -> {
val timeInForce = parser.asString(trade["timeInForce"])
Expand Down
14 changes: 12 additions & 2 deletions src/commonMain/kotlin/exchange.dydx.abacus/output/Account.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package exchange.dydx.abacus.output

import exchange.dydx.abacus.output.input.MarginMode
import exchange.dydx.abacus.output.input.OrderSide
import exchange.dydx.abacus.output.input.OrderStatus
import exchange.dydx.abacus.output.input.OrderTimeInForce
Expand Down Expand Up @@ -255,6 +256,7 @@ data class SubaccountPosition(
val marginUsage: TradeStatesWithDoubleValues,
val quoteBalance: TradeStatesWithDoubleValues, // available for isolated market position
val equity: TradeStatesWithDoubleValues, // available for isolated market position
val marginMode: MarginMode?
) {
companion object {
internal fun create(
Expand Down Expand Up @@ -383,6 +385,7 @@ data class SubaccountPosition(
parser,
parser.asMap(data["equity"]),
)
val marginMode = parser.asString(data["marginMode"])?.let { MarginMode.invoke(it) }

return if (existing?.id != id ||
existing.assetId != assetId ||
Expand Down Expand Up @@ -410,7 +413,8 @@ data class SubaccountPosition(
existing.freeCollateral !== freeCollateral ||
existing.marginUsage !== marginUsage ||
existing.quoteBalance !== quoteBalance ||
existing.equity !== equity
existing.equity !== equity ||
existing.marginMode != marginMode
) {
val side = positionSide(size)
SubaccountPosition(
Expand Down Expand Up @@ -442,6 +446,7 @@ data class SubaccountPosition(
marginUsage,
quoteBalance,
equity,
marginMode,
)
} else {
existing
Expand Down Expand Up @@ -662,6 +667,7 @@ data class SubaccountOrder(
val reduceOnly: Boolean,
val cancelReason: String?,
val resources: SubaccountOrderResources,
val marginMode: MarginMode?
) {
companion object {
internal fun create(
Expand Down Expand Up @@ -695,6 +701,7 @@ data class SubaccountOrder(
val resources = parser.asMap(data["resources"])?.let {
SubaccountOrderResources.create(existing?.resources, parser, it, localizer)
}
val marginMode = parser.asString(data["marginMode"])?.let { MarginMode.invoke(it) }
if (id != null && marketId != null && type != null && side != null && status != null && price != null && size != null &&
resources != null
) {
Expand Down Expand Up @@ -744,7 +751,9 @@ data class SubaccountOrder(
existing.postOnly != postOnly ||
existing.reduceOnly != reduceOnly ||
existing.cancelReason != cancelReason ||
existing.resources !== resources
existing.resources !== resources ||
existing.subaccountNumber != subaccountNumber ||
existing.marginMode != marginMode
) {
SubaccountOrder(
subaccountNumber,
Expand Down Expand Up @@ -774,6 +783,7 @@ data class SubaccountOrder(
reduceOnly,
cancelReason,
resources,
marginMode,
)
} else {
existing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,13 +299,14 @@ internal open class SubaccountProcessor(parser: ParserProtocol) : BaseProcessor(
modified = transform(modified, payload, "current", currentAccountKeyMap)

if (firstTime) {
val subaccountNumber = parser.asInt(modified["subaccountNumber"])
val openPerpetualPositionsData =
(
parser.asNativeMap(payload["openPositions"])
?: parser.asNativeMap(payload["openPerpetualPositions"])
)

val positions = perpetualPositionsProcessor.received(openPerpetualPositionsData)
val positions = perpetualPositionsProcessor.received(openPerpetualPositionsData, subaccountNumber)
modified.safeSet(
"positions",
positions,
Expand Down Expand Up @@ -371,12 +372,14 @@ internal open class SubaccountProcessor(parser: ParserProtocol) : BaseProcessor(
payload: List<Any>?,
height: BlockAndTime?,
): Map<String, Any> {
val subaccountNumber = parser.asInt(subaccount["subaccountNumber"])
return if (payload != null) {
val modified = subaccount.mutable()
val transformed = ordersProcessor.received(
parser.asNativeMap(subaccount["orders"]),
payload,
height,
subaccountNumber,
)
modified.safeSet("orders", transformed)
modified
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package exchange.dydx.abacus.processor.wallet.account

import exchange.dydx.abacus.output.input.MarginMode
import exchange.dydx.abacus.processor.base.BaseProcessor
import exchange.dydx.abacus.processor.utils.OrderTypeProcessor
import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.state.manager.BlockAndTime
import exchange.dydx.abacus.utils.NUM_PARENT_SUBACCOUNTS
import exchange.dydx.abacus.utils.Numeric
import exchange.dydx.abacus.utils.mutable
import exchange.dydx.abacus.utils.safeSet
Expand Down Expand Up @@ -202,6 +204,11 @@ internal class OrderProcessor(parser: ParserProtocol) : BaseProcessor(parser) {
if (modified["id"] == null) {
modified.safeSet("id", payload["clientId"])
}
parser.asInt(modified["subaccountNumber"])?.run {
modified.safeSet("subaccountNumber", this)
// the v4_parent_subaccount message has subaccountNumber available but v4_orders does not
modified.safeSet("marginMode", if (this >= NUM_PARENT_SUBACCOUNTS) MarginMode.isolated.rawValue else MarginMode.cross.rawValue)
}
val size = parser.asDouble(payload["size"])
if (size != null) {
var totalFilled = parser.asDouble(payload["totalFilled"])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import exchange.dydx.abacus.processor.base.BaseProcessor
import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.state.manager.BlockAndTime
import exchange.dydx.abacus.utils.mutable
import exchange.dydx.abacus.utils.safeSet
import exchange.dydx.abacus.utils.typedSafeSet

internal class OrdersProcessor(parser: ParserProtocol) : BaseProcessor(parser) {
Expand All @@ -12,16 +13,24 @@ internal class OrdersProcessor(parser: ParserProtocol) : BaseProcessor(parser) {
internal fun received(
existing: Map<String, Any>?,
payload: List<Any>?,
height: BlockAndTime?
height: BlockAndTime?,
subaccountNumber: Int?,
): Map<String, Any>? {
return if (payload != null) {
val orders = existing?.mutable() ?: mutableMapOf<String, Any>()
for (data in payload) {
parser.asNativeMap(data)?.let { data ->
val orderId = parser.asString(data["id"] ?: data["clientId"])
val modified = data.toMutableMap()
val orderSubaccountNumber = parser.asInt(data["subaccountNumber"])

if (orderSubaccountNumber == null) {
modified.safeSet("subaccountNumber", subaccountNumber)
}

if (orderId != null) {
val existing = parser.asNativeMap(orders[orderId])
val order = itemProcessor.received(existing, data, height)
val order = itemProcessor.received(existing, modified, height)
orders.typedSafeSet(orderId, order)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package exchange.dydx.abacus.processor.wallet.account

import abs
import exchange.dydx.abacus.output.input.MarginMode
import exchange.dydx.abacus.processor.base.BaseProcessor
import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.utils.NUM_PARENT_SUBACCOUNTS
import exchange.dydx.abacus.utils.Numeric
import exchange.dydx.abacus.utils.ParsingHelper
import exchange.dydx.abacus.utils.safeSet
Expand Down Expand Up @@ -106,7 +108,7 @@ internal class PerpetualPositionProcessor(parser: ParserProtocol) : BaseProcesso

override fun received(
existing: Map<String, Any>?,
payload: Map<String, Any>
payload: Map<String, Any>,
): Map<String, Any> {
var modified = transform(existing, payload, positionKeyMap)
modified = transform(modified, payload, "current", currentPositionKeyMap)
Expand All @@ -115,6 +117,13 @@ internal class PerpetualPositionProcessor(parser: ParserProtocol) : BaseProcesso
val sizeMap = size(parser.asNativeMap(payload["size"]), size, parser.asString(payload["side"]))
modified.safeSet("size", sizeMap)

parser.asInt(payload["subaccountNumber"])?.run {
modified.safeSet("subaccountNumber", this)

// the v4_parent_subaccount message has subaccountNumber available but v4_orders does not
modified.safeSet("marginMode", if (this >= NUM_PARENT_SUBACCOUNTS) MarginMode.isolated.rawValue else MarginMode.cross.rawValue)
}

ParsingHelper.asset(parser.asString(modified["id"]))?.let {
modified["assetId"] = it
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,28 @@ package exchange.dydx.abacus.processor.wallet.account

import exchange.dydx.abacus.processor.base.BaseProcessor
import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.utils.modify
import exchange.dydx.abacus.utils.mutable
import exchange.dydx.abacus.utils.safeSet

internal class PerpetualPositionsProcessor(parser: ParserProtocol) : BaseProcessor(parser) {
private val itemProcessor = PerpetualPositionProcessor(parser = parser)

internal fun received(payload: Map<String, Any>?): Map<String, Any>? {
internal fun received(
payload: Map<String, Any>?,
subaccountNumber: Int?,
): Map<String, Any>? {
if (payload != null) {
val result = mutableMapOf<String, Any>()
for ((key, value) in payload) {
parser.asNativeMap(value)?.let { value ->
val item = itemProcessor.received(null, value)
parser.asNativeMap(value)?.let { data ->

var modifiedData = data.toMutableMap()
subaccountNumber?.run {
modifiedData.modify("subaccountNumber", subaccountNumber)
}

val item = itemProcessor.received(null, modifiedData)
result.safeSet(key, item)
}
}
Expand Down
Loading

0 comments on commit 2b8834c

Please sign in to comment.