CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-solana--web3-js

Comprehensive JavaScript SDK for building Solana blockchain applications with modern architecture and type safety

93

1.29x

Evaluation93%

1.29x

Agent success when using this tile

Overview
Eval results
Files

transaction-building.mddocs/

Transaction Building

Comprehensive transaction message creation, compilation, and optimization with functional composition patterns and support for versioned transactions and address lookup tables.

Capabilities

Transaction Message Creation

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
);

Transaction Message Configuration

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
);

Transaction Message Compilation

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);

Transaction Compilation and Signing

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();

Address Lookup Tables

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
);

Transaction Validation

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;

Complete Transaction Building Example

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;
}

Types

/**
 * 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-js

docs

account-management.md

core-primitives.md

cryptography.md

encoding-codecs.md

error-handling.md

high-level-utilities.md

index.md

instructions-programs.md

rpc-communication.md

signing-authentication.md

transaction-building.md

tile.json