Comprehensive JavaScript SDK for building Solana blockchain applications with modern architecture and type safety
93
Evaluation — 93%
↑ 1.29xAgent success when using this tile
Comprehensive transaction message creation, compilation, and optimization with functional composition patterns and support for versioned transactions and address lookup tables.
Build transaction messages using a functional, step-by-step approach.
/**
* Base transaction message structure
*/
type BaseTransactionMessage = {
readonly instructions: readonly IInstruction[];
readonly version: TransactionVersion;
};
/**
* Create an empty transaction message with specified version
* @param config - Version configuration
* @returns Empty transaction message
*/
function createTransactionMessage<TVersion extends TransactionVersion>(
config: { version: TVersion }
): Extract<TransactionMessage, { version: TVersion }>;
/**
* Add instructions to a transaction message
* @param instructions - Instructions to append
* @param transactionMessage - Existing transaction message
* @returns New transaction message with added instructions
*/
function appendTransactionMessageInstructions<TTransactionMessage>(
instructions: readonly IInstruction[],
transactionMessage: TTransactionMessage
): TTransactionMessage;
/**
* Add a single instruction to a transaction message
* @param instruction - Instruction to append
* @param transactionMessage - Existing transaction message
* @returns New transaction message with added instruction
*/
function appendTransactionMessageInstruction<TTransactionMessage>(
instruction: IInstruction,
transactionMessage: TTransactionMessage
): TTransactionMessage;
/**
* Add instructions to the beginning of a transaction message
* @param instructions - Instructions to prepend
* @param transactionMessage - Existing transaction message
* @returns New transaction message with prepended instructions
*/
function prependTransactionMessageInstructions<TTransactionMessage>(
instructions: readonly IInstruction[],
transactionMessage: TTransactionMessage
): TTransactionMessage;
/**
* Add a single instruction to the beginning of a transaction message
* @param instruction - Instruction to prepend
* @param transactionMessage - Existing transaction message
* @returns New transaction message with prepended instruction
*/
function prependTransactionMessageInstruction<TTransactionMessage>(
instruction: IInstruction,
transactionMessage: TTransactionMessage
): TTransactionMessage;Usage Examples:
import {
createTransactionMessage,
appendTransactionMessageInstructions,
setTransactionMessageFeePayer,
address
} from "@solana/web3.js";
// Start with empty transaction
const baseMessage = createTransactionMessage({ version: 0 });
// Add instructions
const withInstructions = appendTransactionMessageInstructions(
[
// Your instructions here
{
programId: address("11111111111111111111111111111112"),
accounts: [],
data: new Uint8Array()
}
],
baseMessage
);
// Set fee payer (required for compilation)
const withFeePayer = setTransactionMessageFeePayer(
address("your-fee-payer-address"),
withInstructions
);Set fee payer and lifetime constraints on transaction messages.
/**
* Set the fee payer for a transaction message
* @param feePayer - Address that will pay transaction fees
* @param transactionMessage - Transaction message to modify
* @returns Transaction message with fee payer set
*/
function setTransactionMessageFeePayer<TTransactionMessage>(
feePayer: Address,
transactionMessage: TTransactionMessage
): TTransactionMessage & ITransactionMessageWithFeePayer;
/**
* Set blockhash-based lifetime constraint
* @param lifetimeConstraint - Blockhash and last valid block height
* @param transactionMessage - Transaction message to modify
* @returns Transaction message with lifetime constraint
*/
function setTransactionMessageLifetimeUsingBlockhash<TTransactionMessage>(
lifetimeConstraint: {
blockhash: Blockhash;
lastValidBlockHeight: bigint;
},
transactionMessage: TTransactionMessage
): TTransactionMessage & ITransactionMessageWithBlockhashLifetime;
/**
* Set durable nonce-based lifetime constraint
* @param durableNonceConfig - Nonce configuration
* @param transactionMessage - Transaction message to modify
* @returns Transaction message with durable nonce lifetime
*/
function setTransactionMessageLifetimeUsingDurableNonce<TTransactionMessage>(
durableNonceConfig: {
nonce: Nonce;
nonceAccountAddress: Address;
nonceAuthorityAddress: Address;
},
transactionMessage: TTransactionMessage
): TTransactionMessage & ITransactionMessageWithDurableNonceLifetime;Usage Examples:
import {
createTransactionMessage,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash,
createSolanaRpc,
address
} from "@solana/web3.js";
const rpc = createSolanaRpc("https://api.devnet.solana.com");
// Get recent blockhash
const { value: { blockhash, lastValidBlockHeight } } = await rpc
.getLatestBlockhash()
.send();
// Build transaction step by step
const message = createTransactionMessage({ version: 0 });
const withFeePayer = setTransactionMessageFeePayer(
address("your-fee-payer-address"),
message
);
const readyToCompile = setTransactionMessageLifetimeUsingBlockhash(
{ blockhash, lastValidBlockHeight },
withFeePayer
);Convert transaction messages to compiled format for network transmission.
/**
* Compile a transaction message to bytes
* @param transactionMessage - Compilable transaction message
* @returns Compiled transaction message bytes
*/
function compileTransactionMessage<TTransactionMessage extends CompilableTransactionMessage>(
transactionMessage: TTransactionMessage
): CompiledTransactionMessage;
/**
* Decompile transaction message bytes back to readable format
* @param compiledTransactionMessage - Compiled message bytes
* @param config - Optional decompilation configuration
* @returns Decompiled transaction message
*/
function decompileTransactionMessage(
compiledTransactionMessage: CompiledTransactionMessage,
config?: {
addressesByLookupTableAddress?: ReadonlyMap<Address, readonly Address[]>;
}
): TransactionMessage;Usage Examples:
import {
compileTransactionMessage,
createTransactionMessage,
appendTransactionMessageInstructions,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash
} from "@solana/web3.js";
// Build complete transaction message
const message = createTransactionMessage({ version: 0 });
const withInstructions = appendTransactionMessageInstructions(myInstructions, message);
const withFeePayer = setTransactionMessageFeePayer(feePayerAddress, withInstructions);
const compilableMessage = setTransactionMessageLifetimeUsingBlockhash(
{ blockhash, lastValidBlockHeight },
withFeePayer
);
// Compile to bytes
const compiledMessage = compileTransactionMessage(compilableMessage);Convert transaction messages to final transaction format ready for network submission.
/**
* Compile a transaction message to a transaction
* @param transactionMessage - Compilable transaction message
* @returns Transaction with empty signatures
*/
function compileTransaction<TTransactionMessage extends CompilableTransactionMessage>(
transactionMessage: TTransactionMessage
): Transaction;
/**
* Sign a transaction with keypairs
* @param keyPairs - Array of key pairs to sign with
* @param transaction - Transaction to sign
* @returns Fully signed transaction
*/
function signTransaction<TTransaction extends Transaction>(
keyPairs: readonly CryptoKeyPair[],
transaction: TTransaction
): Promise<TTransaction & ITransactionWithSignatures>;
/**
* Partially sign a transaction
* @param keyPairs - Array of key pairs to sign with
* @param transaction - Transaction to sign
* @returns Partially signed transaction
*/
function partiallySignTransaction<TTransaction extends Transaction>(
keyPairs: readonly CryptoKeyPair[],
transaction: TTransaction
): Promise<TTransaction>;
/**
* Get wire-format transaction bytes
* @param transaction - Signed transaction
* @returns Base64-encoded transaction bytes for network submission
*/
function getBase64EncodedWireTransaction(transaction: Transaction): Base64EncodedWireTransaction;Usage Examples:
import {
compileTransaction,
signTransaction,
getBase64EncodedWireTransaction,
generateKeyPair
} from "@solana/web3.js";
// Compile transaction message to transaction
const transaction = compileTransaction(compilableMessage);
// Sign transaction
const keyPair = await generateKeyPair();
const signedTransaction = await signTransaction([keyPair], transaction);
// Get wire format for network submission
const wireTransaction = getBase64EncodedWireTransaction(signedTransaction);
// Now ready to send via RPC
const signature = await rpc.sendTransaction(wireTransaction).send();Optimize transaction size using address lookup tables for frequently used addresses.
/**
* Compress transaction message using address lookup tables
* @param transactionMessage - Transaction message to compress
* @param addressesByLookupTableAddress - Map of lookup table addresses to their address lists
* @returns Compressed transaction message
*/
function compressTransactionMessageUsingAddressLookupTables<
TTransactionMessage extends BaseTransactionMessage
>(
transactionMessage: TTransactionMessage,
addressesByLookupTableAddress: ReadonlyMap<Address, readonly Address[]>
): TTransactionMessage;Usage Examples:
import {
compressTransactionMessageUsingAddressLookupTables,
address
} from "@solana/web3.js";
// Define address lookup table
const lookupTableAddress = address("your-lookup-table-address");
const lookupTableAddresses = [
address("frequently-used-address-1"),
address("frequently-used-address-2"),
// ... more addresses
];
const addressLookupMap = new Map([
[lookupTableAddress, lookupTableAddresses]
]);
// Compress transaction using lookup tables
const compressedMessage = compressTransactionMessageUsingAddressLookupTables(
transactionMessage,
addressLookupMap
);Utilities for validating transaction messages and their properties.
/**
* Check if transaction message has blockhash lifetime constraint
* @param transactionMessage - Transaction message to check
* @returns True if message uses blockhash lifetime
*/
function isTransactionMessageWithBlockhashLifetime(
transactionMessage: BaseTransactionMessage
): transactionMessage is TransactionMessageWithBlockhashLifetime;
/**
* Check if transaction is a durable nonce transaction
* @param transaction - Transaction to check
* @returns True if transaction uses durable nonce
*/
function isDurableNonceTransaction(
transaction: BaseTransactionMessage
): transaction is DurableNonceTransactionMessage;
/**
* Assert that transaction is fully signed
* @param transaction - Transaction to validate
* @throws Error if transaction is not fully signed
*/
function assertTransactionIsFullySigned(
transaction: Transaction
): asserts transaction is FullySignedTransaction;import {
createTransactionMessage,
appendTransactionMessageInstructions,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash,
compileTransaction,
signTransaction,
createSolanaRpc,
generateKeyPair,
address
} from "@solana/web3.js";
async function buildAndSendTransaction() {
const rpc = createSolanaRpc("https://api.devnet.solana.com");
// 1. Get blockhash
const { value: { blockhash, lastValidBlockHeight } } = await rpc
.getLatestBlockhash()
.send();
// 2. Create base transaction
const message = createTransactionMessage({ version: 0 });
// 3. Add instructions
const withInstructions = appendTransactionMessageInstructions([
{
programId: address("11111111111111111111111111111112"),
accounts: [],
data: new Uint8Array()
}
], message);
// 4. Set fee payer
const feePayerKeyPair = await generateKeyPair();
const feePayerAddress = await getAddressFromPublicKey(feePayerKeyPair.publicKey);
const withFeePayer = setTransactionMessageFeePayer(feePayerAddress, withInstructions);
// 5. Set lifetime constraint
const compilableMessage = setTransactionMessageLifetimeUsingBlockhash(
{ blockhash, lastValidBlockHeight },
withFeePayer
);
// 6. Compile to transaction
const transaction = compileTransaction(compilableMessage);
// 7. Sign transaction
const signedTransaction = await signTransaction([feePayerKeyPair], transaction);
// 8. Send transaction
const wireTransaction = getBase64EncodedWireTransaction(signedTransaction);
const signature = await rpc.sendTransaction(wireTransaction).send();
console.log("Transaction sent:", signature);
return signature;
}/**
* Base transaction message
*/
type BaseTransactionMessage = {
readonly instructions: readonly IInstruction[];
readonly version: TransactionVersion;
};
/**
* Transaction message with fee payer
*/
interface ITransactionMessageWithFeePayer {
readonly feePayer: Address;
}
/**
* Transaction message with blockhash lifetime
*/
interface ITransactionMessageWithBlockhashLifetime {
readonly lifetimeConstraint: {
readonly blockhash: Blockhash;
readonly lastValidBlockHeight: bigint;
};
}
/**
* Transaction message with durable nonce lifetime
*/
interface ITransactionMessageWithDurableNonceLifetime {
readonly lifetimeConstraint: {
readonly nonce: Nonce;
};
}
/**
* Transaction message ready for compilation
*/
type CompilableTransactionMessage = BaseTransactionMessage &
ITransactionMessageWithFeePayer &
(ITransactionMessageWithBlockhashLifetime | ITransactionMessageWithDurableNonceLifetime);
/**
* Compiled transaction
*/
interface Transaction {
readonly messageBytes: TransactionMessageBytes;
readonly signatures: SignaturesMap;
readonly lifetimeConstraint: BlockhashLifetimeConstraint | NonceLifetimeConstraint;
}
/**
* Signature map for transaction
*/
type SignaturesMap = Record<Address, SignatureBytes | null>;
/**
* Wire-encoded transaction for network submission
*/
type Base64EncodedWireTransaction = string & { readonly __brand: unique symbol };Install with Tessl CLI
npx tessl i tessl/npm-solana--web3-jsdocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10