Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.7.22: AdjustIsolatedMargin, Add AmountPercent and fix summary + fields #359

Merged
merged 18 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.21"
version = "1.7.22"

repositories {
google()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal class AdjustIsolatedMarginInputCalculator(val parser: ParserProtocol) {
IsolatedMarginAdjustmentType.valueOf(it)
} ?: IsolatedMarginAdjustmentType.Add

return if (wallet != null && isolatedMarginAdjustment != null && type != null) {
return if (wallet != null && isolatedMarginAdjustment != null) {
val modified = state.mutable()
val parentTransferDelta = getModifiedTransferDelta(isolatedMarginAdjustment, true)
val childTransferDelta = getModifiedTransferDelta(isolatedMarginAdjustment, false)
Expand All @@ -44,8 +44,8 @@ internal class AdjustIsolatedMarginInputCalculator(val parser: ParserProtocol) {
"postOrder",
)

val modifiedParentSubaccount = parser.asNativeMap(parser.value(walletPostChildSubaccountTransfer, "accounts.subaccounts.$parentSubaccountNumber"))
val modifiedChildSubaccount = parser.asNativeMap(parser.value(walletPostChildSubaccountTransfer, "accounts.subaccounts.$childSubaccountNumber"))
val modifiedParentSubaccount = parser.asNativeMap(parser.value(walletPostChildSubaccountTransfer, "account.subaccounts.$parentSubaccountNumber"))
val modifiedChildSubaccount = parser.asNativeMap(parser.value(walletPostChildSubaccountTransfer, "account.subaccounts.$childSubaccountNumber"))
val modifiedIsolatedMarginAdjustment = finalize(isolatedMarginAdjustment, modifiedParentSubaccount, modifiedChildSubaccount, type)

modified["adjustIsolatedMargin"] = modifiedIsolatedMarginAdjustment
Expand Down Expand Up @@ -94,13 +94,13 @@ internal class AdjustIsolatedMarginInputCalculator(val parser: ParserProtocol) {
type: IsolatedMarginAdjustmentType,
): Map<String, Any> {
val summary = mutableMapOf<String, Any>()
val crossCollateral = parser.asDouble(parser.value(parentSubaccount, "freeCollateral.postOrder"))
val crossMarginUsage = parser.asDouble(parser.value(parentSubaccount, "marginUsage.postOrder"))
val crossCollateral = parentSubaccount?.get("freeCollateral")
val crossMarginUsage = parentSubaccount?.get("marginUsage")
val openPositions = parser.asNativeMap(childSubaccount?.get("openPositions"))
val marketId = openPositions?.keys?.firstOrNull()
val positionMargin = parser.asDouble(parser.value(childSubaccount, "freeCollateral.postOrder"))
val positionLeverage = parser.asDouble(parser.value(childSubaccount, "openPositions.$marketId.leverage.postOrder"))
val liquidationPrice = parser.asDouble(parser.value(childSubaccount, "openPositions.$marketId.liquidationPrice.postOrder"))
val positionMargin = childSubaccount?.get("freeCollateral")
val positionLeverage = parser.value(childSubaccount, "openPositions.$marketId.leverage")
val liquidationPrice = parser.value(childSubaccount, "openPositions.$marketId.liquidationPrice")

when (type) {
IsolatedMarginAdjustmentType.Add -> {
Expand All @@ -123,13 +123,51 @@ internal class AdjustIsolatedMarginInputCalculator(val parser: ParserProtocol) {
return summary
}

private fun amountField(): Map<String, Any> {
return mapOf(
"field" to "amount",
"type" to "double",
)
}

private fun requiredFields(): List<Any> {
return listOf(
amountField(),
)
}

private fun calculatedOptionsFromField(fields: List<Any>?): Map<String, Any>? {
fields?.let {
val options = mutableMapOf<String, Any>(
"needsSize" to false,
)

for (item in fields) {
parser.asNativeMap(item)?.let { field ->
when (parser.asString(field["field"])) {
"amount" -> {
options["needsSize"] = true
}
}
}
}

return options
}

return null
}

private fun finalize(
isolatedMarginAdjustment: Map<String, Any>,
parentSubaccount: Map<String, Any>?,
childSubaccount: Map<String, Any>?,
type: IsolatedMarginAdjustmentType,
): Map<String, Any> {
val modified = isolatedMarginAdjustment.mutable()
val fields = requiredFields()
modified.safeSet("fields", fields)
modified.safeSet("options", calculatedOptionsFromField(fields))
modified.safeSet("summary", summaryForType(parentSubaccount, childSubaccount, type))
return modified
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,15 @@ data class AdjustIsolatedMarginInputOptions(
@Serializable
data class AdjustIsolatedMarginInputSummary(
val crossFreeCollateral: Double?,
val crossFreeCollateralUpdated: Double?,
val crossMarginUsage: Double?,
val crossMarginUsageUpdated: Double?,
val positionMargin: Double?,
val positionMarginUpdated: Double?,
val positionLeverage: Double?,
val positionLeverageUpdated: Double?,
val liquidationPrice: Double?,
val liquidationPriceUpdated: Double?,
) {
companion object {
internal fun create(
Expand All @@ -52,25 +57,40 @@ data class AdjustIsolatedMarginInputSummary(
Logger.d { "creating Adjust Isolated Margin Input Summary\n" }

data?.let {
val crossFreeCollateral = parser.asDouble(data["crossFreeCollateral"])
val crossMarginUsage = parser.asDouble(data["crossMarginUsage"])
val positionMargin = parser.asDouble(data["positionMargin"])
val positionLeverage = parser.asDouble(data["positionLeverage"])
val liquidationPrice = parser.asDouble(data["liquidationPrice"])
val crossFreeCollateral = parser.asDouble(parser.value(data, "crossFreeCollateral.current"))
val crossFreeCollateralUpdated = parser.asDouble(parser.value(data, "crossFreeCollateral.postOrder"))
val crossMarginUsage = parser.asDouble(parser.value(data, "crossMarginUsage.current"))
val crossMarginUsageUpdated = parser.asDouble(parser.value(data, "crossMarginUsage.postOrder"))
val positionMargin = parser.asDouble(parser.value(data, "positionMargin.current"))
val positionMarginUpdated = parser.asDouble(parser.value(data, "positionMargin.postOrder"))
val positionLeverage = parser.asDouble(parser.value(data, "positionLeverage.current"))
val positionLeverageUpdated = parser.asDouble(parser.value(data, "positionLeverage.postOrder"))
val liquidationPrice = parser.asDouble(parser.value(data, "liquidationPrice.current"))
val liquidationPriceUpdated = parser.asDouble(parser.value(data, "liquidationPrice.postOrder"))

return if (
existing?.crossFreeCollateral != crossFreeCollateral ||
existing?.crossFreeCollateralUpdated != crossFreeCollateralUpdated ||
existing?.crossMarginUsage != crossMarginUsage ||
existing?.crossMarginUsageUpdated != crossMarginUsageUpdated ||
existing?.positionMargin != positionMargin ||
existing?.positionMarginUpdated != positionMarginUpdated ||
existing?.positionLeverage != positionLeverage ||
existing?.liquidationPrice != liquidationPrice
existing?.positionLeverageUpdated != positionLeverageUpdated ||
existing?.liquidationPrice != liquidationPrice ||
existing?.liquidationPriceUpdated != liquidationPriceUpdated
) {
AdjustIsolatedMarginInputSummary(
crossFreeCollateral,
crossFreeCollateralUpdated,
crossMarginUsage,
crossMarginUsageUpdated,
positionMargin,
positionMarginUpdated,
positionLeverage,
positionLeverageUpdated,
liquidationPrice,
liquidationPriceUpdated,
)
} else {
existing
Expand All @@ -94,12 +114,10 @@ enum class IsolatedMarginAdjustmentType {
data class AdjustIsolatedMarginInput(
val type: IsolatedMarginAdjustmentType,
val amount: String?,
val amountPercent: String?,
val childSubaccountNumber: Int?,
val adjustIsolatedMarginInputOptions: AdjustIsolatedMarginInputOptions?,
val summary: AdjustIsolatedMarginInputSummary?,
val errors: String?,
val errorMessage: String?,
val fee: Double?,
val summary: AdjustIsolatedMarginInputSummary?
) {
companion object {
internal fun create(
Expand All @@ -116,48 +134,34 @@ data class AdjustIsolatedMarginInput(

val childSubaccountNumber = parser.asInt(data["ChildSubaccountNumber"])
val amount = parser.asString(data["Amount"])
val fee = parser.asDouble(data["fee"])
val amountPercent = parser.asString(data["AmountPercent"])

val adjustIsolatedMarginInputOptions = AdjustIsolatedMarginInputOptions.create(
existing?.adjustIsolatedMarginInputOptions,
parser,
parser.asMap(data["adjustIsolatedMarginInputOptions"]),
parser.asMap(data["options"]),
)
val summary = AdjustIsolatedMarginInputSummary.create(
existing?.summary,
parser,
parser.asMap(data["summary"]),
)

val errors = parser.asString(data["errors"])

val errorMessage: String? =
if (errors != null) {
val errorArray = parser.decodeJsonArray(errors)
val firstError = parser.asMap(errorArray?.first())
parser.asString(firstError?.get("message"))
} else {
null
}

return if (
existing?.type != type ||
existing.amount != amount ||
existing.amountPercent != amountPercent ||
existing.childSubaccountNumber != childSubaccountNumber ||
existing.adjustIsolatedMarginInputOptions != adjustIsolatedMarginInputOptions ||
existing.summary !== summary ||
existing.errors !== errors ||
existing.errorMessage != errorMessage ||
existing.fee != fee
existing.summary !== summary
) {
AdjustIsolatedMarginInput(
type,
amount,
amountPercent,
childSubaccountNumber,
adjustIsolatedMarginInputOptions,
summary,
errors,
errorMessage,
fee,
)
} else {
existing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2244,7 +2244,7 @@ open class StateManagerAdaptor(
val walletAddress = wallet.walletAddress ?: error("walletAddress is null")
val isolatedMarginAdjustment = stateMachine.state?.input?.adjustIsolatedMargin
?: error("isolatedMarginAdjustment is null")
val amount = isolatedMarginAdjustment.amount ?: error("amount is null")
val amount = parser.asString(isolatedMarginAdjustment.amount) ?: error("amount is null")
val childSubaccountNumber = isolatedMarginAdjustment.childSubaccountNumber
?: error("childSubaccountNumber is null")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import exchange.dydx.abacus.responses.ParsingError
import exchange.dydx.abacus.responses.StateResponse
import exchange.dydx.abacus.state.changes.Changes
import exchange.dydx.abacus.state.changes.StateChanges
import exchange.dydx.abacus.utils.IList
import exchange.dydx.abacus.utils.NUM_PARENT_SUBACCOUNTS
import exchange.dydx.abacus.utils.mutable
import exchange.dydx.abacus.utils.mutableMapOf
Expand All @@ -19,6 +20,7 @@ import kotlinx.serialization.Serializable
enum class AdjustIsolatedMarginInputField {
Type,
Amount,
AmountPercent,
ChildSubaccountNumber,
}

Expand Down Expand Up @@ -64,37 +66,59 @@ fun TradingStateMachine.adjustIsolatedMargin(
if (adjustIsolatedMargin["Type"] != parser.asString(data)) {
adjustIsolatedMargin.safeSet(type.name, parser.asString(data))
adjustIsolatedMargin.safeSet("Amount", null)
adjustIsolatedMargin.safeSet("AmountPercent", null)
}
changes = StateChanges(
iListOf(Changes.wallet, Changes.subaccount, Changes.input),
null,
subaccountNumbers,
)
changes = getStateChanges(subaccountNumbers)
}
AdjustIsolatedMarginInputField.AmountPercent,
AdjustIsolatedMarginInputField.Amount -> {
val amount = parser.asString(data)
adjustIsolatedMargin.safeSet(type.name, amount)
changes = StateChanges(
iListOf(Changes.wallet, Changes.subaccount, Changes.input),
null,
subaccountNumbers,
val isolatedMarginAdjustmentType = adjustIsolatedMargin["Type"] ?: IsolatedMarginAdjustmentType.Add.name
val subaccountNumber = if (isolatedMarginAdjustmentType == IsolatedMarginAdjustmentType.Add.name) {
parentSubaccountNumber
} else {
childSubaccountNumber
}
val subaccount = parser.asNativeMap(
parser.value(this.account, "subaccounts.$subaccountNumber"),
)

val freeCollateral = parser.asDouble(parser.value(subaccount, "freeCollateral.current"))
val amountValue = parser.asDouble(data)

if (amountValue == null) {
adjustIsolatedMargin.safeSet("Amount", null)
adjustIsolatedMargin.safeSet("AmountPercent", null)
} else if (type == AdjustIsolatedMarginInputField.Amount) {
adjustIsolatedMargin.safeSet(type.name, amountValue.toString())

if (freeCollateral != null) {
val amountPercent = amountValue / freeCollateral
adjustIsolatedMargin.safeSet("AmountPercent", amountPercent.toString())
} else {
adjustIsolatedMargin.safeSet("AmountPercent", null)
}
} else if (type == AdjustIsolatedMarginInputField.AmountPercent) {
adjustIsolatedMargin.safeSet(type.name, amountValue.toString())

if (freeCollateral != null) {
val amount = amountValue * freeCollateral
adjustIsolatedMargin.safeSet("Amount", amount.toString())
} else {
adjustIsolatedMargin.safeSet("Amount", null)
}
}

changes = getStateChanges(subaccountNumbers)
}
AdjustIsolatedMarginInputField.ChildSubaccountNumber -> {
val childSubaccountNumber = parser.asInt(data)
adjustIsolatedMargin.safeSet(type.name, childSubaccountNumber)
val subaccountNumbers = if (childSubaccountNumber != null) {
iListOf(parentSubaccountNumber, childSubaccountNumber)
} else {
iListOf(parentSubaccountNumber)
var updatedSubaccountNumbers = iListOf(parentSubaccountNumber)
val updatedChildSubaccountNumber = parser.asInt(data)
adjustIsolatedMargin.safeSet(type.name, updatedChildSubaccountNumber)
if (updatedChildSubaccountNumber != null) {
updatedSubaccountNumbers = iListOf(parentSubaccountNumber, updatedChildSubaccountNumber)
}
changes = StateChanges(
iListOf(Changes.wallet, Changes.subaccount, Changes.input),
null,
subaccountNumbers,
)
changes = getStateChanges(updatedSubaccountNumbers)
}
else -> {}
}
} else {
error = cannotModify(type.name)
Expand All @@ -113,6 +137,16 @@ fun TradingStateMachine.adjustIsolatedMargin(
return StateResponse(state, changes, if (error != null) iListOf(error) else null)
}

fun getStateChanges(
subaccountNumbers: IList<Int>,
): StateChanges {
return StateChanges(
iListOf(Changes.wallet, Changes.subaccount, Changes.input),
null,
subaccountNumbers,
)
}

fun TradingStateMachine.validAdjustIsolatedMarginInput(
adjustIsolatedMargin: Map<String, Any>,
parentSubaccountNumber: Int?,
Expand All @@ -130,6 +164,10 @@ fun TradingStateMachine.validAdjustIsolatedMarginInput(
val amount = parser.asDouble(adjustIsolatedMargin["Amount"])
return amount == null || amount > 0
}
AdjustIsolatedMarginInputField.AmountPercent.name -> {
val amountPercent = parser.asDouble(adjustIsolatedMargin["AmountPercent"])
return amountPercent == null || amountPercent > 0
}
AdjustIsolatedMarginInputField.ChildSubaccountNumber.name -> {
val childSubaccountNumber = parser.asInt(adjustIsolatedMargin["ChildSubaccountNumber"])
return childSubaccountNumber == null || childSubaccountNumber % NUM_PARENT_SUBACCOUNTS == parentSubaccountNumber
Expand Down
Loading
Loading