Skip to content

Commit

Permalink
Merge branch 'main' into feature/TRA-329-trade-isolated-margin-receip…
Browse files Browse the repository at this point in the history
…t-lines
  • Loading branch information
ruixhuang authored May 30, 2024
2 parents e7b35c4 + 82f7f6d commit efbfbb6
Show file tree
Hide file tree
Showing 12 changed files with 360 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ data class TransferOutInputOptions(
@Serializable
data class TransferInputChainResource(
val chainName: String?,
val rpc: String?,
val networkName: String?,
val rpc: String? = null,
val networkName: String? = null,
val chainId: Int?,
val iconUrl: String?
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
package exchange.dydx.abacus.processor.router.skip

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

internal class SkipChainProcessor(parser: ParserProtocol) : BaseProcessor(parser) {
private val keyMap = mapOf(
"string" to mapOf(
"chain_name" to "stringKey",
"networkIdentifier" to "stringKey",
"chain_id" to "type",
"logo_uri" to "iconUrl",
),
)

override fun received(
existing: Map<String, Any>?,
internal class SkipChainProcessor(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["network_identifier"]) ?: parser.asString(payload["chain_name"]),
string = parser.asString(payload["network_identifier"]) ?: parser.asString(payload["chain_name"]),
type = parser.asString(payload["chain_id"]) ?: "",
iconUrl = parser.asString(payload["logo_uri"]),
)
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
package exchange.dydx.abacus.processor.router.skip

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

internal class SkipChainResourceProcessor(parser: ParserProtocol) : BaseProcessor(parser) {
private val keyMap = mapOf(
"string" to mapOf(
"chain_name" to "chainName",
"rpc" to "rpc",
"networkName" to "networkName",
"chain_id" to "chainId",
"logo_uri" to "iconUrl",
),
)
internal class SkipChainResourceProcessor(private val parser: ParserProtocol) {

override fun received(
existing: Map<String, Any>?,
fun received(
payload: Map<String, Any>
): Map<String, Any> {
return transform(existing, payload, keyMap)
): TransferInputChainResource {
return TransferInputChainResource(
chainName = parser.asString(payload["chain_name"]),
rpc = parser.asString(payload["rpc"]),
networkName = parser.asString(payload["networkName"]),
chainId = parser.asInt(payload["chain_id"]),
iconUrl = parser.asString(payload["logo_uri"]),
)
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
package exchange.dydx.abacus.processor.router.skip

import exchange.dydx.abacus.output.input.SelectionOption
import exchange.dydx.abacus.output.input.TransferInputChainResource
import exchange.dydx.abacus.processor.base.BaseProcessor
import exchange.dydx.abacus.processor.router.IRouterProcessor
import exchange.dydx.abacus.processor.router.SharedRouterProcessor
import exchange.dydx.abacus.protocols.ParserProtocol
import exchange.dydx.abacus.state.internalstate.InternalTransferInputState
import exchange.dydx.abacus.utils.mutable
import exchange.dydx.abacus.utils.safeSet

@Suppress("NotImplementedDeclaration")
internal class SkipProcessor(parser: ParserProtocol) : BaseProcessor(parser), IRouterProcessor {
internal class SkipProcessor(
parser: ParserProtocol,
private val internalState: InternalTransferInputState
) : BaseProcessor(parser), IRouterProcessor {
override var chains: List<Any>? = null

// possibly want to use a different variable so we aren't stuck with this bad type
Expand All @@ -26,8 +33,25 @@ internal class SkipProcessor(parser: ParserProtocol) : BaseProcessor(parser), IR
existing: Map<String, Any>?,
payload: Map<String, Any>
): Map<String, Any>? {
throw NotImplementedError("receivedChains is not implemented in SkipProcessor!")
if (this.chains != null) {
return existing
}
this.chains = parser.asNativeList(payload["chains"])
var modified = mutableMapOf<String, Any>()
existing?.let {
modified = it.mutable()
}
val chainOptions = chainOptions()

internalState.chains = chainOptions
val selectedChainId = defaultChainId()
modified.safeSet("transfer.chain", selectedChainId)
selectedChainId?.let {
internalState.chainResources = chainResources(chainId = selectedChainId)
}
return modified
}

override fun receivedTokens(
existing: Map<String, Any>?,
payload: Map<String, Any>
Expand Down Expand Up @@ -72,7 +96,9 @@ internal class SkipProcessor(parser: ParserProtocol) : BaseProcessor(parser), IR
}

override fun defaultChainId(): String? {
throw NotImplementedError("defaultChainId is not implemented in SkipProcessor!")
val selectedChain = parser.asNativeMap(this.chains?.find { parser.asString(parser.asNativeMap(it)?.get("chain_id")) == "1" })

return parser.asString(selectedChain?.get("chain_id"))
}

override fun selectedTokenSymbol(tokenAddress: String?): String? {
Expand All @@ -91,16 +117,41 @@ internal class SkipProcessor(parser: ParserProtocol) : BaseProcessor(parser), IR
throw NotImplementedError("defaultTokenAddress is not implemented in SkipProcessor!")
}

override fun chainResources(chainId: String?): Map<String, Any>? {
throw NotImplementedError("chainResources is not implemented in SkipProcessor!")
override fun chainResources(chainId: String?): Map<String, TransferInputChainResource>? {
val chainResources = mutableMapOf<String, TransferInputChainResource>()
chainId?.let {
this.chains?.find {
parser.asString(parser.asNativeMap(it)?.get("chain_id")) == chainId
}?.let {
val processor = SkipChainResourceProcessor(parser)
parser.asNativeMap(it)?.let { payload ->
chainResources[chainId] = processor.received(payload)
}
}
}
return chainResources
}

override fun tokenResources(chainId: String?): Map<String, Any>? {
throw NotImplementedError("tokenResources is not implemented in SkipProcessor!")
}

override fun chainOptions(): List<Any> {
throw NotImplementedError("chainOptions is not implemented in SkipProcessor!")
override fun chainOptions(): List<SelectionOption> {
val chainProcessor = SkipChainProcessor(parser)
val options = mutableListOf<SelectionOption>()

this.chains?.let {
for (chain in it) {
parser.asNativeMap(chain)?.let { chain ->
if (parser.asString(chain.get("chainType")) != "cosmos") {
options.add(chainProcessor.received(chain))
}
}
}
}

options.sortBy { parser.asString(it.stringKey) }
return options
}

override fun tokenOptions(chainId: String?): List<Any> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ internal class SquidProcessor(
override fun updateTokensDefaults(modified: MutableMap<String, Any>, selectedChainId: String?) {
val tokenOptions = tokenOptions(selectedChainId)
internalState.tokens = tokenOptions
modified.safeSet("transfer.depositOptions.assets", tokenOptions)
modified.safeSet("transfer.withdrawalOptions.assets", tokenOptions)
modified.safeSet("transfer.token", defaultTokenAddress(selectedChainId))
internalState.tokenResources = tokenResources(selectedChainId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,19 @@ class V4StateManagerConfigs(
return if (environment.isMainNet) "noble-1" else "grand-1"
}

fun skipV1Chains(): String {
return "$skipHost/v1/info/chains?include_evm=true"
}

fun nobleDenom(): String? {
return "uusdc"
}

private val skipHost: String
get() {
return "https://api.skip.money"
}

private val squidV2Host: String
get() {
return if (environment.isMainNet) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import kollections.iListOf
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject

internal fun TradingStateMachine.squidChains(payload: String): StateChanges? {
internal fun TradingStateMachine.routerChains(payload: String): StateChanges? {
val json = parser.decodeJsonObject(payload)
return if (json != null) {
input = squidProcessor.receivedChains(input, json)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import exchange.dydx.abacus.state.manager.HumanReadableWithdrawPayload
import exchange.dydx.abacus.state.manager.pendingCctpWithdraw
import exchange.dydx.abacus.state.model.TradingStateMachine
import exchange.dydx.abacus.state.model.TransferInputField
import exchange.dydx.abacus.state.model.routerChains
import exchange.dydx.abacus.state.model.squidRoute
import exchange.dydx.abacus.state.model.squidRouteV2
import exchange.dydx.abacus.state.model.squidStatus
Expand Down Expand Up @@ -69,6 +70,17 @@ internal class OnboardingSupervisor(
retrieveCctpChainIds()
}

@Suppress("UnusedPrivateMember")
private fun retrieveSkipTransferChains() {
val oldState = stateMachine.state
val chainsUrl = helper.configs.skipV1Chains()
helper.get(chainsUrl, null, null) { _, response, httpCode, _ ->
if (helper.success(httpCode) && response != null) {
update(stateMachine.routerChains(response), oldState)
}
}
}

private fun retrieveTransferAssets() {
val oldState = stateMachine.state
val url = helper.configs.squidV2Assets()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package exchange.dydx.abacus.payload.v4

import exchange.dydx.abacus.state.model.TransferInputField
import exchange.dydx.abacus.state.model.squidChains
import exchange.dydx.abacus.state.model.routerChains
import exchange.dydx.abacus.state.model.squidRoute
import exchange.dydx.abacus.state.model.squidRouteV2
import exchange.dydx.abacus.state.model.squidStatus
Expand All @@ -20,7 +20,7 @@ class V4SquidTests : V4BaseTests() {
// Due to the JIT compiler nature for JVM (and Kotlin) and JS, Android/web would ran slow the first round. Second round give more accurate result
setup()

val stateChange = perp.squidChains(mock.squidChainsMock.payload)
val stateChange = perp.routerChains(mock.squidChainsMock.payload)
assertNotNull(stateChange)

test({
Expand All @@ -47,7 +47,7 @@ class V4SquidTests : V4BaseTests() {
// Due to the JIT compiler nature for JVM (and Kotlin) and JS, Android/web would ran slow the first round. Second round give more accurate result
setup()

var stateChange = perp.squidChains(mock.squidChainsMock.payload)
var stateChange = perp.routerChains(mock.squidChainsMock.payload)
assertNotNull(stateChange)

stateChange = perp.squidTokens(mock.squidTokensMock.payload)
Expand Down Expand Up @@ -112,7 +112,7 @@ class V4SquidTests : V4BaseTests() {

perp.transfer("DEPOSIT", TransferInputField.type, 0)

var stateChange = perp.squidChains(mock.squidChainsMock.payload)
var stateChange = perp.routerChains(mock.squidChainsMock.payload)
assertNotNull(stateChange)

stateChange = perp.squidTokens(mock.squidTokensMock.payload)
Expand Down Expand Up @@ -148,7 +148,7 @@ class V4SquidTests : V4BaseTests() {

perp.transfer("DEPOSIT", TransferInputField.type, 0)

var stateChange = perp.squidChains(mock.squidChainsMock.payload)
var stateChange = perp.routerChains(mock.squidChainsMock.payload)
assertNotNull(stateChange)

stateChange = perp.squidTokens(mock.squidTokensMock.payload)
Expand Down Expand Up @@ -219,7 +219,7 @@ class V4SquidTests : V4BaseTests() {
fun testDefaultTokenAddress() {
setup()

var stateChange = perp.squidChains(mock.squidChainsMock.payload)
var stateChange = perp.routerChains(mock.squidChainsMock.payload)
assertNotNull(stateChange)

stateChange = perp.squidTokens(mock.squidTokensMock.payload)
Expand All @@ -232,7 +232,7 @@ class V4SquidTests : V4BaseTests() {
fun testChainResources() {
setup()

val stateChange = perp.squidChains(mock.squidChainsMock.payload)
val stateChange = perp.routerChains(mock.squidChainsMock.payload)
assertNotNull(stateChange)

val result = perp.squidProcessor.chainResources("1")
Expand All @@ -245,7 +245,7 @@ class V4SquidTests : V4BaseTests() {
fun testTokenResources() {
setup()

var stateChange = perp.squidChains(mock.squidChainsMock.payload)
var stateChange = perp.routerChains(mock.squidChainsMock.payload)
assertNotNull(stateChange)

stateChange = perp.squidTokens(mock.squidTokensMock.payload)
Expand All @@ -259,7 +259,7 @@ class V4SquidTests : V4BaseTests() {
fun testTokenOptions() {
setup()

var stateChange = perp.squidChains(mock.squidChainsMock.payload)
var stateChange = perp.routerChains(mock.squidChainsMock.payload)
assertNotNull(stateChange)

stateChange = perp.squidTokens(mock.squidTokensMock.payload)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package exchange.dydx.abacus.processor.router.skip
import exchange.dydx.abacus.output.input.SelectionOption
import exchange.dydx.abacus.output.input.TransferInputChainResource
import exchange.dydx.abacus.state.internalstate.InternalTransferInputState
import exchange.dydx.abacus.tests.payloads.SkipChainsMock
import exchange.dydx.abacus.utils.Parser
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonObject
import kotlin.test.Test
import kotlin.test.assertEquals

internal fun templateToJson(template: String): Map<String, Any> {
return Json.parseToJsonElement(template.trimIndent()).jsonObject.toMap()
}

class SkipProcessorTests {

internal val internalState = InternalTransferInputState()
internal val skipProcessor = SkipProcessor(parser = Parser(), internalState = internalState)
internal val skipChainsMock = SkipChainsMock()

@Test
fun testReceivedChains() {
val modified = skipProcessor.receivedChains(
existing = mapOf(),
payload = templateToJson(
skipChainsMock.payload,
),
)

val expectedChains = listOf(
SelectionOption(stringKey = "Ethereum", string = "Ethereum", type = "1", iconUrl = "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png"),
SelectionOption(stringKey = "aura", string = "aura", type = "xstaxy-1", iconUrl = "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/xstaxy/chain.png"),
SelectionOption(stringKey = "cheqd", string = "cheqd", type = "cheqd-mainnet-1", iconUrl = "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/cheqd-mainnet/chain.png"),
SelectionOption(stringKey = "kujira", string = "kujira", type = "kaiyo-1", iconUrl = "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/kaiyo/chain.png"),
SelectionOption(stringKey = "osmosis", string = "osmosis", type = "osmosis-1", iconUrl = "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/osmosis/chain.png"),
SelectionOption(stringKey = "stride", string = "stride", type = "stride-1", iconUrl = "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/stride/chain.png"),
)
assertEquals(expectedChains, internalState.chains)

val expectedChainResources = mapOf(
"1" to TransferInputChainResource(
chainName = "Ethereum",
chainId = 1,
iconUrl = "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png",
),
)
assertEquals(expectedChainResources, internalState.chainResources)

val expectedModified = mapOf(
"transfer" to mapOf(
"chain" to "1",
),
)
assertEquals(expectedModified, modified)
}
}
Loading

0 comments on commit efbfbb6

Please sign in to comment.