Skip to content

Commit

Permalink
system program test
Browse files Browse the repository at this point in the history
  • Loading branch information
wiyarmir committed Jun 13, 2024
1 parent ee69866 commit e13020d
Showing 1 changed file with 117 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -1,39 +1,128 @@
package net.avianlabs.solana.domain.program

import kotlinx.coroutines.delay
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.test.runTest
import net.avianlabs.solana.SolanaClient
import net.avianlabs.solana.client.RpcKtorClient
import net.avianlabs.solana.domain.core.Commitment
import net.avianlabs.solana.domain.core.Transaction
import net.avianlabs.solana.domain.core.TransactionBuilder
import net.avianlabs.solana.domain.core.decode
import net.avianlabs.solana.methods.*
import net.avianlabs.solana.tweetnacl.TweetNaCl
import net.avianlabs.solana.tweetnacl.ed25519.Ed25519Keypair
import kotlin.random.Random
import kotlin.test.Test
import kotlin.time.Duration.Companion.seconds

private val logger = KotlinLogging.logger { }

class SystemProgramTest {

@Ignore
@Test
@Ignore
fun testCreateDurableNonceAccount() = runBlocking {
val client = SolanaClient(client = RpcKtorClient("http://localhost:8899"))
val owner = TweetNaCl.Signature.generateKey(Random.nextBytes(32))
logger.info { "Keypair: ${owner.publicKey}" }
val nonce1 = TweetNaCl.Signature.generateKey(Random.nextBytes(32))
logger.info { "Nonce account 1: ${nonce1.publicKey}" }
val nonce2 = TweetNaCl.Signature.generateKey(Random.nextBytes(32))
logger.info { "Nonce account 2: ${nonce2.publicKey}" }
val destination = TweetNaCl.Signature.generateKey(Random.nextBytes(32))
logger.info { "Destination: ${destination.publicKey}" }

val airdrop = client.requestAirdrop(owner.publicKey, 2_000_000_000)
val airdrop2 = client.requestAirdrop(destination.publicKey, 2_000_000_000)
client.waitForTransaction(airdrop, airdrop2)

val balance = client.getBalance(owner.publicKey)
logger.info { "Balance: $balance" }

val nonce1tx = client.createNonceAccountSigned(
keypair = owner,
nonceAccount = nonce1,
)
val init1Sig = client.sendTransaction(nonce1tx)

logger.info { "Initialized nonce account 1: $init1Sig" }

val nonce2tx = client.createNonceAccountSigned(
keypair = owner,
nonceAccount = nonce2,
)

val init2Sig = client.sendTransaction(nonce2tx)

logger.info { "Initialized nonce account 2: $init2Sig" }

client.waitForTransaction(init1Sig, init2Sig)

val keypair = TweetNaCl.Signature.generateKey(Random.nextBytes(32))
println("Keypair: ${keypair.publicKey}")
val nonceAccount = TweetNaCl.Signature.generateKey(Random.nextBytes(32))
println("Nonce account: ${nonceAccount.publicKey}")
val nonceAccount1 = client.getNonce(nonce1.publicKey, Commitment.Confirmed)
logger.info { "Nonce account 1 info: $nonceAccount1" }

client.requestAirdrop(keypair.publicKey, 2_000_000_000)
delay(15.seconds)
val balance = client.getBalance(keypair.publicKey)
println("Balance: $balance")
val tx1 = transferTransaction(
nonceKeypair = nonce1,
owner = owner,
destination = destination,
nonceAccount = nonceAccount1,
)

val nonceAccount2 = client.getNonce(nonce2.publicKey, Commitment.Confirmed)
logger.info { "Nonce account 2 info: $nonceAccount2" }

val tx2 = transferTransaction(
nonceKeypair = nonce2,
owner = owner,
destination = destination,
nonceAccount = nonceAccount2,
)

val tx2Sig = client.sendTransaction(tx2)

client.waitForTransaction(tx2Sig)

val tx1Sig = client.sendTransaction(tx1)
logger.info { "Advanced nonce account: $tx1Sig" }

client.waitForTransaction(tx1Sig)

val newNonce = client.getNonce(nonce1.publicKey, Commitment.Confirmed)
logger.info { "New nonce: ${newNonce?.nonce}" }
}

private fun transferTransaction(
nonceKeypair: Ed25519Keypair,
owner: Ed25519Keypair,
destination: Ed25519Keypair,
nonceAccount: NonceAccount?
) = TransactionBuilder()
.addInstruction(
SystemProgram.nonceAdvance(
nonceAccount = nonceKeypair.publicKey,
authorized = owner.publicKey,
)
)
.addInstruction(
SystemProgram.transfer(
fromPublicKey = owner.publicKey,
toPublicKey = destination.publicKey,
lamports = 1_000,
)
)
.setRecentBlockHash(nonceAccount!!.nonce)
.build()
.sign(owner)

val rentExempt = client.getMinimumBalanceForRentExemption(SystemProgram.NONCE_ACCOUNT_LENGTH)
private suspend fun SolanaClient.createNonceAccountSigned(
keypair: Ed25519Keypair,
nonceAccount: Ed25519Keypair
): Transaction {
val rentExempt = getMinimumBalanceForRentExemption(SystemProgram.NONCE_ACCOUNT_LENGTH)

val blockhash = client.getRecentBlockhash()
val blockhash = getRecentBlockhash()

val initTransaction = Transaction()
.addInstruction(
Expand All @@ -52,46 +141,21 @@ class SystemProgramTest {
)
.setRecentBlockHash(blockhash.blockhash)
.sign(listOf(keypair, nonceAccount))
return initTransaction
}


val initSignature = client.sendTransaction(initTransaction)

println("Initialized nonce account: $initSignature")
delay(15.seconds)

val lamportsPerSignature = client.getFeeForMessage(initTransaction.message.serialize())
println("Lamports per signature: $lamportsPerSignature")

val nonce = client.getNonce(nonceAccount.publicKey, Commitment.Processed)
println("Nonce account info: $nonce")

val testTransaction = TransactionBuilder()
.addInstruction(
SystemProgram.nonceAdvance(
nonceAccount = nonceAccount.publicKey,
authorized = keypair.publicKey,
)
)
.addInstruction(
SystemProgram.transfer(
fromPublicKey = keypair.publicKey,
toPublicKey = nonceAccount.publicKey,
lamports = 1_000_000_000,
)
)
.setRecentBlockHash(nonce!!.nonce)
.build()
.sign(keypair)

val testSignature = client.sendTransaction(testTransaction)
println("Advanced nonce account: $testSignature")

delay(15.seconds)

val testTxInfo = client.getTransaction(testSignature, Commitment.Confirmed)
println("Transaction info: ${testTxInfo?.decode()}")

val newNonce = client.getNonce(nonceAccount.publicKey, Commitment.Processed)
println("New nonce account info: $newNonce")
private suspend fun SolanaClient.waitForTransaction(
vararg signatures: String,
commitment: Commitment = Commitment.Finalized,
) = coroutineScope {
signatures.map { signature ->
async {
var transactionResponse: TransactionResponse?
do {
transactionResponse = getTransaction(signature, commitment)
} while (transactionResponse == null)
logger.info { "Transaction $commitment $signature" }
}
}.awaitAll()
}
}

0 comments on commit e13020d

Please sign in to comment.