Skip to content

Commit

Permalink
TRCL-3643 Static Typing: TransferInput (#630)
Browse files Browse the repository at this point in the history
  • Loading branch information
ruixhuang authored Sep 9, 2024
1 parent 5676bfa commit d9d83fd
Show file tree
Hide file tree
Showing 25 changed files with 1,959 additions and 724 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package exchange.dydx.abacus.calculator
import exchange.dydx.abacus.output.input.InputType
import exchange.dydx.abacus.output.input.OrderType
import exchange.dydx.abacus.output.input.ReceiptLine
import exchange.dydx.abacus.output.input.TransferType
import exchange.dydx.abacus.state.internalstate.InternalInputState
import exchange.dydx.abacus.state.manager.StatsigConfig

internal class ReceiptCalculator {
fun calculate(
Expand Down Expand Up @@ -48,52 +50,47 @@ internal class ReceiptCalculator {
}

InputType.TRANSFER -> {
null // TODO when working with transfer
/*
val transfer = parser.asNativeMap(input["transfer"]) ?: return null
val type = parser.asString(transfer["type"]) ?: return null
return when (type) {
"DEPOSIT", "WITHDRAWAL" -> {
if (StatsigConfig.useSkip) {
listOf(
ReceiptLine.Equity.rawValue,
ReceiptLine.BuyingPower.rawValue,
ReceiptLine.BridgeFee.rawValue,
// add these back when supported by Skip
// ReceiptLine.ExchangeRate.rawValue,
// ReceiptLine.ExchangeReceived.rawValue,
// ReceiptLine.Fee.rawValue,
ReceiptLine.Slippage.rawValue,
ReceiptLine.TransferRouteEstimatedDuration.rawValue,
)
} else {
when (input.transfer.type) {
TransferType.deposit, TransferType.withdrawal -> {
if (StatsigConfig.useSkip) {
listOf(
ReceiptLine.Equity,
ReceiptLine.BuyingPower,
ReceiptLine.BridgeFee,
// add these back when supported by Skip
// ReceiptLine.ExchangeRate,
// ReceiptLine.ExchangeReceived,
// ReceiptLine.Fee,
ReceiptLine.Slippage,
ReceiptLine.TransferRouteEstimatedDuration,
)
} else {
listOf(
ReceiptLine.Equity,
ReceiptLine.BuyingPower,
ReceiptLine.ExchangeRate,
ReceiptLine.ExchangeReceived,
ReceiptLine.Fee,
// ReceiptLine.BridgeFee,
ReceiptLine.Slippage,
ReceiptLine.TransferRouteEstimatedDuration,
)
}
}

TransferType.transferOut -> {
listOf(
ReceiptLine.Equity.rawValue,
ReceiptLine.BuyingPower.rawValue,
ReceiptLine.ExchangeRate.rawValue,
ReceiptLine.ExchangeReceived.rawValue,
ReceiptLine.Fee.rawValue,
// ReceiptLine.BridgeFee.rawValue,
ReceiptLine.Slippage.rawValue,
ReceiptLine.TransferRouteEstimatedDuration.rawValue,
ReceiptLine.Equity,
ReceiptLine.MarginUsage,
ReceiptLine.Fee,
)
}
}

"TRANSFER_OUT" -> {
listOf(
ReceiptLine.Equity.rawValue,
ReceiptLine.MarginUsage.rawValue,
ReceiptLine.Fee.rawValue,
)
}
else -> {
listOf()
else -> {
listOf()
}
}
}
*/
}

InputType.ADJUST_ISOLATED_MARGIN -> {
listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import exchange.dydx.abacus.calculator.CalculationPeriod
import exchange.dydx.abacus.output.TradeStatesWithStringValues
import exchange.dydx.abacus.output.account.SubaccountPositionResources
import exchange.dydx.abacus.output.input.OrderSide
import exchange.dydx.abacus.output.input.TransferType
import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.state.internalstate.InternalMarketState
import exchange.dydx.abacus.state.internalstate.InternalPerpetualPosition
import exchange.dydx.abacus.state.internalstate.InternalPositionCalculated
import exchange.dydx.abacus.state.internalstate.InternalSubaccountCalculated
import exchange.dydx.abacus.state.internalstate.InternalSubaccountState
import exchange.dydx.abacus.state.internalstate.InternalTradeInputState
import exchange.dydx.abacus.state.internalstate.InternalTransferInputState
import exchange.dydx.abacus.state.internalstate.InternalWalletState
import exchange.dydx.abacus.utils.Numeric
import exchange.dydx.abacus.utils.mutable
Expand Down Expand Up @@ -83,6 +85,40 @@ internal class SubaccountTransformerV2(
return wallet
}

fun applyTransferToWallet(
wallet: InternalWalletState,
subaccountNumber: Int?,
transfer: InternalTransferInputState,
parser: ParserProtocol,
period: CalculationPeriod,
): InternalWalletState {
val delta = deltaFromTransfer(transfer) ?: return wallet
val subaccount = wallet.account.subaccounts[subaccountNumber] ?: return wallet

applyDeltaToSubaccount(
subaccount = subaccount,
delta = delta,
period = period,
)
return wallet
}

private fun deltaFromTransfer(
transfer: InternalTransferInputState,
): Delta? {
val type = transfer.type ?: return null
val summary = transfer.summary ?: return null
val multiplier =
(if (type == TransferType.deposit) Numeric.double.POSITIVE else Numeric.double.NEGATIVE)
val usdcSize =
(summary.usdcSize ?: Numeric.double.ZERO) * multiplier
val fee = (summary.fee ?: Numeric.double.ZERO) * Numeric.double.NEGATIVE
return Delta(
usdcSize = usdcSize,
fee = fee,
)
}

private fun deltaFromTrade(
trade: InternalTradeInputState,
market: InternalMarketState?,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package exchange.dydx.abacus.calculator.v2

import exchange.dydx.abacus.calculator.CalculationPeriod
import exchange.dydx.abacus.output.input.TransferInputSummary
import exchange.dydx.abacus.output.input.TransferType
import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.state.internalstate.InternalTransferInputState
import exchange.dydx.abacus.state.internalstate.InternalWalletState

internal class TransferInputCalculatorV2(
private val parser: ParserProtocol,
private val subaccountTransformer: SubaccountTransformerV2 = SubaccountTransformerV2(parser),
) {
fun calculate(
transfer: InternalTransferInputState,
wallet: InternalWalletState,
subaccountNumber: Int?,
): InternalTransferInputState {
if (wallet.isAccountConnected && transfer.type != null) {
finalize(transfer)

subaccountTransformer.applyTransferToWallet(
wallet = wallet,
subaccountNumber = subaccountNumber,
transfer = transfer,
parser = parser,
period = CalculationPeriod.post,
)
}
return transfer
}

private fun finalize(
transfer: InternalTransferInputState,
): InternalTransferInputState {
transfer.summary = summaryForType(transfer)
return transfer
}

private fun summaryForType(
transfer: InternalTransferInputState,
): TransferInputSummary? {
val type = transfer.type ?: return null
when (type) {
TransferType.deposit -> {
val size = parser.asDouble(transfer.size?.size)
var usdcSize = parser.asDouble(transfer.size?.usdcSize)
val fee = parser.asDouble(transfer.fee)

val route = transfer.route

val slippage = parser.asDouble(parser.value(route, "slippage"))
val exchangeRate = parser.asDouble(parser.value(route, "exchangeRate"))
val estimatedRouteDuration = parser.asDouble(parser.value(route, "estimatedRouteDuration"))
val bridgeFee = parser.asDouble(parser.value(route, "bridgeFee"))
val gasFee = parser.asDouble(parser.value(route, "gasFee"))
val toAmount = parser.asDouble(parser.value(route, "toAmount"))
val toAmountMin = parser.asDouble(parser.value(route, "toAmountMin"))
val toAmountUSDC = parser.asDouble(parser.value(route, "toAmountUSDC"))
var aggregatePriceImpact = parser.asDouble(parser.value(route, "aggregatePriceImpact"))
aggregatePriceImpact = if (aggregatePriceImpact != null) aggregatePriceImpact / 100.0 else null

usdcSize = if (usdcSize != null) {
usdcSize
} else if (size != null && exchangeRate != null) {
exchangeRate * size
} else {
null
}

return TransferInputSummary(
filled = true,
fee = fee,
slippage = slippage,
exchangeRate = exchangeRate,
estimatedRouteDuration = estimatedRouteDuration,
usdcSize = usdcSize,
bridgeFee = bridgeFee,
gasFee = gasFee,
toAmount = toAmount,
toAmountMin = toAmountMin,
toAmountUSDC = toAmountUSDC,
aggregatePriceImpact = aggregatePriceImpact,
)
}

TransferType.withdrawal -> {
val usdcSize = parser.asDouble(transfer.size?.usdcSize)
val fee = parser.asDouble(transfer.fee)

val route = transfer.route

val slippage = parser.asDouble(parser.value(route, "slippage"))
val exchangeRate = parser.asDouble(parser.value(route, "exchangeRate"))
val estimatedRouteDuration = parser.asDouble(parser.value(route, "estimatedRouteDuration"))
val bridgeFee = parser.asDouble(parser.value(route, "bridgeFee"))
val gasFee = parser.asDouble(parser.value(route, "gasFee"))
val toAmount = parser.asDouble(parser.value(route, "toAmount"))
val toAmountMin = parser.asDouble(parser.value(route, "toAmountMin"))
val toAmountUSDC = parser.asDouble(parser.value(route, "toAmountUSDC"))
var aggregatePriceImpact = parser.asDouble(parser.value(route, "aggregatePriceImpact"))
aggregatePriceImpact = if (aggregatePriceImpact != null) aggregatePriceImpact / 100.0 else null

return TransferInputSummary(
filled = true,
fee = fee,
slippage = slippage,
exchangeRate = exchangeRate,
estimatedRouteDuration = estimatedRouteDuration,
usdcSize = usdcSize,
bridgeFee = bridgeFee,
gasFee = gasFee,
toAmount = toAmount,
toAmountMin = toAmountMin,
toAmountUSDC = toAmountUSDC,
aggregatePriceImpact = aggregatePriceImpact,
)
}

TransferType.transferOut -> {
val usdcSize = parser.asDouble(transfer.size?.usdcSize)

return TransferInputSummary(
filled = true,
gasFee = transfer.fee,
usdcSize = usdcSize,
fee = null,
slippage = null,
exchangeRate = null,
estimatedRouteDuration = null,
bridgeFee = null,
toAmount = null,
toAmountMin = null,
toAmountUSDC = null,
aggregatePriceImpact = null,
)
}
}
}
}
10 changes: 8 additions & 2 deletions src/commonMain/kotlin/exchange.dydx.abacus/output/input/Input.kt
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,14 @@ data class Input(
ClosePositionInput.create(existing?.closePosition, parser, parser.asMap(data?.get("closePosition")))
}

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

val triggerOrders = if (staticTyping) {
TriggerOrdersInput.create(state = internalState?.input?.triggerOrders)
Expand Down
Loading

0 comments on commit d9d83fd

Please sign in to comment.