Skip to content

Commit

Permalink
Merge pull request #16 from solana-mobile/get-account-info
Browse files Browse the repository at this point in the history
Add getAccountInfo, getMultipleAccounts, getProgramAccounts RPC Methods
  • Loading branch information
Funkatronics authored Jun 20, 2024
2 parents 8071edc + 7514b3a commit d1bea6c
Show file tree
Hide file tree
Showing 13 changed files with 899 additions and 194 deletions.
5 changes: 3 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ vanniktechMavenPublish = "0.25.3"

[libraries]
crypto = { group = "com.diglol.crypto", name = "crypto", version = "0.1.5" }
kborsh = { group = "io.github.funkatronics", name = "kborsh", version = "0.1.0" }
kotlin-test = { group = "org.jetbrains.kotlin", name = "kotlin-test" }
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinSerialization" }
kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinxCoroutines" }
kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlinxCoroutines" }
ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" }
ktor-client-cio = { group = "io.ktor", name = "ktor-client-cio", version.ref = "ktor" }
ktor-client-mock = { group = "io.ktor", name = "ktor-client-mock", version.ref = "ktor" }
multimult = { group = "io.github.funkatronics", name = "multimult", version = "0.2.2" }
web3-solana = { group = "com.solanamobile", name = "web3-solana", version = "0.3.0-beta3" }
multimult = { group = "io.github.funkatronics", name = "multimult", version = "0.2.3" }
web3-solana = { group = "com.solanamobile", name = "web3-solana", version = "0.3.0-beta4" }

[plugins]
kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
Expand Down
21 changes: 18 additions & 3 deletions rpccore/src/commonMain/kotlin/com/solana/networking/Rpc20Driver.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.solana.networking

import com.solana.rpccore.*
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.KSerializer
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json

class Rpc20Driver(private val url: String,
Expand All @@ -12,7 +15,8 @@ class Rpc20Driver(private val url: String,
ignoreUnknownKeys = true
})

override suspend fun <R> makeRequest(request: RpcRequest, resultSerializer: KSerializer<R>): Rpc20Response<R> {
override suspend fun <R> makeRequest(request: RpcRequest,
resultSerializer: DeserializationStrategy<R>): Rpc20Response<R> {
require(request.jsonrpc == "2.0") { "Request is not a JSON RPC 2.0 request (${request.jsonrpc})"}
return httpDriver.makeHttpRequest(
HttpPostRequest(
Expand All @@ -28,9 +32,9 @@ class Rpc20Driver(private val url: String,
)
).run {
try {
json.decodeFromString(Rpc20Response.serializer(resultSerializer), this)
json.decodeFromString(Deserializer(resultSerializer), this)
} catch (e: Exception) {
Rpc20Response(error = RpcError(-1, e.message ?: this))
Rpc20Response(error = RpcError(-1, e.message ?: e.toString()))
}
}
}
Expand All @@ -42,4 +46,15 @@ class Rpc20Driver(private val url: String,
) : HttpRequest {
override val method = "POST"
}

private class Deserializer<R>(deserializer: DeserializationStrategy<R>): DeserializationStrategy<Rpc20Response<R>> {
private val deserializer = Rpc20Response.serializer(object : KSerializer<R> {
override val descriptor = deserializer.descriptor
override fun serialize(encoder: Encoder, value: R) {}
override fun deserialize(decoder: Decoder): R = decoder.decodeSerializableValue(deserializer)
})
override val descriptor = deserializer.descriptor
override fun deserialize(decoder: Decoder): Rpc20Response<R> =
decoder.decodeSerializableValue(deserializer)
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.solana.rpccore

import kotlinx.serialization.KSerializer
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.json.JsonElement

interface JsonRpcDriver {
suspend fun <R> makeRequest(request: RpcRequest, resultSerializer: KSerializer<R>): RpcResponse<R>
suspend fun <R> makeRequest(request: RpcRequest, resultSerializer: DeserializationStrategy<R>): RpcResponse<R>
}

suspend inline fun <reified R> JsonRpcDriver.get(
request: RpcRequest,
serializer: KSerializer<R>
serializer: DeserializationStrategy<R>
): Result<R?> =
this.makeRequest(request, serializer).let { response ->
(response.result)?.let { result ->
Expand Down
2 changes: 2 additions & 0 deletions solanaclient/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ kotlin {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.serialization.json)
implementation(libs.web3.solana)
implementation(libs.kborsh)
implementation(libs.multimult)
}
}
Expand All @@ -44,6 +45,7 @@ kotlin {
implementation(libs.kotlin.test)
implementation(libs.kotlinx.coroutines.test)
implementation(libs.kotlinx.serialization.json)
implementation(libs.ktor.client.mock)
implementation(libs.crypto)
}
}
Expand Down
77 changes: 77 additions & 0 deletions solanaclient/src/commonMain/kotlin/com/solana/rpc/AccountInfo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.solana.rpc

import com.solana.publickey.SolanaPublicKey
import com.solana.serializers.*
import com.solana.serializers.BorshAsAsEncodedDataArrayDeserializer
import com.solana.serializers.ByteArrayAsEncodedDataArrayDeserializer
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.nullable

@Serializable
data class AccountInfo<D>(
val data: D?,
val executable: Boolean,
val lamports: ULong,
val owner: SolanaPublicKey,
val rentEpoch: ULong,
val size: ULong? = null
)

@Serializable
data class AccountInfoWithPublicKey<P>(
val account: AccountInfo<P>,
@SerialName("pubkey") val publicKey: String
)

fun SolanaAccountDeserializer() =
SolanaResponseDeserializer(
AccountInfo.serializer(
ByteArrayAsEncodedDataArrayDeserializer.asSerializer()
)
)

fun <A> SolanaAccountDeserializer(deserializer: DeserializationStrategy<A>) =
SolanaResponseDeserializer(
AccountInfo.serializer(
BorshAsAsEncodedDataArrayDeserializer(deserializer).asSerializer()
)
)

fun MultipleAccountsDeserializer() =
SolanaResponseDeserializer(
ListSerializer(
AccountInfo.serializer(
ByteArrayAsEncodedDataArrayDeserializer.asSerializer()
).nullable
)
)

fun <A> MultipleAccountsDeserializer(deserializer: DeserializationStrategy<A>) =
SolanaResponseDeserializer(
ListSerializer(
AccountInfo.serializer(
BorshAsAsEncodedDataArrayDeserializer(deserializer).asSerializer()
).nullable
)
)

fun ProgramAccountsDeserializer() =
SolanaResponseDeserializer(
ListSerializer(
AccountInfoWithPublicKey.serializer(
ByteArrayAsEncodedDataArrayDeserializer.asSerializer()
)
)
)

fun <A> ProgramAccountsDeserializer(deserializer: DeserializationStrategy<A>) =
SolanaResponseDeserializer(
ListSerializer(
AccountInfoWithPublicKey.serializer(
BorshAsAsEncodedDataArrayDeserializer(deserializer).asSerializer()
)
)
)
Loading

0 comments on commit d1bea6c

Please sign in to comment.