From be17c3e8e504bf288b39a1dd877cd2e5b1f7aee6 Mon Sep 17 00:00:00 2001 From: moo-onthelawn <70078372+moo-onthelawn@users.noreply.github.com> Date: Thu, 30 May 2024 16:53:59 -0400 Subject: [PATCH 1/3] create memo field for transferInput (#401) Co-authored-by: mobile-build-bot-git --- build.gradle.kts | 2 +- docs/Input/TransferInput.md | 79 ++++++++++++++++++- .../output/input/TransferInput.kt | 6 +- .../TradingStateMachine+TransferInput.kt | 11 ++- .../payload/TransferInputTests.kt | 73 +++++++++++++++++ 5 files changed, 166 insertions(+), 5 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index dbcbbdba5..6e3e08b5e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -51,7 +51,7 @@ allprojects { } group = "exchange.dydx.abacus" -version = "1.7.41" +version = "1.7.42" repositories { google() diff --git a/docs/Input/TransferInput.md b/docs/Input/TransferInput.md index 416c53dcb..46729a4c8 100644 --- a/docs/Input/TransferInput.md +++ b/docs/Input/TransferInput.md @@ -7,7 +7,10 @@ data class TransferInput(  val fee: Double?,  val chain: String?,  val address: String?, + val memo: String?,  val depositOptions: DepositInputOptions?, + val withdrawalOptions: WithdrawalInputOptions?, + val transferOutOptions: TransferOutInputOptions?,  val summary: TransferInputSummary?,  val resources: TransferInputResources?,  val requestPayload: TransferInputRequestPayload? @@ -39,10 +42,22 @@ Selected chain to perform the transfer Selected token address of the chain to perform the transfer +## memo + +Memo for transfer + ## depositOptions structure of [DepositInputOptions](#DepositInputOptions) +## withdrawalOptions + +structure of [WithdrawalInputOptions](#WithdrawalInputOptions) + +## transferOutOptions + +structure of [TransferOutInputOptions](#TransferOutInputOptions) + ## summary structure of [TransferInputSummary](#TransferInputSummary) @@ -80,6 +95,66 @@ UX should let the user choose whether to use fast speed Option of assets to choose from +# WithdrawalInputOptions + +data class DepositInputOptions( + val needsSize: Boolean?, + val needsAddress: Boolean?, + val needsFastSpeed: Boolean?, + val exchanges: Array? + val chains: Array? + val assets: Array? +) + +## needsSize + +UX should let user enter the size + +## needsAddress + +UX should let user enter a wallet address + +## needsFastSpeed + +UX should let the user choose whether to use fast speed + +## exchanges + +Option of exchanges to choose from + +## chains + +Option of chains to choose from + +## assets + +Option of assets to choose from + +# TransferOutInputOptions + +data class TransferOutInputOptions( + val needsSize: Boolean?, + val needsAddress: Boolean?, + val chains: Array?, + val assets: Array? +) + +## needsSize + +UX should let user enter the size + +## needsAddress + +UX should let user enter a wallet address + +## chains + +Option of chains to choose from + +## assets + +Option of assets to choose from + # TransferInputSummary data class TransferInputSummary( @@ -102,7 +177,7 @@ Whether the transfer transaction can be filled # TransferInputResources -The chain and token resources of the selected chain and its associated tokens. Use the chainId +The chain and token resources of the selected chain and its associated tokens. Use the chainId and token address of the key to the maps, respectively, to get the resource. data class TransferInputResources( @@ -147,4 +222,4 @@ data class TransferInputRequestPayload(  val gasPrice: String?,  val maxFeePerGas: String?,  val maxPriorityFeePerGas: String? -) \ No newline at end of file +) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/output/input/TransferInput.kt b/src/commonMain/kotlin/exchange.dydx.abacus/output/input/TransferInput.kt index e094ef997..17133955e 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/output/input/TransferInput.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/output/input/TransferInput.kt @@ -149,7 +149,7 @@ data class TransferOutInputOptions( val needsSize: Boolean?, val needsAddress: Boolean?, val chains: IList?, - val assets: IList? + val assets: IList?, ) { companion object { internal fun create( @@ -474,6 +474,7 @@ data class TransferInput( val chain: String?, val token: String?, val address: String?, + val memo: String?, val depositOptions: DepositInputOptions?, val withdrawalOptions: WithdrawalInputOptions?, val transferOutOptions: TransferOutInputOptions?, @@ -509,6 +510,7 @@ data class TransferInput( val chain = parser.asString(data["chain"]) val token = parser.asString(data["token"]) val address = parser.asString(data["address"]) + val memo = parser.asString(data["memo"]) var depositOptions: DepositInputOptions? = null if (type == TransferType.deposit) { @@ -577,6 +579,7 @@ data class TransferInput( existing.chain != chain || existing.token != token || existing.address != address || + existing.memo != memo || existing.depositOptions != depositOptions || existing.withdrawalOptions != withdrawalOptions || existing.transferOutOptions != transferOutOptions || @@ -595,6 +598,7 @@ data class TransferInput( chain, token, address, + memo, depositOptions, withdrawalOptions, transferOutOptions, diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TransferInput.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TransferInput.kt index 2cc152517..391b2a6bf 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TransferInput.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TransferInput.kt @@ -25,6 +25,7 @@ enum class TransferInputField(val rawValue: String) { chain("chain"), token("token"), address("address"), + MEMO("memo"), fastSpeed("fastSpeed"); companion object { @@ -69,6 +70,7 @@ fun TradingStateMachine.transfer( transfer.safeSet("size.usdcSize", null) transfer.safeSet("route", null) transfer.safeSet("requestPayload", null) + transfer.safeSet("memo", null) if (parser.asString(data) == "TRANSFER_OUT") { transfer.safeSet("chain", "chain") transfer.safeSet("token", "usdc") @@ -135,7 +137,6 @@ fun TradingStateMachine.transfer( iListOf(subaccountNumber), ) } - TransferInputField.fastSpeed.rawValue -> { transfer.safeSet(typeText, parser.asBool(data)) changes = StateChanges( @@ -166,6 +167,14 @@ fun TradingStateMachine.transfer( iListOf(subaccountNumber), ) } + TransferInputField.MEMO.rawValue -> { + transfer.safeSet(typeText, parser.asString(data)) + changes = StateChanges( + iListOf(Changes.input), + null, + iListOf(subaccountNumber), + ) + } else -> {} } } else { diff --git a/src/commonTest/kotlin/exchange.dydx.abacus/payload/TransferInputTests.kt b/src/commonTest/kotlin/exchange.dydx.abacus/payload/TransferInputTests.kt index d86937fbc..633528067 100644 --- a/src/commonTest/kotlin/exchange.dydx.abacus/payload/TransferInputTests.kt +++ b/src/commonTest/kotlin/exchange.dydx.abacus/payload/TransferInputTests.kt @@ -28,6 +28,8 @@ class TransferInputTests : V3BaseTests() { testTransferOutTransferInput() perp.log("Transfer Out", time) + + testTransferInputTypeChange() } private fun testDepositTransferInput() { @@ -414,6 +416,10 @@ class TransferInputTests : V3BaseTests() { perp.transfer("5000.0", TransferInputField.usdcSize) }, null) + test({ + perp.transfer("test memo", TransferInputField.MEMO) + }, null) + test( { perp.transfer("1000.0", TransferInputField.usdcSize) @@ -423,6 +429,7 @@ class TransferInputTests : V3BaseTests() { "input": { "transfer": { "type": "TRANSFER_OUT", + "memo": "test memo", "size": { "usdcSize": 1000.0 }, @@ -469,4 +476,70 @@ class TransferInputTests : V3BaseTests() { }, ) } + + private fun testTransferInputTypeChange() { + test( + { + perp.transfer("DEPOSIT", TransferInputField.type) + }, + """ + { + "input": { + "transfer": { + "type": "DEPOSIT", + "memo": null + } + } + } + """.trimIndent(), + ) + + test( + { + perp.transfer("TRANSFER_OUT", TransferInputField.type) + }, + """ + { + "input": { + "transfer": { + "type": "TRANSFER_OUT", + "memo": null + } + } + } + """.trimIndent(), + ) + + test( + { + perp.transfer("test memo", TransferInputField.MEMO) + }, + """ + { + "input": { + "transfer": { + "type": "TRANSFER_OUT", + "memo": "test memo" + } + } + } + """.trimIndent(), + ) + + test( + { + perp.transfer("WITHDRAWAL", TransferInputField.type) + }, + """ + { + "input": { + "transfer": { + "type": "WITHDRAWAL", + "memo": null + } + } + } + """.trimIndent(), + ) + } } From 20649eda5f43ceb22d8f6edd06f5b529dcc0014a Mon Sep 17 00:00:00 2001 From: Jeremy Lee <37092291+yogurtandjam@users.noreply.github.com> Date: Thu, 30 May 2024 17:20:47 -0400 Subject: [PATCH 2/3] fix: setting tokens chains and resources (#402) --- build.gradle.kts | 2 +- .../TradingStateMachine+TransferInput.kt | 42 +++++++++++-------- .../state/model/TradingStateMachine.kt | 2 +- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6e3e08b5e..a0544b438 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -51,7 +51,7 @@ allprojects { } group = "exchange.dydx.abacus" -version = "1.7.42" +version = "1.7.43" repositories { google() diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TransferInput.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TransferInput.kt index 391b2a6bf..ac3500c88 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TransferInput.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TransferInput.kt @@ -213,35 +213,44 @@ private fun TradingStateMachine.updateTransferToTokenType(transfer: MutableMap, chainType: String) { val tokenOptions = squidProcessor.tokenOptions(chainType) if (transfer["type"] != "TRANSFER_OUT") { - transfer.safeSet( - "depositOptions.assets", - tokenOptions, - ) - transfer.safeSet( - "withdrawalOptions.assets", - tokenOptions, - ) + internalState.transfer.tokens = tokenOptions transfer.safeSet("chain", chainType) transfer.safeSet("token", squidProcessor.defaultTokenAddress(chainType)) - transfer.safeSet( - "resources.chainResources", - squidProcessor.chainResources(chainType), - ) - transfer.safeSet( - "resources.tokenResources", - squidProcessor.tokenResources(chainType), - ) + internalState.transfer.chainResources = squidProcessor.chainResources(chainType) + internalState.transfer.tokenResources = squidProcessor.tokenResources(chainType) } transfer.safeSet("exchange", null) transfer.safeSet("size.size", null) transfer.safeSet("route", null) transfer.safeSet("requestPayload", null) +// needed to pass tests, remove later + transfer.safeSet( + "depositOptions.assets", + tokenOptions, + ) + transfer.safeSet( + "withdrawalOptions.assets", + tokenOptions, + ) + transfer.safeSet( + "resources.chainResources", + squidProcessor.chainResources(chainType), + ) + transfer.safeSet( + "resources.tokenResources", + squidProcessor.tokenResources(chainType), + ) } private fun TradingStateMachine.updateTransferExchangeType(transfer: MutableMap, exchange: String) { val exchangeDestinationChainId = squidProcessor.exchangeDestinationChainId val tokenOptions = squidProcessor.tokenOptions(exchangeDestinationChainId) if (transfer["type"] != "TRANSFER_OUT") { + internalState.transfer.tokens = tokenOptions + transfer.safeSet("token", squidProcessor.defaultTokenAddress(exchangeDestinationChainId)) + internalState.transfer.tokenResources = squidProcessor.tokenResources(exchangeDestinationChainId) + +// needed to pass tests, remove later transfer.safeSet( "depositOptions.assets", tokenOptions, @@ -250,7 +259,6 @@ private fun TradingStateMachine.updateTransferExchangeType(transfer: MutableMap< "withdrawalOptions.assets", tokenOptions, ) - transfer.safeSet("token", squidProcessor.defaultTokenAddress(exchangeDestinationChainId)) transfer.safeSet( "resources.tokenResources", squidProcessor.tokenResources(exchangeDestinationChainId), diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine.kt index 0d824bed3..25c710599 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine.kt @@ -82,7 +82,7 @@ open class TradingStateMachine( private val maxSubaccountNumber: Int, private val useParentSubaccount: Boolean, ) { - private val internalState: InternalState = InternalState() + internal val internalState: InternalState = InternalState() internal val parser: ParserProtocol = Parser() internal val marketsProcessor = MarketsSummaryProcessor(parser) From 82f7f6d9fe058402775aeca2aa03469d97203ccd Mon Sep 17 00:00:00 2001 From: Jeremy Lee <37092291+yogurtandjam@users.noreply.github.com> Date: Thu, 30 May 2024 18:47:56 -0400 Subject: [PATCH 3/3] feat: skip v1/chains endpoint [OTE-347] (#390) Co-authored-by: mobile-build-bot-git --- build.gradle.kts | 2 +- .../output/input/TransferInput.kt | 4 +- .../router/skip/SkipChainProcessor.kt | 25 +-- .../router/skip/SkipChainResourceProcessor.kt | 26 ++- .../processor/router/skip/SkipProcessor.kt | 65 +++++- .../processor/router/squid/SquidProcessor.kt | 2 + .../manager/configs/V4StateManagerConfigs.kt | 9 + .../state/model/TradingStateMachine+Squid.kt | 2 +- .../v2/supervisor/OnboardingSupervisor.kt | 12 ++ .../payload/v4/V4SquidTests.kt | 18 +- .../router/skip/SkipProcessorTests.kt | 57 ++++++ .../tests/payloads/SkipChainsMock.kt | 187 ++++++++++++++++++ v4_abacus.podspec | 4 +- 13 files changed, 361 insertions(+), 52 deletions(-) create mode 100644 src/commonTest/kotlin/exchange.dydx.abacus/processor/router/skip/SkipProcessorTests.kt create mode 100644 src/commonTest/kotlin/exchange.dydx.abacus/tests/payloads/SkipChainsMock.kt diff --git a/build.gradle.kts b/build.gradle.kts index a0544b438..c925cb25a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -51,7 +51,7 @@ allprojects { } group = "exchange.dydx.abacus" -version = "1.7.43" +version = "1.7.44" repositories { google() diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/output/input/TransferInput.kt b/src/commonMain/kotlin/exchange.dydx.abacus/output/input/TransferInput.kt index 17133955e..5c49f6dd4 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/output/input/TransferInput.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/output/input/TransferInput.kt @@ -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? ) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipChainProcessor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipChainProcessor.kt index d9967c7d3..07ee41a16 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipChainProcessor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipChainProcessor.kt @@ -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?, +internal class SkipChainProcessor(private val parser: ParserProtocol) { + fun received( payload: Map - ): Map { - 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"]), + ) } } diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipChainResourceProcessor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipChainResourceProcessor.kt index d4906869d..849a6b4cc 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipChainResourceProcessor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipChainResourceProcessor.kt @@ -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?, + fun received( payload: Map - ): Map { - 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"]), + ) } } diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipProcessor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipProcessor.kt index edb9296ee..24d7c5349 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipProcessor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/skip/SkipProcessor.kt @@ -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? = null // possibly want to use a different variable so we aren't stuck with this bad type @@ -26,8 +33,25 @@ internal class SkipProcessor(parser: ParserProtocol) : BaseProcessor(parser), IR existing: Map?, payload: Map ): Map? { - throw NotImplementedError("receivedChains is not implemented in SkipProcessor!") + if (this.chains != null) { + return existing + } + this.chains = parser.asNativeList(payload["chains"]) + var modified = mutableMapOf() + 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?, payload: Map @@ -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? { @@ -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? { - throw NotImplementedError("chainResources is not implemented in SkipProcessor!") + override fun chainResources(chainId: String?): Map? { + val chainResources = mutableMapOf() + 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? { throw NotImplementedError("tokenResources is not implemented in SkipProcessor!") } - override fun chainOptions(): List { - throw NotImplementedError("chainOptions is not implemented in SkipProcessor!") + override fun chainOptions(): List { + val chainProcessor = SkipChainProcessor(parser) + val options = mutableListOf() + + 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 { diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/squid/SquidProcessor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/squid/SquidProcessor.kt index 866b34411..5e8a2b94d 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/squid/SquidProcessor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/processor/router/squid/SquidProcessor.kt @@ -173,6 +173,8 @@ internal class SquidProcessor( override fun updateTokensDefaults(modified: MutableMap, 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) } diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/configs/V4StateManagerConfigs.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/configs/V4StateManagerConfigs.kt index 79d3aaa45..ef36530ee 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/configs/V4StateManagerConfigs.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/configs/V4StateManagerConfigs.kt @@ -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) { diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+Squid.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+Squid.kt index ddb14d6a9..156e6858c 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+Squid.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+Squid.kt @@ -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) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/OnboardingSupervisor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/OnboardingSupervisor.kt index 8fc8caf1b..522114ce1 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/OnboardingSupervisor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/OnboardingSupervisor.kt @@ -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 @@ -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() diff --git a/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4SquidTests.kt b/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4SquidTests.kt index 00c93356f..1af6d062c 100644 --- a/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4SquidTests.kt +++ b/src/commonTest/kotlin/exchange.dydx.abacus/payload/v4/V4SquidTests.kt @@ -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 @@ -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({ @@ -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) @@ -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) @@ -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) @@ -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) @@ -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") @@ -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) @@ -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) diff --git a/src/commonTest/kotlin/exchange.dydx.abacus/processor/router/skip/SkipProcessorTests.kt b/src/commonTest/kotlin/exchange.dydx.abacus/processor/router/skip/SkipProcessorTests.kt new file mode 100644 index 000000000..465951928 --- /dev/null +++ b/src/commonTest/kotlin/exchange.dydx.abacus/processor/router/skip/SkipProcessorTests.kt @@ -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 { + 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) + } +} diff --git a/src/commonTest/kotlin/exchange.dydx.abacus/tests/payloads/SkipChainsMock.kt b/src/commonTest/kotlin/exchange.dydx.abacus/tests/payloads/SkipChainsMock.kt new file mode 100644 index 000000000..a25cf8b92 --- /dev/null +++ b/src/commonTest/kotlin/exchange.dydx.abacus/tests/payloads/SkipChainsMock.kt @@ -0,0 +1,187 @@ +package exchange.dydx.abacus.tests.payloads + +internal class SkipChainsMock { + internal val payload = """{ + "chains": [ + { + "chain_name": "kujira", + "chain_id": "kaiyo-1", + "pfm_enabled": false, + "cosmos_module_support": { + "authz": true, + "feegrant": true + }, + "supports_memo": true, + "logo_uri": "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/kaiyo/chain.png", + "bech32_prefix": "kujira", + "fee_assets": [ + { + "denom": "ibc/47BD209179859CDE4A2806763D7189B6E6FE13A17880FE2B42DE1E6C1E329E23", + "gas_price": null + }, + { + "denom": "ibc/EFF323CC632EC4F747C61BCE238A758EFDB7699C3226565F7C20DA06509D59A5", + "gas_price": null + } + ], + "chain_type": "cosmos", + "ibc_capabilities": { + "cosmos_pfm": false, + "cosmos_ibc_hooks": false, + "cosmos_memo": true, + "cosmos_autopilot": false + }, + "is_testnet": false + }, + { + "chain_name": "cheqd", + "chain_id": "cheqd-mainnet-1", + "pfm_enabled": false, + "cosmos_module_support": { + "authz": true, + "feegrant": true + }, + "supports_memo": true, + "logo_uri": "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/cheqd-mainnet/chain.png", + "bech32_prefix": "cheqd", + "fee_assets": [ + { + "denom": "ncheq", + "gas_price": { + "low": "25", + "average": "50", + "high": "100" + } + } + ], + "chain_type": "cosmos", + "ibc_capabilities": { + "cosmos_pfm": false, + "cosmos_ibc_hooks": false, + "cosmos_memo": true, + "cosmos_autopilot": false + }, + "is_testnet": false + }, + { + "chain_name": "osmosis", + "chain_id": "osmosis-1", + "pfm_enabled": true, + "cosmos_module_support": { + "authz": true, + "feegrant": false + }, + "supports_memo": true, + "logo_uri": "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/osmosis/chain.png", + "bech32_prefix": "osmo", + "fee_assets": [ + { + "denom": "uosmo", + "gas_price": { + "low": "0.0025", + "average": "0.025", + "high": "0.04" + } + } + ], + "chain_type": "cosmos", + "ibc_capabilities": { + "cosmos_pfm": true, + "cosmos_ibc_hooks": true, + "cosmos_memo": true, + "cosmos_autopilot": false + }, + "is_testnet": false + }, + { + "chain_name": "stride", + "chain_id": "stride-1", + "pfm_enabled": true, + "cosmos_module_support": { + "authz": false, + "feegrant": true + }, + "supports_memo": true, + "logo_uri": "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/stride/chain.png", + "bech32_prefix": "stride", + "fee_assets": [ + { + "denom": "stusaga", + "gas_price": { + "low": "0.01", + "average": "0.01", + "high": "0.01" + } + }, + { + "denom": "stuatom", + "gas_price": { + "low": "0.0001", + "average": "0.001", + "high": "0.01" + } + } + ], + "chain_type": "cosmos", + "ibc_capabilities": { + "cosmos_pfm": true, + "cosmos_ibc_hooks": false, + "cosmos_memo": true, + "cosmos_autopilot": true + }, + "is_testnet": false + }, + { + "chain_name": "aura", + "chain_id": "xstaxy-1", + "pfm_enabled": false, + "cosmos_module_support": { + "authz": true, + "feegrant": true + }, + "supports_memo": true, + "logo_uri": "https://raw.githubusercontent.com/chainapsis/keplr-chain-registry/main/images/xstaxy/chain.png", + "bech32_prefix": "aura", + "fee_assets": [ + { + "denom": "uaura", + "gas_price": { + "low": "0.001", + "average": "0.0025", + "high": "0.004" + } + } + ], + "chain_type": "cosmos", + "ibc_capabilities": { + "cosmos_pfm": false, + "cosmos_ibc_hooks": false, + "cosmos_memo": true, + "cosmos_autopilot": false + }, + "is_testnet": false + }, + { + "chain_name": "Ethereum", + "chain_id": "1", + "pfm_enabled": false, + "cosmos_module_support": { + "authz": false, + "feegrant": false + }, + "supports_memo": false, + "logo_uri": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/info/logo.png", + "bech32_prefix": "", + "fee_assets": [], + "chain_type": "evm", + "ibc_capabilities": { + "cosmos_pfm": false, + "cosmos_ibc_hooks": false, + "cosmos_memo": false, + "cosmos_autopilot": false + }, + "is_testnet": false + } + ] +}""" +} diff --git a/v4_abacus.podspec b/v4_abacus.podspec index 4bb221e77..2f4d0aeb1 100644 --- a/v4_abacus.podspec +++ b/v4_abacus.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'v4_abacus' - spec.version = '1.7.38' + spec.version = '1.7.43' spec.homepage = 'https://github.com/dydxprotocol/v4-abacus' spec.source = { :http=> ''} spec.authors = '' @@ -11,7 +11,7 @@ Pod::Spec.new do |spec| - if false + if !Dir.exist?('build/cocoapods/framework/Abacus.framework') || Dir.empty?('build/cocoapods/framework/Abacus.framework') raise " Kotlin framework 'Abacus' doesn't exist yet, so a proper Xcode project can't be generated.