Sol.College

Building and sending transactions from a client

A transaction bundles instructions, a recent blockhash and signatures. Clients fetch a recent blockhash, add instructions (often including compute-budget instructions for priority fees), sign, send, and confirm at a chosen commitment level. Versioned transactions add address lookup tables so more accounts fit.

Reference: Solana docs: Transactions · Solana docs: Fees

Real code, line by line

6 excerpts from different projects. Each caption links the exact lines at the fork's pinned commit. The notes below each excerpt explain the lines that matter.

pubkeyapp/tokengator · libs/api/preset/data-access/src/lib/api-preset-minter.service.ts L846–870 @ b87eed9 · MIT · original
      payerKey: feePayer.publicKey,      recentBlockhash: blockhash,    }).compileToV0Message(addressLookupTableAccounts)     const transaction = new VersionedTransaction(transactionMessage)    transaction.sign([feePayer, authority, mintKeypair])     return this.sendAndConfirmTransaction({ transaction, blockhash, lastValidBlockHeight })  }   private async sendAndConfirmTransaction({    transaction,    blockhash,    lastValidBlockHeight,  }: {    transaction: VersionedTransaction    blockhash: string    lastValidBlockHeight: number  }): Promise<string> {    const signature = await this.solana.connection.sendTransaction(transaction, { skipPreflight: true })    this.logger.debug(`Signature: ${signature}`)    await this.solana.connection.confirmTransaction({ blockhash, lastValidBlockHeight, signature }, 'confirmed')    this.logger.debug(`Confirmed: ${signature}`)    return signature  }
  1. Line 853 return this.sendAndConfirmTransaction({ transaction, blockhash, lastValidBlockHeight }): Submits the signed transaction to the cluster.
restacked-dev/valhalla · lib/src/lib/optimizeTransaction.ts L40–65 @ 7aa9ddf · MIT · original
    signerKey,    instructions  );   const transactions: VersionedTransaction[] = [];   const recentBlockhash = await connection.getLatestBlockhash();   for (const tx of txs) {    // Get CU budget and priority fee for each tx    const [microLamportsEstimate, computeUnits] = await Promise.all([      estimatePrioritizationFee(connection, tx.instructions, 100),      getSimulationUnits(connection, tx.instructions, signerKey, lookupTables),    ]);     // console.log('Priority fees: ', microLamportsEstimate, ' / CUs: ', computeUnits);     const instructions = [      ComputeBudgetProgram.setComputeUnitLimit({        units: computeUnits || 200_000,      }),      ComputeBudgetProgram.setComputeUnitPrice({        microLamports: microLamportsEstimate,      }),      ...tx.instructions,    ];
  1. Line 46 const recentBlockhash = await connection.getLatestBlockhash();: Fetches a recent blockhash. Transactions expire if it gets too old.
  2. Line 58 ComputeBudgetProgram.setComputeUnitLimit({: Sets the compute-unit limit or price (priority fee).
ProofOfEstimate/poe-solana · app/utils/sendVersionedTransaction.ts L8–32 @ 29a7c77 · MIT · original
  TransactionSignature,  VersionedTransaction,} from "@solana/web3.js"; export const sendVersionedTransaction = async (  instructions: TransactionInstruction[],  wallet: WalletContextState,  connection: Connection) => {  if (!wallet.publicKey) {    throw new WalletNotConnectedError(connectWalletText);  }   // Get the lates block hash to use on our transaction and confirmation  let latestBlockhash = await connection.getLatestBlockhash("confirmed");   // Create a new TransactionMessage with version and compile it to version 0  const messageV0 = new TransactionMessage({    payerKey: wallet.publicKey,    recentBlockhash: latestBlockhash.blockhash,    instructions,  }).compileToV0Message();   // Create a new VersionedTransacction to support the v0 message  const transaction = new VersionedTransaction(messageV0);
  1. Line 22 let latestBlockhash = await connection.getLatestBlockhash("confirmed");: Fetches a recent blockhash. Transactions expire if it gets too old.
supermetalmons/mons-dot-rehab · web/src/app/account/account-data-access.tsx L169–194 @ 0359070 · CC0-1.0 · original
  transaction: VersionedTransaction;  latestBlockhash: { blockhash: string; lastValidBlockHeight: number };}> {  // Get the latest blockhash to use in our transaction  const latestBlockhash = await connection.getLatestBlockhash();   // Create instructions to send, in this case a simple transfer  const instructions = [    SystemProgram.transfer({      fromPubkey: publicKey,      toPubkey: destination,      lamports: amount * LAMPORTS_PER_SOL,    }),  ];   // Create a new TransactionMessage with version and compile it to legacy  const messageLegacy = new TransactionMessage({    payerKey: publicKey,    recentBlockhash: latestBlockhash.blockhash,    instructions,  }).compileToLegacyMessage();   // Create a new VersionedTransaction which supports legacy and v0  const transaction = new VersionedTransaction(messageLegacy);   return {
  1. Line 173 const latestBlockhash = await connection.getLatestBlockhash();: Fetches a recent blockhash. Transactions expire if it gets too old.
airicyu/solstage-web · src/app/account/account-data-access.tsx L191–216 @ 28fe02d · MIT · original
  transaction: VersionedTransaction;  latestBlockhash: { blockhash: string; lastValidBlockHeight: number };}> {  // Get the latest blockhash to use in our transaction  const latestBlockhash = await connection.getLatestBlockhash();   // Create instructions to send, in this case a simple transfer  const instructions = [    SystemProgram.transfer({      fromPubkey: publicKey,      toPubkey: destination,      lamports: amount * LAMPORTS_PER_SOL,    }),  ];   // Create a new TransactionMessage with version and compile it to legacy  const messageLegacy = new TransactionMessage({    payerKey: publicKey,    recentBlockhash: latestBlockhash.blockhash,    instructions,  }).compileToLegacyMessage();   // Create a new VersionedTransaction which supports legacy and v0  const transaction = new VersionedTransaction(messageLegacy);   return {
  1. Line 195 const latestBlockhash = await connection.getLatestBlockhash();: Fetches a recent blockhash. Transactions expire if it gets too old.
khtang-7777/seloongmun · web/components/account/account-data-access.tsx L171–196 @ e314413 · MIT · original
  transaction: VersionedTransaction;  latestBlockhash: { blockhash: string; lastValidBlockHeight: number };}> {  // Get the latest blockhash to use in our transaction  const latestBlockhash = await connection.getLatestBlockhash();   // Create instructions to send, in this case a simple transfer  const instructions = [    SystemProgram.transfer({      fromPubkey: publicKey,      toPubkey: destination,      lamports: amount * LAMPORTS_PER_SOL,    }),  ];   // Create a new TransactionMessage with version and compile it to legacy  const messageLegacy = new TransactionMessage({    payerKey: publicKey,    recentBlockhash: latestBlockhash.blockhash,    instructions,  }).compileToLegacyMessage();   // Create a new VersionedTransaction which supports legacy and v0  const transaction = new VersionedTransaction(messageLegacy);   return {
  1. Line 175 const latestBlockhash = await connection.getLatestBlockhash();: Fetches a recent blockhash. Transactions expire if it gets too old.

Go further