Skip to content

Commit

Permalink
Merge pull request #1 from avianlabs/add-commitment
Browse files Browse the repository at this point in the history
Add commitment to the calls
  • Loading branch information
jszmltr authored Oct 3, 2023
2 parents bf4cf2e + 8f9ceb7 commit 3850f77
Show file tree
Hide file tree
Showing 11 changed files with 198 additions and 72 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.avianlabs.solana

import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import net.avianlabs.solana.client.RpcInvocation
Expand All @@ -9,10 +10,12 @@ public class SolanaClient(
private val client: RpcKtorClient,
) {

@OptIn(ExperimentalSerializationApi::class)
internal val json: Json = Json {
ignoreUnknownKeys = true
isLenient = true
allowSpecialFloatingPointValues = true
explicitNulls = false
}

internal suspend inline fun <reified T> invoke(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package net.avianlabs.solana.domain.core


/**
* [Commitment.Finalized] - the node will query the most recent block confirmed by supermajority of the cluster as having reached maximum lockout, meaning the cluster has recognized this block as finalized
* [Commitment.Confirmed] - the node will query the most recent block that has been voted on by supermajority of the cluster.
* It incorporates votes from gossip and replay.
* It does not count votes on descendants of a block, only direct votes on that block.
* This confirmation level also upholds "optimistic confirmation" guarantees in release 1.3 and onwards.
* [Commitment.Processed] - the node will query its most recent block. Note that the block may still be skipped by the cluster.
*
* @see <a href="https://docs.solana.com/api/http#configuring-state-commitment">Configuring state commitment</a>
*/
public enum class Commitment(public val value: String) {
Finalized("finalized"),
Confirmed("confirmed"),
Processed("processed"),
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
package net.avianlabs.solana.methods

import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.encodeToJsonElement
import net.avianlabs.solana.SolanaClient
import net.avianlabs.solana.client.RpcResponse.RPC
import net.avianlabs.solana.domain.core.Commitment
import net.avianlabs.solana.domain.core.PublicKey

/**
* @return The balance of the account of provided [PublicKey]
*
* @param account Pubkey of account to query
* @param commitment Optional [Commitment] level
*/
public suspend fun SolanaClient.getBalance(
account: PublicKey,
commitment: Commitment? = null,
): Long {
val result = invoke<RPC<Long>>("getBalance", params(account))
val result = invoke<RPC<Long>>(
method = "getBalance",
params = JsonArray(buildList {
add(json.encodeToJsonElement<PublicKey>(account))
commitment?.let { add(json.encodeToJsonElement(BalanceParams(it.value))) }
})
)
return result!!.value!!
}

private fun SolanaClient.params(
account: PublicKey,
) = JsonArray(listOf(json.encodeToJsonElement(account)))
@Serializable
internal data class BalanceParams(
val commitment: String? = null,
)
Original file line number Diff line number Diff line change
@@ -1,16 +1,35 @@
package net.avianlabs.solana.methods

import io.ktor.util.*
import io.ktor.util.encodeBase64
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.encodeToJsonElement
import net.avianlabs.solana.SolanaClient
import net.avianlabs.solana.client.RpcResponse.RPC
import net.avianlabs.solana.domain.core.Commitment

public suspend fun SolanaClient.getFeeForMessage(message: ByteArray): Long {
val result = invoke<RPC<Long>>("getFeeForMessage", params(message))
/**
* Get the fee the network will charge for a particular Message
*
* @param message Base-64 encoded Message
* @param commitment Optional [Commitment] level
*
*/
public suspend fun SolanaClient.getFeeForMessage(
message: ByteArray,
commitment: Commitment? = null
): Long {
val result = invoke<RPC<Long>>(
method = "getFeeForMessage",
params = JsonArray(buildList {
add(json.encodeToJsonElement<String>(message.encodeBase64()))
commitment?.let { add(json.encodeToJsonElement(FeeForMessageParams(it.value))) }
})
)
return result!!.value!!
}

private fun SolanaClient.params(
message: ByteArray,
) = JsonArray(listOf(json.encodeToJsonElement(message.encodeBase64())))
@Serializable
internal data class FeeForMessageParams(
val commitment: String? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,31 @@ import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.encodeToJsonElement
import net.avianlabs.solana.SolanaClient
import net.avianlabs.solana.domain.core.Commitment

/**
* Returns minimum balance required to make account rent exempt.
*
* @param dataLength the Account's data length
* @param commitment Optional [Commitment] level
*/
public suspend fun SolanaClient.getMinimumBalanceForRentExemption(
dataLength: Long,
commitment: String = "confirmed",
commitment: Commitment? = null,
): Long {
val result = invoke<Long>("getMinimumBalanceForRentExemption", params(dataLength, commitment))
val result = invoke<Long>(
method = "getMinimumBalanceForRentExemption",
params = JsonArray(buildList {
add(json.encodeToJsonElement(dataLength))
commitment?.let {
add(json.encodeToJsonElement(GetMinimumBalanceForRentExemptionParams(it.value)))
}
})
)
return result!!
}

private fun SolanaClient.params(
dataLength: Long,
commitment: String,
) = JsonArray(
listOf(
json.encodeToJsonElement(dataLength),
json.encodeToJsonElement(GetMinimumBalanceForRentExemptionParams(commitment))
)
)

@Serializable
internal data class GetMinimumBalanceForRentExemptionParams(
val commitment: String,
val commitment: String? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,29 @@ import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.encodeToJsonElement
import net.avianlabs.solana.SolanaClient
import net.avianlabs.solana.client.RpcResponse
import net.avianlabs.solana.domain.core.Commitment

/**
* Returns the latest blockhash
*
* @param commitment Optional [Commitment] level
*/
public suspend fun SolanaClient.getRecentBlockhash(
commitment: String? = null,
commitment: Commitment? = null,
): RecentBlockHash {
val rpc = invoke<RpcResponse.RPC<RecentBlockHash>>("getRecentBlockhash", params(commitment))
return rpc!!.value!!
val result = invoke<RpcResponse.RPC<RecentBlockHash>>(
method = "getRecentBlockhash",
params = JsonArray(buildList {
commitment?.let { add(json.encodeToJsonElement(RecentBlockHashParams(it.value))) }
})
)
return result!!.value!!
}

private fun SolanaClient.params(
commitment: String? = null,
) = JsonArray(listOf(json.encodeToJsonElement(commitment)))
@Serializable
public data class RecentBlockHashParams(
val commitment: String? = null,
)

@Serializable
public data class RecentBlockHash(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,36 @@ import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.encodeToJsonElement
import net.avianlabs.solana.SolanaClient
import net.avianlabs.solana.domain.core.Commitment
import net.avianlabs.solana.domain.core.PublicKey

/**
* Returns Signatures for confirmed transactions that include
* the given address in their accountKeys list.
* Returns signatures backwards in time from the provided signature or
* most recent confirmed block
*
* @param account Account address
* @param commitment Optional [Commitment] level
*/
public suspend fun SolanaClient.getSignaturesForAddress(
account: PublicKey,
commitment: String?,
commitment: Commitment? = null,
): List<SignatureInformation> {
val rpcParams = SignaturesForAddress(
commitment = commitment,
val result = invoke<List<SignatureInformation>>(
method = "getSignaturesForAddress",
params = JsonArray(buildList {
add(json.encodeToJsonElement<PublicKey>(account))
commitment?.let {
add(json.encodeToJsonElement(SignaturesForAddressParams(commitment = it.value)))
}
})
)
val result =
invoke<List<SignatureInformation>>("getSignaturesForAddress", params(account, rpcParams))
return result!!
}

private fun SolanaClient.params(
account: PublicKey,
rpcParams: SignaturesForAddress,
) = JsonArray(listOf(json.encodeToJsonElement(account), json.encodeToJsonElement(rpcParams)))

@Serializable
internal data class SignaturesForAddress(
internal data class SignaturesForAddressParams(
val limit: Long? = null,
val before: String? = null,
val until: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,34 @@ import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.encodeToJsonElement
import net.avianlabs.solana.SolanaClient
import net.avianlabs.solana.client.RpcResponse.RPC
import net.avianlabs.solana.domain.core.Commitment
import net.avianlabs.solana.domain.core.PublicKey

/**
* Returns the token balance of an SPL Token account.
*
* @param tokenAccount Pubkey of Token account to query
* @param commitment Optional [Commitment] level
*
*/
public suspend fun SolanaClient.getTokenAccountBalance(
tokenAccount: PublicKey,
commitment: Commitment? = null,
): TokenAmountInfo {
val result = invoke<RPC<TokenAmountInfo>>("getTokenAccountBalance", params(tokenAccount))
val result = invoke<RPC<TokenAmountInfo>>(
method = "getTokenAccountBalance",
params = JsonArray(buildList {
add(json.encodeToJsonElement<PublicKey>(tokenAccount))
commitment?.let { add(json.encodeToJsonElement(TokenAccountBalanceParams(it.value))) }
})
)
return result!!.value!!
}

private fun SolanaClient.params(
account: PublicKey,
) = JsonArray(listOf(json.encodeToJsonElement(account)))
@Serializable
internal data class TokenAccountBalanceParams(
val commitment: String? = null
)

@Serializable
public data class TokenAmountInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,28 @@ import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.encodeToJsonElement
import net.avianlabs.solana.SolanaClient
import net.avianlabs.solana.domain.core.Commitment

/**
* Returns transaction details for a confirmed transaction
*
* @param signature Transaction signature, as base-58 encoded string
* @param commitment Optional [Commitment] level
*
*/
public suspend fun SolanaClient.getTransaction(
signature: String,
commitment: String? = null,
commitment: Commitment? = null,
): TransactionResponse? {
val rpcParams = GetTransactionParams(
commitment = commitment,
return invoke<TransactionResponse?>(
method = "getTransaction",
params = JsonArray(buildList {
add(json.encodeToJsonElement<String>(signature))
commitment?.let { add(json.encodeToJsonElement(GetTransactionParams(it.value))) }
})
)
return invoke<TransactionResponse?>("getTransaction", params(signature, rpcParams))
}

private fun SolanaClient.params(
signature: String,
rpcParams: GetTransactionParams,
) = JsonArray(listOf(json.encodeToJsonElement(signature), json.encodeToJsonElement(rpcParams)))

@Serializable
internal data class GetTransactionParams(
val commitment: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,33 @@ import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.encodeToJsonElement
import net.avianlabs.solana.SolanaClient
import net.avianlabs.solana.client.RpcResponse.RPC
import net.avianlabs.solana.domain.core.Commitment

/**
* Returns whether a blockhash is still valid or not
*
* @param blockHash the blockhash of the block to evaluate, as base-58 encoded string
* @param commitment Optional [Commitment] level
* @param minContextSlot Optional minimum slot that the request can be evaluated at
*
*/
public suspend fun SolanaClient.isBlockHashValid(
blockHash: String,
commitment: String? = null,
commitment: Commitment? = null,
minContextSlot: Long? = null,
): Boolean {
val result =
invoke<RPC<Boolean>>("isBlockhashValid", params(blockHash, commitment, minContextSlot))
val result = invoke<RPC<Boolean>>(
method = "isBlockhashValid",
params = JsonArray(buildList {
add(json.encodeToJsonElement<String>(blockHash))
if (commitment != null || minContextSlot != null) {
add(json.encodeToJsonElement(IsBlockHashValidParams(commitment?.value, minContextSlot)))
}
})
)
return result!!.value!!
}

private fun SolanaClient.params(
blockHash: String,
commitment: String? = null,
minContextSlot: Long? = null,
) = JsonArray(
listOf(
json.encodeToJsonElement(blockHash),
json.encodeToJsonElement(IsBlockHashValidParams(commitment, minContextSlot))
)
)

@Serializable
internal data class IsBlockHashValidParams(
val commitment: String? = null,
Expand Down
Loading

0 comments on commit 3850f77

Please sign in to comment.