Skip to main content

Building Solana transactions

A client interacts with the Solana network by submitting a transaction to the cluster. Transactions allow a client to invoke instructions of on-chain Programs.

For a full explanation, see the core docs overview of a transaction.

Add dependencies

The web3-solana library provides the abstraction classes like Transaction and AccountMeta to simplify building Solana transactions.

dependencies {
  implementation("com.solanamobile:web3-solana:0.2.5")
}

Example: Memo Program Transaction

In the following example, we are creating a Transaction that invokes the Memo Program to publish the message "Hello Solana" on-chain.

Create an instruction

A transaction instruction is comprised of a program id, a list of accounts, and instruction data specific to the program.

To create an instruction, define a list of AccountMeta that represent the accounts required by the instruction. Then pass the encoded message as data into the TransactionInstruction constructor.

import com.solana.publickey.*
import com.solana.transaction.*

// Solana Memo Program
val memoProgramId = "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
val memoProgramIdKey = SolanaPublicKey.from(memoProgramId)

// Construct the instruction
val message = "Hello Solana!"
val memoInstruction = TransactionInstruction(
memoProgramIdKey,
// Define the accounts in instruction
listOf(AccountMeta(address, true, true)),
// Pass in the instruction data as ByteArray
message.encodeToByteArray()
)

Create the Memo transaction

After creating the instructions, use Message.Builder() to assemble the instructions and a blockhash to construct the a Transaction message. Then pass the transaction message into the Transaction constructor.

See the previous Making RPC Requests guide for an example of how to fetch a blockhash.

import com.solana.rpc.SolanaRpcClient
import com.solana.networking.KtorNetworkDriver

// Fetch blockhash from RPC
val rpcClient = SolanaRpcClient("https://api.devnet.solana.com", KtorNetworkDriver())
val blockhasResponse = rpcClient.getLatestBlockhash()

if (response.error) {
println("Failed to fetch latest blockhash: ${response.error.message}")
return;
}

// Build transaction message
val memoTxMessage = Message.Builder()
.addInstruction(memoInstruction) // Pass in instruction from previous step
.setRecentBlockhash(blockhasResponse.result!!.blockhash)
.build()

// Construct the Transaction object from the message
val unsignedTx = Transaction(memoTxMessage)

Next steps

Read the following Using Mobile Wallet Adapter guide to learn how to sign these transactions and submit them to the Solana network.