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

Static Typing: Transfer resources POC #364

Merged
merged 12 commits into from
May 29, 2024
2 changes: 1 addition & 1 deletion detekt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ complexity:
LargeClass:
threshold: 1000 # up from 600
LongMethod:
threshold: 100 # up from 60
active: false
TooManyFunctions:
active: false
NestedBlockDepth:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package exchange.dydx.abacus.output.input

import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.state.internalstate.InternalState
import exchange.dydx.abacus.state.manager.V4Environment
import exchange.dydx.abacus.utils.IList
import exchange.dydx.abacus.utils.Logger
Expand Down Expand Up @@ -39,7 +40,8 @@ data class Input(
existing: Input?,
parser: ParserProtocol,
data: Map<*, *>?,
environment: V4Environment?
environment: V4Environment?,
internalState: InternalState?
): Input? {
Logger.d { "creating Input\n" }

Expand All @@ -50,7 +52,7 @@ data class Input(
val closePosition =
ClosePositionInput.create(existing?.closePosition, parser, parser.asMap(data["closePosition"]))
val transfer =
TransferInput.create(existing?.transfer, parser, parser.asMap(data["transfer"]), environment)
TransferInput.create(existing?.transfer, parser, parser.asMap(data["transfer"]), environment, internalState?.transfer)
val triggerOrders =
TriggerOrdersInput.create(existing?.triggerOrders, parser, parser.asMap(data["triggerOrders"]))
val adjustIsolatedMargin =
Expand Down
181 changes: 21 additions & 160 deletions src/commonMain/kotlin/exchange.dydx.abacus/output/input/TransferInput.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package exchange.dydx.abacus.output.input

import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.state.internalstate.InternalTransferInputState
import exchange.dydx.abacus.state.manager.CctpConfig.cctpChainIds
import exchange.dydx.abacus.state.manager.ExchangeConfig.exchangeList
import exchange.dydx.abacus.state.manager.V4Environment
Expand Down Expand Up @@ -30,7 +31,8 @@ data class DepositInputOptions(
internal fun create(
existing: DepositInputOptions?,
parser: ParserProtocol,
data: Map<*, *>?
data: Map<*, *>?,
internalState: InternalTransferInputState?
): DepositInputOptions? {
Logger.d { "creating Deposit Input Options\n" }

Expand All @@ -39,35 +41,9 @@ data class DepositInputOptions(
val needsAddress = parser.asBool(data["needsAddress"])
val needsFastSpeed = parser.asBool(data["needsFastSpeed"])

var chains: IMutableList<SelectionOption>? = null
parser.asList(data["chains"])?.let { data ->
chains = iMutableListOf()
for (i in data.indices) {
val item = data[i]
SelectionOption.create(
existing?.chains?.getOrNull(i),
parser,
parser.asMap(item),
)?.let {
chains?.add(it)
}
}
}
val chains: IList<SelectionOption>? = internalState?.chains?.toIList() ?: iListOf()

var assets: IMutableList<SelectionOption>? = null
parser.asList(data["assets"])?.let { data ->
assets = iMutableListOf()
for (i in data.indices) {
val item = data[i]
SelectionOption.create(
existing?.assets?.getOrNull(i),
parser,
parser.asMap(item),
)?.let {
assets?.add(it)
}
}
}
val assets: IList<SelectionOption>? = internalState?.tokens?.toIList() ?: iListOf()

var exchanges: IMutableList<SelectionOption>? = null
exchangeList?.let { data ->
Expand Down Expand Up @@ -118,7 +94,8 @@ data class WithdrawalInputOptions(
internal fun create(
existing: WithdrawalInputOptions?,
parser: ParserProtocol,
data: Map<*, *>?
data: Map<*, *>?,
internalState: InternalTransferInputState?,
): WithdrawalInputOptions? {
Logger.d { "creating Withdrawal Input Options\n" }

Expand All @@ -127,34 +104,9 @@ data class WithdrawalInputOptions(
val needsAddress = parser.asBool(data["needsAddress"])
val needsFastSpeed = parser.asBool(data["needsFastSpeed"])

var chains: IMutableList<SelectionOption>? = null
parser.asList(data["chains"])?.let { data ->
chains = iMutableListOf()
for (i in data.indices) {
val item = data[i]
SelectionOption.create(
existing?.chains?.getOrNull(i),
parser,
parser.asMap(item),
)?.let {
chains?.add(it)
}
}
}
var assets: IMutableList<SelectionOption>? = null
parser.asList(data["assets"])?.let { data ->
assets = iMutableListOf()
for (i in data.indices) {
val item = data[i]
SelectionOption.create(
existing?.assets?.getOrNull(i),
parser,
parser.asMap(item),
)?.let {
assets?.add(it)
}
}
}
val chains: IList<SelectionOption>? = internalState?.chains?.toIList() ?: iListOf()

val assets: IList<SelectionOption>? = internalState?.tokens?.toIList() ?: iListOf()

var exchanges: IMutableList<SelectionOption>? = null
exchangeList?.let { data ->
Expand Down Expand Up @@ -260,44 +212,7 @@ data class TransferInputChainResource(
val networkName: String?,
val chainId: Int?,
val iconUrl: String?
) {
companion object {
internal fun create(
existing: TransferInputChainResource?,
parser: ParserProtocol,
data: Map<*, *>?
): TransferInputChainResource? {
Logger.d { "creating Transfer Input Chain Resource\n" }

data?.let {
val chainName = parser.asString(data["chainName"])
val rpc = parser.asString(data["rpc"])
val networkName = parser.asString(data["networkName"])
val chainId = parser.asInt(data["chainId"])
val iconUrl = parser.asString(data["iconUrl"])

return if (existing?.chainName != chainName ||
existing?.rpc != rpc ||
existing?.networkName != networkName ||
existing?.chainId != chainId ||
existing?.iconUrl != iconUrl
) {
TransferInputChainResource(
chainName,
rpc,
networkName,
chainId,
iconUrl,
)
} else {
existing
}
}
Logger.d { "Transfer Input Chain Resource not valid" }
return null
}
}
}
)

@JsExport
@Serializable
Expand All @@ -307,44 +222,7 @@ data class TransferInputTokenResource(
var symbol: String?,
var decimals: Int?,
var iconUrl: String?
) {
companion object {
internal fun create(
existing: TransferInputTokenResource?,
parser: ParserProtocol,
data: Map<*, *>?
): TransferInputTokenResource? {
Logger.d { "creating Transfer Input Token Resource\n" }

data?.let {
val name = parser.asString(data["name"])
val address = parser.asString(data["address"])
val symbol = parser.asString(data["symbol"])
val decimals = parser.asInt(data["decimals"])
val iconUrl = parser.asString(data["iconUrl"])

return if (existing?.name != name ||
existing?.address != address ||
existing?.symbol != symbol ||
existing?.decimals != decimals ||
existing?.iconUrl != iconUrl
) {
TransferInputTokenResource(
name,
address,
symbol,
decimals,
iconUrl,
)
} else {
existing
}
}
Logger.d { "Transfer Input Token Resource not valid" }
return null
}
}
}
)

@JsExport
@Serializable
Expand All @@ -355,32 +233,13 @@ data class TransferInputResources(
companion object {
internal fun create(
existing: TransferInputResources?,
parser: ParserProtocol,
data: Map<*, *>?
internalState: InternalTransferInputState?,
): TransferInputResources? {
Logger.d { "creating Transfer Input Resources\n" }

data?.let {
val chainResourcesMap = parser.asMap(data["chainResources"])
val chainResources: IMap<String, TransferInputChainResource> =
chainResourcesMap?.mapValues { entry ->
TransferInputChainResource.create(
null,
parser,
parser.asMap(entry.value),
) ?: TransferInputChainResource(null, null, null, null, null)
}?.toIMap() ?: iMapOf()

val tokenResourcesMap = parser.asMap(data["tokenResources"])
val tokenResources: IMap<String, TransferInputTokenResource> =
tokenResourcesMap?.mapValues {
TransferInputTokenResource.create(
null,
parser,
parser.asMap(it.value),
) ?: TransferInputTokenResource(null, null, null, null, null)
}?.toIMap() ?: iMapOf()

internalState?.let {
val chainResources: IMap<String, TransferInputChainResource> = internalState.chainResources?.toIMap() ?: iMapOf()
val tokenResources: IMap<String, TransferInputTokenResource> = internalState.tokenResources?.toIMap() ?: iMapOf()
return if (
existing?.chainResources != chainResources ||
existing.tokenResources != tokenResources
Expand Down Expand Up @@ -632,7 +491,8 @@ data class TransferInput(
existing: TransferInput?,
parser: ParserProtocol,
data: Map<*, *>?,
environment: V4Environment?
environment: V4Environment?,
internalState: InternalTransferInputState?
): TransferInput? {
Logger.d { "creating Transfer Input\n" }

Expand All @@ -656,6 +516,7 @@ data class TransferInput(
existing?.depositOptions,
parser,
parser.asMap(data["depositOptions"]),
internalState,
)
}

Expand All @@ -665,6 +526,7 @@ data class TransferInput(
existing?.withdrawalOptions,
parser,
parser.asMap(data["withdrawalOptions"]),
internalState,
)
}

Expand All @@ -686,8 +548,7 @@ data class TransferInput(

val resources = TransferInputResources.create(
existing?.resources,
parser,
parser.asMap(data["resources"]),
internalState,
)

val route = parser.asMap(data["route"])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
package exchange.dydx.abacus.processor.squid

import exchange.dydx.abacus.processor.base.BaseProcessor
import exchange.dydx.abacus.output.input.SelectionOption
import exchange.dydx.abacus.protocols.ParserProtocol

internal class SquidChainProcessor(parser: ParserProtocol) : BaseProcessor(parser) {
private val keyMap = mapOf(
"string" to mapOf(
"chainName" to "stringKey",
"networkIdentifier" to "stringKey",
"chainId" to "type",
"chainIconURI" to "iconUrl",
),
)

override fun received(
existing: Map<String, Any>?,
internal class SquidChainProcessor(
private val parser: ParserProtocol
) {
fun received(
payload: Map<String, Any>
): Map<String, Any> {
return transform(existing, payload, keyMap)
): SelectionOption {
return SelectionOption(
stringKey = parser.asString(payload["networkIdentifier"]) ?: parser.asString(payload["chainName"]),
string = parser.asString(payload["networkIdentifier"]) ?: parser.asString(payload["chainName"]),
type = parser.asString(payload["chainId"]) ?: "",
iconUrl = parser.asString(payload["chainIconURI"]),
)
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
package exchange.dydx.abacus.processor.squid

import exchange.dydx.abacus.processor.base.BaseProcessor
import exchange.dydx.abacus.output.input.TransferInputChainResource
import exchange.dydx.abacus.protocols.ParserProtocol

internal class SquidChainResourceProcessor(parser: ParserProtocol) : BaseProcessor(parser) {
private val keyMap = mapOf(
"string" to mapOf(
"chainName" to "chainName",
"rpc" to "rpc",
"networkName" to "networkName",
"chainId" to "chainId",
"chainIconURI" to "iconUrl",
),
)

override fun received(
existing: Map<String, Any>?,
internal class SquidChainResourceProcessor(
private val parser: ParserProtocol
) {
fun received(
payload: Map<String, Any>
): Map<String, Any> {
return transform(existing, payload, keyMap)
): TransferInputChainResource {
return TransferInputChainResource(
chainName = parser.asString(payload["chainName"]),
rpc = parser.asString(payload["rpc"]),
networkName = parser.asString(payload["networkName"]),
chainId = parser.asInt(payload["chainId"]),
iconUrl = parser.asString(payload["chainIconURI"]),
)
}
}
Loading
Loading