Skip to content

Commit

Permalink
Solana 2.0 Update (#74)
Browse files Browse the repository at this point in the history
* new branch w/refactor

* use solanakt master branch snapshot

* update with solana kt sockets/remove moshi branch

* fix up issues from auction house merge, remove deprecations

* switch to solana 2.0 release
  • Loading branch information
Funkatronics authored Oct 25, 2022
1 parent 6c5fb1d commit ababae2
Show file tree
Hide file tree
Showing 60 changed files with 494 additions and 1,624 deletions.
2 changes: 1 addition & 1 deletion lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0'

// SolanaKT
implementation 'com.github.metaplex-foundation:SolanaKT:1.1.5'
implementation 'com.github.metaplex-foundation:SolanaKT:2.0.0'

// Moshi
implementation "com.squareup.moshi:moshi:1.13.0"
Expand Down
19 changes: 0 additions & 19 deletions lib/src/main/java/com/metaplex/lib/Metaplex.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ import com.metaplex.lib.modules.nfts.NftClient
import com.metaplex.lib.drivers.solana.Connection
import com.metaplex.lib.modules.candymachines.CandyMachineClient
import com.metaplex.lib.modules.candymachinesv2.CandyMachineV2Client
import com.solana.core.PublicKey
import com.solana.models.buffer.BufferInfo
import com.solana.vendor.borshj.BorshCodable

class Metaplex(val connection: Connection,
private var identityDriver: IdentityDriver,
Expand All @@ -35,20 +32,4 @@ class Metaplex(val connection: Connection,
this.storageDriver = storageDriver
return this.storageDriver
}

@Deprecated(ASYNC_CALLBACK_DEPRECATION_MESSAGE, ReplaceWith("connection.getAccountInfo(account)"))
fun <T: BorshCodable> getAccountInfo(account: PublicKey,
decodeTo: Class<T>,
onComplete: ((Result<BufferInfo<T>>) -> Unit)){
this.connection.getAccountInfo(account, decodeTo, onComplete)
}

@Deprecated(ASYNC_CALLBACK_DEPRECATION_MESSAGE, ReplaceWith("connection.getMultipleAccountsInfo(accounts)"))
fun <T: BorshCodable> getMultipleAccountsInfo(
accounts: List<PublicKey>,
decodeTo: Class<T>,
onComplete: ((Result<List<BufferInfo<T>?>>) -> Unit)
) {
this.connection.getMultipleAccountsInfo(accounts, decodeTo, onComplete)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@
package com.metaplex.lib.drivers.solana

import com.metaplex.lib.serialization.serializers.base64.BorshAsBase64JsonArraySerializer
import com.metaplex.lib.serialization.serializers.solana.AnchorAccountSerializer
import com.metaplex.lib.serialization.serializers.solana.PublicKeyAs32ByteSerializer
import com.metaplex.lib.serialization.serializers.solana.SolanaResponseSerializer
import com.solana.core.PublicKey
import com.solana.models.buffer.Buffer
import com.solana.models.buffer.BufferInfo
import com.solana.vendor.borshj.BorshCodable
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
Expand All @@ -25,28 +21,17 @@ import kotlinx.serialization.builtins.nullable
data class AccountInfo<D>(val data: D?, val executable: Boolean,
val lamports: Long, val owner: String?, val rentEpoch: Long)

internal fun <D, T: BorshCodable> AccountInfo<D>.toBufferInfo() =
BufferInfo(data?.let { Buffer(data as T) }, executable, lamports, owner, rentEpoch)

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

@Serializable
data class AccountPublicKey(@Serializable(with = PublicKeyAs32ByteSerializer::class) val publicKey: PublicKey)

internal fun <A> SolanaAccountSerializer(serializer: KSerializer<A>) =
AccountInfoSerializer(
BorshAsBase64JsonArraySerializer(
AnchorAccountSerializer(serializer.descriptor.serialName, serializer)
)
)
AccountInfoSerializer(BorshAsBase64JsonArraySerializer(serializer))

internal fun <A> MultipleAccountsSerializer(serializer: KSerializer<A>) =
MultipleAccountsInfoSerializer(
BorshAsBase64JsonArraySerializer(
AnchorAccountSerializer(serializer.descriptor.serialName, serializer)
)
)
MultipleAccountsInfoSerializer(BorshAsBase64JsonArraySerializer(serializer))

internal fun <A> ProgramAccountsSerializer(serializer: KSerializer<A>) =
ListSerializer(
Expand All @@ -55,12 +40,6 @@ internal fun <A> ProgramAccountsSerializer(serializer: KSerializer<A>) =
).nullable
)

internal inline fun <reified A> SolanaAccountSerializer() =
AccountInfoSerializer<A?>(BorshAsBase64JsonArraySerializer(AnchorAccountSerializer()))

internal inline fun <reified A> MultipleAccountsSerializer() =
MultipleAccountsInfoSerializer<A?>(BorshAsBase64JsonArraySerializer(AnchorAccountSerializer()))

private fun <D> AccountInfoSerializer(serializer: KSerializer<D>) =
SolanaResponseSerializer(AccountInfo.serializer(serializer))

Expand Down
35 changes: 0 additions & 35 deletions lib/src/main/java/com/metaplex/lib/drivers/solana/Connection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,11 @@
package com.metaplex.lib.drivers.solana

import android.util.Base64
import com.metaplex.lib.ASYNC_CALLBACK_DEPRECATION_MESSAGE
import com.metaplex.lib.drivers.rpc.RpcRequest
import com.solana.core.PublicKey
import com.solana.core.Transaction
import com.solana.models.ProgramAccount
import com.solana.models.ProgramAccountConfig
import com.solana.models.SignatureStatusRequestConfiguration
import com.solana.models.buffer.BufferInfo
import com.solana.vendor.borshj.BorshCodable
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.serializer
Expand Down Expand Up @@ -47,37 +43,6 @@ interface Connection {
suspend fun getSignatureStatuses(signatures: List<String>,
configs: SignatureStatusRequestConfiguration?)
: Result<List<SignatureStatus>>

//region DEPRECATED METHODS
@Deprecated(ASYNC_CALLBACK_DEPRECATION_MESSAGE,
ReplaceWith("getAccountInfo(serializer, account)"))
fun <T: BorshCodable> getAccountInfo(account: PublicKey,
decodeTo: Class<T>,
onComplete: ((Result<BufferInfo<T>>) -> Unit))


@Deprecated(ASYNC_CALLBACK_DEPRECATION_MESSAGE,
ReplaceWith("getMultipleAccountsInfo(serializer, accounts)"))
fun <T: BorshCodable> getMultipleAccountsInfo(
accounts: List<PublicKey>,
decodeTo: Class<T>,
onComplete: ((Result<List<BufferInfo<T>?>>) -> Unit)
)

@Deprecated(ASYNC_CALLBACK_DEPRECATION_MESSAGE,
ReplaceWith("getProgramAccounts(serializer, account, programAccountConfig)"))
fun <T: BorshCodable> getProgramAccounts(account: PublicKey,
programAccountConfig: ProgramAccountConfig,
decodeTo: Class<T>,
onComplete: (Result<List<ProgramAccount<T>>>) -> Unit
)

@Deprecated(ASYNC_CALLBACK_DEPRECATION_MESSAGE,
ReplaceWith("getSignatureStatuses(signatures, configs)"))
fun getSignatureStatuses(signatures: List<String>,
configs: SignatureStatusRequestConfiguration?,
onComplete: ((Result<com.solana.models.SignatureStatus>) -> Unit))
//endregion
}

//region ERRORS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,14 @@ package com.metaplex.lib.drivers.solana
import com.metaplex.lib.drivers.rpc.JdkRpcDriver
import com.metaplex.lib.drivers.rpc.JsonRpcDriver
import com.metaplex.lib.drivers.rpc.RpcRequest
import com.metaplex.lib.serialization.serializers.legacy.BorshCodeableSerializer
import com.metaplex.lib.programs.token_metadata.MasterEditionAccountJsonAdapterFactory
import com.metaplex.lib.programs.token_metadata.MasterEditionAccountRule
import com.metaplex.lib.programs.token_metadata.accounts.*
import com.metaplex.lib.shared.AccountPublicKeyJsonAdapterFactory
import com.metaplex.lib.shared.AccountPublicKeyRule
import com.solana.api.Api
import com.solana.api.getAccountInfo
import com.solana.core.PublicKey
import com.solana.models.ProgramAccountConfig
import com.solana.models.SignatureStatusRequestConfiguration
import com.solana.models.buffer.BufferInfo
import com.solana.networking.NetworkingRouter
import com.solana.networking.NetworkingRouterConfig
import com.solana.networking.RPCEndpoint
import com.solana.vendor.borshj.BorshCodable
import kotlinx.coroutines.CoroutineScope
import com.solana.networking.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.JsonElement

/**
* [Connection] implementation that wraps the legacy async-callback API into the
Expand All @@ -39,39 +28,14 @@ import kotlinx.serialization.KSerializer
*
* @author Funkatronics
*/
class SolanaConnectionDriver(private val rpcService: JsonRpcDriver,
override val transactionOptions: TransactionOptions = TransactionOptions()
)
: Connection {

private var endpoint: RPCEndpoint = RPCEndpoint.mainnetBetaSolana
class SolanaConnectionDriver(
private val rpcService: JsonRpcDriver,
override val transactionOptions: TransactionOptions = TransactionOptions()
) : Connection {

@JvmOverloads
constructor(endpoint: RPCEndpoint, rpcService: JsonRpcDriver = JdkRpcDriver(endpoint.url))
: this(rpcService) { this.endpoint = endpoint }

// Some things are still using this, so need to keep a reference to it here
@Deprecated("Deprecated, use an RPC Driver implementation instead")
val solanaRPC: Api = Api(
NetworkingRouter(endpoint,
config = NetworkingRouterConfig(
listOf(
MetadataAccountRule(),
MetaplexDataRule(),
MetaplexCollectionRule(),
AccountPublicKeyRule(),
MasterEditionAccountRule(),
MetaplexCreatorRule()
),
listOf(
MetadataAccountJsonAdapterFactory(),
MetaplexDataAdapterJsonAdapterFactory(),
AccountPublicKeyJsonAdapterFactory(),
MasterEditionAccountJsonAdapterFactory()
)
)
)
)
: this(rpcService)

//region CONNECTION
override suspend fun <R> get(request: RpcRequest, serializer: KSerializer<R>): Result<R> =
Expand Down Expand Up @@ -146,56 +110,4 @@ class SolanaConnectionDriver(private val rpcService: JsonRpcDriver,
else result as Result<List<SignatureStatus>> // safe cast, null case handled above
}
//endregion

//region DEPRECATED METHODS
override fun <T: BorshCodable> getAccountInfo(
account: PublicKey,
decodeTo: Class<T>,
onComplete: (Result<BufferInfo<T>>) -> Unit
) {
CoroutineScope(Dispatchers.IO).launch {
onComplete(getAccountInfo(BorshCodeableSerializer(decodeTo), account)
.map { it.toBufferInfo() })
}
}

override fun <T : BorshCodable> getMultipleAccountsInfo(
accounts: List<PublicKey>,
decodeTo: Class<T>,
onComplete: (Result<List<BufferInfo<T>?>>) -> Unit
) {
CoroutineScope(Dispatchers.IO).launch {
onComplete(getMultipleAccountsInfo(BorshCodeableSerializer(decodeTo), accounts)
.map { it.map { it?.toBufferInfo() } })
}
}

override fun <T : BorshCodable> getProgramAccounts(
account: PublicKey,
programAccountConfig: ProgramAccountConfig,
decodeTo: Class<T>,
onComplete: (Result<List<com.solana.models.ProgramAccount<T>>>) -> Unit) {
CoroutineScope(Dispatchers.IO).launch {
onComplete(getProgramAccounts(BorshCodeableSerializer(decodeTo), account, programAccountConfig)
.map { it.map {
com.solana.models.ProgramAccount(it.account.toBufferInfo(), it.publicKey)
} })
}
}

override fun getSignatureStatuses(signatures: List<String>,
configs: SignatureStatusRequestConfiguration?,
onComplete: ((Result<com.solana.models.SignatureStatus>) -> Unit)) {
CoroutineScope(Dispatchers.IO).launch {
onComplete(getSignatureStatuses(signatures, configs).map {
com.solana.models.SignatureStatus(it.map { sigStatus ->
com.solana.models.SignatureStatus.Value(
sigStatus.slot, sigStatus.confirmations,
sigStatus.err, sigStatus.confirmationStatus
)
})
})
}
}
//endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ object CandyMachineInstructions {
AccountMeta(collectionAuthorityRecord, false, true),
AccountMeta(tokenMetadataProgram, false, false),
AccountMeta(systemProgram, false, false),
AccountMeta(Sysvar.SYSVAR_RENT_ADDRESS, false, false)
AccountMeta(Sysvar.SYSVAR_RENT_PUBKEY, false, false)
),
Borsh.encodeToByteArray(
AnchorInstructionSerializer("initialize"),
Expand Down
35 changes: 35 additions & 0 deletions lib/src/main/java/com/metaplex/lib/extensions/Result+Extensions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Connection+Extensions
* Metaplex
*
* Created by Funkatronics on 10/19/2022
*/

package com.metaplex.lib.extensions

import com.metaplex.lib.drivers.solana.Connection
import com.metaplex.lib.drivers.solana.TransactionOptions
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withTimeout

suspend fun Result<String>.confirmTransaction(
connection: Connection, transactionOptions: TransactionOptions = connection.transactionOptions
): Result<String> = withTimeout(transactionOptions.timeout.toMillis()) {

suspend fun confirmationStatus() =
connection.getSignatureStatuses(listOf(getOrThrow()), null)
.getOrNull()?.first()?.confirmationStatus

// wait for desired transaction status
while(confirmationStatus() != transactionOptions.commitment.toString()) {

// wait a bit before retrying
val millis = System.currentTimeMillis()
var inc = 0
while(System.currentTimeMillis() - millis < 300 && isActive) { inc++ }

if (!isActive) break // breakout after timeout
}

this@confirmTransaction // return result
}
Loading

0 comments on commit ababae2

Please sign in to comment.