Skip to main content

Transaction Interface

software.sava.core.tx.Transaction Provides methods to create, sign, and serialize Solana transactions.

Constants

int MAX_SERIALIZED_LENGTH = 1232;
int MAX_BASE_64_ENCODED_LENGTH = 1683;
int SIGNATURE_LENGTH = 64;
int BLOCK_HASH_LENGTH = 32;
int MAX_ACCOUNTS = 64;
int BLOCK_QUEUE_SIZE = 151;
int BLOCKS_UNTIL_FINALIZED = 32;

Factory Methods

Basic Transaction Creation

static Transaction createTx(
    PublicKey feePayer,
    List<Instruction> instructions
)
feePayer
PublicKey
required
Account that will pay transaction fees
instructions
List<Instruction>
required
List of instructions to execute
return
Transaction
Legacy transaction ready to sign
static Transaction createTx(List<Instruction> instructions)
return
Transaction
Transaction without explicit fee payer (uses first signer)
static Transaction createTx(
    PublicKey feePayer,
    Instruction instruction
)

With Address Lookup Tables

static Transaction createTx(
    PublicKey feePayer,
    List<Instruction> instructions,
    AddressLookupTable lookupTable
)
feePayer
PublicKey
required
Fee payer account
instructions
List<Instruction>
required
Instructions to execute
lookupTable
AddressLookupTable
required
Address lookup table for versioned transaction (v0)
return
Transaction
Versioned transaction with lookup table support
static Transaction createTx(
    AccountMeta feePayer,
    List<Instruction> instructions,
    LookupTableAccountMeta[] tableAccountMetas
)
tableAccountMetas
LookupTableAccountMeta[]
required
Multiple lookup tables for complex transactions

Signing Methods

Sign with Single Signer

void sign(Signer signer)
signer
Signer
required
Signer to sign the transaction
void sign(byte[] recentBlockHash, Signer signer)
recentBlockHash
byte[]
required
Recent block hash (32 bytes)
void sign(String recentBlockHash, Signer signer)
recentBlockHash
String
required
Base58-encoded recent block hash

Sign with Multiple Signers

void sign(SequencedCollection<Signer> signers)
signers
SequencedCollection<Signer>
required
Ordered collection of signers
void sign(
    String recentBlockHash,
    SequencedCollection<Signer> signers
)

Sign and Encode

String signAndBase64Encode(Signer signer)
return
String
Base64-encoded signed transaction ready for RPC submission
String signAndBase64Encode(
    byte[] recentBlockHash,
    Signer signer
)
String signAndBase64Encode(
    String recentBlockHash,
    SequencedCollection<Signer> signers
)

Static Signing Utilities

static void sign(
    Signer signer,
    byte[] out
)
signer
Signer
required
Signer to sign with
out
byte[]
required
Serialized transaction to sign in place
static String signAndBase64Encode(
    Signer signer,
    byte[] out
)

Transaction Manipulation

Block Hash Management

void setRecentBlockHash(byte[] recentBlockHash)
void setRecentBlockHash(String recentBlockHash)
recentBlockHash
byte[] | String
required
Recent block hash to set
byte[] recentBlockHash()
return
byte[]
Current block hash (32 bytes)

Instruction Modification

Transaction prependIx(Instruction ix)
ix
Instruction
required
Instruction to prepend
return
Transaction
New transaction with prepended instruction
Transaction appendIx(Instruction ix)
Transaction replaceInstruction(int index, Instruction instruction)
index
int
required
Index of instruction to replace
Transaction prependInstructions(
    SequencedCollection<Instruction> instructions
)
Transaction appendInstructions(
    SequencedCollection<Instruction> instructions
)

Transaction Properties

String getBase58Id()
return
String
Base58-encoded transaction signature (transaction ID)
byte[] getId()
return
byte[]
Transaction signature bytes (64 bytes)
int size()
return
int
Size of serialized transaction in bytes
boolean exceedsSizeLimit()
return
boolean
True if transaction exceeds 1232 byte limit
int version()
return
int
Transaction version (0 for versioned, -1 for legacy)
int numSigners()
return
int
Number of required signers
List<Instruction> instructions()
return
List<Instruction>
List of instructions in the transaction
AccountMeta feePayer()
return
AccountMeta
Fee payer account metadata

Serialization

byte[] serialized()
return
byte[]
Serialized transaction bytes
String base64EncodeToString()
return
String
Base64-encoded transaction for RPC submission

Example Usage

Simple Transfer

import software.sava.core.accounts.PublicKey;
import software.sava.core.accounts.Signer;
import software.sava.core.tx.Transaction;
import software.sava.core.tx.Instruction;

// Create signer
var signer = Signer.createFromKeyPair(keyPairBytes);
var fromPubKey = signer.publicKey();
var toPubKey = PublicKey.fromBase58Encoded(recipientAddress);

// Create transfer instruction
var transferIx = SystemProgram.transfer(
    fromPubKey,
    toPubKey,
    1_000_000_000L // 1 SOL in lamports
);

// Create and sign transaction
var tx = Transaction.createTx(fromPubKey, transferIx);
String blockHash = getRecentBlockhash();
tx.sign(blockHash, signer);

// Get base64-encoded transaction
String encodedTx = tx.base64EncodeToString();

// Or sign and encode in one step
String encoded = tx.signAndBase64Encode(blockHash, signer);

Multiple Instructions

import java.util.List;

// Create multiple instructions
var computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit(200_000);
var transferIx1 = SystemProgram.transfer(from, to1, amount1);
var transferIx2 = SystemProgram.transfer(from, to2, amount2);

// Create transaction with multiple instructions
var instructions = List.of(
    computeBudgetIx,
    transferIx1,
    transferIx2
);

var tx = Transaction.createTx(feePayer, instructions);
tx.sign(blockHash, signer);

Versioned Transaction with Lookup Table

// Load lookup table
var lookupTable = AddressLookupTable.read(
    lookupTableAddress,
    lookupTableData
);

// Create versioned transaction
var tx = Transaction.createTx(
    feePayer,
    instructions,
    lookupTable
);

tx.sign(blockHash, signer);

// Transaction version will be 0
assert tx.version() == 0;

Multiple Signers

import java.util.List;

// Create signers
var signer1 = Signer.createFromKeyPair(keyPair1);
var signer2 = Signer.createFromKeyPair(keyPair2);
var signer3 = Signer.createFromKeyPair(keyPair3);

// Create transaction requiring multiple signatures
var tx = Transaction.createTx(feePayer, instructions);

// Sign with all required signers
var signers = List.of(signer1, signer2, signer3);
tx.sign(blockHash, signers);

// Or sign and encode
String encoded = tx.signAndBase64Encode(blockHash, signers);

Prepend Compute Budget

// Create transaction
var tx = Transaction.createTx(feePayer, instructions);

// Prepend compute budget instruction
var budgetIx = ComputeBudgetProgram.setComputeUnitLimit(300_000);
var newTx = tx.prependIx(budgetIx);

// Sign new transaction
newTx.sign(blockHash, signer);

Best Practices

  • Always check exceedsSizeLimit() before signing
  • Use lookup tables for transactions with many accounts
  • Set compute budget for complex programs
  • Cache block hash for batch transaction creation
  • Use versioned transactions (v0) for better efficiency

Build docs developers (and LLMs) love