diff --git a/build.gradle.kts b/build.gradle.kts index 86c019e..ef387a7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("multiplatform") version "1.9.21" apply false + kotlin("multiplatform") version "1.9.22" apply false id("com.vanniktech.maven.publish") version "0.25.3" apply false } diff --git a/rpccore/build.gradle.kts b/rpccore/build.gradle.kts index 4450fab..4f93941 100644 --- a/rpccore/build.gradle.kts +++ b/rpccore/build.gradle.kts @@ -1,6 +1,6 @@ plugins { kotlin("multiplatform") - kotlin("plugin.serialization") version "1.9.21" + kotlin("plugin.serialization") version "1.9.22" id("com.vanniktech.maven.publish") } diff --git a/rpccore/src/commonMain/kotlin/com/solana/networking/Rpc20Driver.kt b/rpccore/src/commonMain/kotlin/com/solana/networking/Rpc20Driver.kt index 3daffc0..68e580d 100644 --- a/rpccore/src/commonMain/kotlin/com/solana/networking/Rpc20Driver.kt +++ b/rpccore/src/commonMain/kotlin/com/solana/networking/Rpc20Driver.kt @@ -3,20 +3,31 @@ package com.solana.networking import com.solana.rpccore.* import kotlinx.serialization.KSerializer import kotlinx.serialization.json.Json +import kotlinx.serialization.modules.SerializersModule +import kotlinx.serialization.modules.polymorphic +import kotlinx.serialization.modules.subclass class Rpc20Driver(private val url: String, - private val httpDriver: HttpNetworkDriver) : JsonRpcDriver { + private val httpDriver: HttpNetworkDriver, + private val json: Json) : JsonRpcDriver { - private val json = Json { + constructor(url: String, httpDriver: HttpNetworkDriver) : this(url, httpDriver, Json { ignoreUnknownKeys = true - } + }) - override suspend fun makeRequest(request: RpcRequest, resultSerializer: KSerializer): Rpc20Response = - httpDriver.makeHttpRequest( + override suspend fun makeRequest(request: RpcRequest, resultSerializer: KSerializer): Rpc20Response { + require(request.jsonrpc == "2.0") { "Request is not a JSON RPC 2.0 request (${request.jsonrpc})"} + return httpDriver.makeHttpRequest( HttpPostRequest( url = url, properties = mapOf("Content-Type" to "application/json; charset=utf-8"), - body = json.encodeToString(RpcRequestPolymorphicSerializer, request) + body = json.encodeToString( + JsonRpc20Request.serializer(), JsonRpc20Request( + request.method, + request.params, + request.id + ) + ) ) ).run { try { @@ -25,6 +36,7 @@ class Rpc20Driver(private val url: String, Rpc20Response(error = RpcError(-1, e.message ?: this)) } } + } internal class HttpPostRequest( override val url: String, diff --git a/rpccore/src/commonMain/kotlin/com/solana/rpccore/RpcRequest.kt b/rpccore/src/commonMain/kotlin/com/solana/rpccore/RpcRequest.kt index 838dcea..9dc0460 100644 --- a/rpccore/src/commonMain/kotlin/com/solana/rpccore/RpcRequest.kt +++ b/rpccore/src/commonMain/kotlin/com/solana/rpccore/RpcRequest.kt @@ -1,6 +1,5 @@ package com.solana.rpccore -import kotlinx.serialization.DeserializationStrategy import kotlinx.serialization.EncodeDefault import kotlinx.serialization.Serializable import kotlinx.serialization.json.* @@ -30,9 +29,3 @@ open class JsonRpc20Request ( @EncodeDefault override val jsonrpc: String = "2.0" } - -object RpcRequestPolymorphicSerializer : JsonContentPolymorphicSerializer(RpcRequest::class) { - override fun selectDeserializer(element: JsonElement): DeserializationStrategy { - return RpcRequest.serializer() - } -} diff --git a/rpccore/src/commonTest/kotlin/com/solana/rpccore/RpcCoreTest.kt b/rpccore/src/commonTest/kotlin/com/solana/rpccore/RpcCoreTest.kt index 62fadca..55b7900 100644 --- a/rpccore/src/commonTest/kotlin/com/solana/rpccore/RpcCoreTest.kt +++ b/rpccore/src/commonTest/kotlin/com/solana/rpccore/RpcCoreTest.kt @@ -5,9 +5,8 @@ import com.solana.networking.HttpRequest import com.solana.networking.Rpc20Driver import com.solana.util.MockHttpDriver import kotlinx.coroutines.test.runTest -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.buildJsonObject -import kotlinx.serialization.json.put +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.* import kotlin.test.* class RpcDriverTest { @@ -139,4 +138,33 @@ class RpcDriverTest { rpcDriver.makeRequest(rpcRequest) } + + @Test + fun testRpc20DriverCorrectlySerializesCustomRequest() = runTest { + class MyRpcRequest : JsonRpc20Request("getSomething", id = "1234", + params = buildJsonArray { + add("a string") + addJsonObject { + put("param", "value") + } + }) + + val rpcUrl = "https://api.invalid.solana.com" + val rpcRequest = MyRpcRequest() + val serializedRequest = buildJsonObject { + put("method", rpcRequest.method) + put("params", rpcRequest.params!!) + put("id", rpcRequest.id) + put("jsonrpc", rpcRequest.jsonrpc) + }.toString() + + val rpcDriver = Rpc20Driver(rpcUrl, object : HttpNetworkDriver { + override suspend fun makeHttpRequest(request: HttpRequest): String { + assertEquals(serializedRequest, request.body) + return "" + } + }) + + rpcDriver.makeRequest(rpcRequest) + } } \ No newline at end of file