Transaction Optimization

Learn how to optimize your Solana transactions for lower fees, higher throughput, and successful execution even during network congestion.

Overview

While Solana offers high throughput and low fees compared to many other blockchains, optimizing your transactions can still provide significant benefits in terms of cost savings, execution speed, and reliability. This is especially important during periods of network congestion or when executing complex DeFi strategies.

Key Benefits: Optimized transactions can lead to lower fees, faster execution, and higher success rates, particularly during peak usage periods on the Solana network.

Difract provides tools and strategies to help you optimize your Solana transactions for:

  • Reduced compute units and priority fees
  • Higher transaction success rates
  • Improved user experience through faster confirmations
  • Efficient execution of complex DeFi operations

Solana Transaction Basics

Before diving into optimization techniques, it's important to understand how Solana transactions work:

Transaction Structure

A Solana transaction consists of:

  • Instructions: Commands to be executed by specific on-chain programs
  • Signatures: Cryptographic signatures from all required accounts
  • Recent Blockhash: A recent blockhash to prevent transaction replay
  • Compute Budget: Parameters defining compute unit limits and priority fees

Compute Units

Solana transactions consume "compute units" based on their complexity. Each transaction has:

  • A default limit of 200,000 compute units
  • The ability to request up to 1.4 million compute units
  • A compute unit price that can be adjusted to prioritize your transaction

Priority Fees

Since February 2023, Solana has implemented a priority fee market where users can pay additional fees to prioritize their transactions:

  • Priority fees are denominated in "micro-lamports per compute unit"
  • Higher priority fees can help transactions be processed faster during congestion
  • The network dynamically adjusts the base fee based on recent demand
// Example: Setting compute limits and priority fees
const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({
  units: 300000 // Request 300k compute units
});

const addPriorityFee = ComputeBudgetProgram.setComputeUnitPrice({
  microLamports: 1000 // Pay 1000 micro-lamports per compute unit
});

// Add these instructions at the beginning of your transaction
const transaction = new Transaction()
  .add(modifyComputeUnits)
  .add(addPriorityFee)
  .add(yourActualInstructions);

Optimization Strategies

Difract provides several strategies to optimize your Solana transactions:

Priority Fee Optimization

Finding the right balance for priority fees:

// Example: Getting recommended priority fee
const recommendedFee = await difract.transactions.getRecommendedPriorityFee({
  urgency: 'high', // 'low', 'medium', 'high'
  instructions: transactionInstructions,
  recent: true // Use most recent network conditions
});

console.log(recommendedFee);
// {
//   microLamports: 2500,
//   estimatedCostLamports: 750000, // 0.00075 SOL
//   networkCongestion: 'moderate',
//   confidence: 0.92
// }

Transaction Batching

Combining multiple operations into a single transaction when possible:

  • Reduces overall fee costs
  • Ensures atomic execution (all operations succeed or fail together)
  • Minimizes the number of signatures needed

Limitation: Solana transactions have a maximum size of 1232 bytes. If your batched transaction exceeds this limit, it will need to be split into multiple transactions.

// Example: Batching multiple token swaps
const batchedTx = await difract.transactions.batchOperations({
  operations: [
    {
      type: 'swap',
      fromMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
      toMint: 'So11111111111111111111111111111111111111112', // SOL
      amount: '50000000' // 50 USDC
    },
    {
      type: 'swap',
      fromMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
      toMint: 'mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So', // mSOL
      amount: '50000000' // 50 USDC
    },
    {
      type: 'stake',
      mint: 'mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So', // mSOL
      protocol: 'saber',
      pool: 'mSOL-SOL'
    }
  ],
  priorityLevel: 'medium'
});

Account Prefetching

Prefetching account data to reduce compute units:

  • Loading account data ahead of transaction execution
  • Reducing on-chain compute requirements
  • Enabling more efficient transaction planning
// Example: Prefetching accounts for a swap
const accountsData = await difract.transactions.prefetchAccounts({
  operation: 'swap',
  fromMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
  toMint: 'So11111111111111111111111111111111111111112', // SOL
  amount: '100000000', // 100 USDC
  route: 'optimal' // Let Difract find the best route
});

// Now use this data in your transaction
const optimizedTransaction = await difract.transactions.createOptimized({
  operation: 'swap',
  accountsData,
  estimatedUnits: accountsData.estimatedComputeUnits
});

Versioned Transactions

Using Solana's versioned transaction format for efficiency:

  • Support for address lookup tables (ALTs) to reduce transaction size
  • More efficient signature verification
  • Better handling of complex transactions
// Example: Creating a versioned transaction with address lookup
const { transaction, lookupTableAddresses } = await difract.transactions.createVersioned({
  instructions: yourInstructions,
  useAddressLookupTables: true
});

Network Congestion Handling

Strategies for executing transactions during periods of high network congestion:

Dynamic Priority Fees

Difract can automatically adjust priority fees based on network conditions:

// Example: Transaction with dynamic priority fee
const tx = await difract.transactions.createWithDynamicFee({
  instructions: yourInstructions,
  priorityStrategy: {
    mode: 'adaptive',
    baseMultiplier: 1.2, // Start at 1.2x the current average
    maxMultiplier: 5, // Don't go above 5x current average
    retryCount: 3, // Try up to 3 times with increasing fees
    retryIntervalMs: 5000 // Wait 5 seconds between retries
  }
});

Transaction Retry Mechanism

Automatically retry failed transactions with optimized parameters:

// Example: Transaction with automatic retry
const result = await difract.transactions.executeWithRetry({
  transaction: yourTransaction,
  wallet: yourWalletAdapter,
  retryOptions: {
    maxAttempts: 5,
    initialBackoffMs: 1000,
    maxBackoffMs: 15000,
    backoffMultiplier: 1.5,
    onRetry: (attempt, error, nextBackoff) => {
      console.log(`Retry attempt ${attempt} after ${nextBackoff}ms due to: ${error.message}`);
    }
  }
});

Network Status Awareness

Check Solana network status before executing transactions:

// Example: Checking network status before transaction
const networkStatus = await difract.network.getStatus();

if (networkStatus.congestion === 'high') {
  // Either wait, increase priority fee, or notify user
  console.log(`Network congestion is high (${networkStatus.averagePriorityFee} µLamports/CU)`);
  
  // Ask user if they want to proceed with higher fee
  const userChoice = await askUserForConfirmation({
    message: 'Network congestion is high. Proceed with increased fee?',
    estimatedFee: networkStatus.recommendedPriorityFee * estimatedComputeUnits
  });
  
  if (userChoice === 'proceed') {
    // Continue with higher priority fee
  } else {
    // Schedule for later or cancel
  }
}

Transaction Simulation

Simulate transactions before executing them to identify potential issues and optimize parameters:

Compute Unit Estimation

Simulate to determine the exact compute units needed:

// Example: Estimating compute units via simulation
const simulation = await difract.transactions.simulate({
  transaction: yourTransaction,
  commitment: 'processed'
});

console.log(simulation);
// {
//   computeUnitsUsed: 143500,
//   logs: [...],
//   success: true,
//   returnData: {...}
// }

// Now set the exact compute unit limit based on simulation result
const optimizedComputeLimit = Math.ceil(simulation.computeUnitsUsed * 1.1); // Add 10% buffer
const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({
  units: optimizedComputeLimit
});

Error Detection

Identify and fix potential transaction errors before submitting:

// Example: Error detection and resolution
try {
  const simulation = await difract.transactions.simulateWithAnalysis({
    transaction: yourTransaction
  });
  
  if (!simulation.success) {
    if (simulation.errorType === 'InsufficientFunds') {
      // Handle insufficient funds error
      console.error(`Insufficient funds: need ${simulation.requiredBalance} SOL`);
    } else if (simulation.errorType === 'ComputeBudgetExceeded') {
      // Handle compute budget exceeded
      console.error(`Compute budget exceeded: used ${simulation.computeUnitsUsed}, limit ${simulation.computeUnitLimit}`);
      
      // Automatically fix by increasing compute unit limit
      const newTransaction = await difract.transactions.adjustComputeLimit({
        transaction: yourTransaction,
        newLimit: simulation.computeUnitsUsed * 1.2 // 20% buffer
      });
      
      // Re-simulate to confirm fix
      const newSimulation = await difract.transactions.simulate({
        transaction: newTransaction
      });
      
      if (newSimulation.success) {
        // Proceed with the new transaction
        return newTransaction;
      }
    }
  }
  
  return simulation.success ? yourTransaction : null;
} catch (error) {
  console.error('Simulation error:', error);
  return null;
}

Best Practices

Follow these best practices for Solana transaction optimization:

Tip: Transaction optimization is especially important for complex DeFi operations that interact with multiple protocols or involve large amounts of capital.

General Guidelines

  • Use versioned transactions: They're more efficient and support address lookup tables
  • Batch related operations: Combine multiple instructions into a single transaction when possible
  • Prioritize during congestion: Set appropriate priority fees based on urgency
  • Simulate before sending: Always simulate transactions to catch errors early
  • Set appropriate compute limits: Request only the compute units you need (plus a small buffer)

DeFi-Specific Recommendations

  • Plan complex strategies: Break complex DeFi operations into well-planned steps
  • Monitor slippage: Set appropriate slippage tolerances based on asset liquidity
  • Use route optimization: Let Difract find the most efficient swap routes
  • Schedule non-urgent transactions: Execute during lower congestion periods when possible
// Example: Complete optimized transaction workflow
async function executeOptimizedTransaction(operationType, params) {
  // 1. Check network status
  const networkStatus = await difract.network.getStatus();
  
  // 2. Get recommended priority fee based on network conditions
  const recommendedFee = await difract.transactions.getRecommendedPriorityFee({
    urgency: params.urgency || 'medium',
    networkStatus
  });
  
  // 3. Create the transaction with appropriate compute budget
  const transaction = await difract.transactions.create({
    type: operationType,
    params: params,
    priorityFee: recommendedFee.microLamports,
    // For versioned transactions with address lookup tables
    useVersioned: true
  });
  
  // 4. Simulate to check for errors and get exact compute usage
  const simulation = await difract.transactions.simulate({
    transaction
  });
  
  if (!simulation.success) {
    throw new Error(`Transaction simulation failed: ${simulation.error}`);
  }
  
  // 5. Optimize compute limit based on simulation
  const optimizedTx = await difract.transactions.adjustComputeLimit({
    transaction,
    newLimit: Math.ceil(simulation.computeUnitsUsed * 1.1) // 10% buffer
  });
  
  // 6. Execute with retry mechanism for handling timeouts or failures
  return await difract.transactions.executeWithRetry({
    transaction: optimizedTx,
    wallet: yourWalletAdapter,
    retryOptions: {
      maxAttempts: 3,
      increaseFeeOnRetry: true
    }
  });
}

Next Steps