Skip to content

Commit

Permalink
Merge pull request #10 from solana-mobile/fix-polymorphic-serialization
Browse files Browse the repository at this point in the history
Fix rpc driver polymorphic serialization
  • Loading branch information
Funkatronics authored Jan 31, 2024
2 parents 523ac88 + 4333918 commit 2f84927
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 18 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -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
}

Expand Down
2 changes: 1 addition & 1 deletion rpccore/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -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")
}

Expand Down
24 changes: 18 additions & 6 deletions rpccore/src/commonMain/kotlin/com/solana/networking/Rpc20Driver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 <R> makeRequest(request: RpcRequest, resultSerializer: KSerializer<R>): Rpc20Response<R> =
httpDriver.makeHttpRequest(
override suspend fun <R> makeRequest(request: RpcRequest, resultSerializer: KSerializer<R>): Rpc20Response<R> {
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 {
Expand All @@ -25,6 +36,7 @@ class Rpc20Driver(private val url: String,
Rpc20Response(error = RpcError(-1, e.message ?: this))
}
}
}

internal class HttpPostRequest(
override val url: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.solana.rpccore

import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.*
Expand Down Expand Up @@ -30,9 +29,3 @@ open class JsonRpc20Request (
@EncodeDefault
override val jsonrpc: String = "2.0"
}

object RpcRequestPolymorphicSerializer : JsonContentPolymorphicSerializer<RpcRequest>(RpcRequest::class) {
override fun selectDeserializer(element: JsonElement): DeserializationStrategy<RpcRequest> {
return RpcRequest.serializer()
}
}
34 changes: 31 additions & 3 deletions rpccore/src/commonTest/kotlin/com/solana/rpccore/RpcCoreTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}
}

0 comments on commit 2f84927

Please sign in to comment.