Advanced Method: Get priority fee estimates using account keys for specialized use cases like pre-transaction analysis, batch operations, and account pattern research.

Overview

The account keys method provides a simpler alternative to transaction serialization when you need quick fee estimates or want to estimate fees before constructing the complete transaction.

Advanced Use Cases

  • Pre-transaction analysis
  • Batch account operations
  • Market research and patterns
  • Specialized architectures

Trade-offs

  • Less accurate than serialized transactions
  • No instruction-specific analysis
  • Best for account-level patterns
Recommendation: For most applications, use the serialized transaction method instead. This account keys method is for specialized use cases where you need account-level analysis or pre-transaction planning.

When to Use Account Keys

Pre-transaction Planning

Get fee estimates before constructing complete transactions

Simplified Integration

When your architecture makes transaction serialization difficult

Quick Market Analysis

Analyze fee patterns for specific accounts without building transactions

Multi-account Analysis

Understand fee patterns across multiple accounts independently

Quick Start

1

Identify Accounts

Determine which accounts will be involved in your transaction
2

Call the API

Make a request with the account keys and desired priority level
3

Apply the Fee

Use the estimate to set priority fee in your transaction

Basic Example

import { ComputeBudgetProgram } from "@solana/web3.js";

// 1. Identify accounts involved in your transaction
const accountKeys = [
  "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Token program
  "YOUR_WALLET_ADDRESS",                          // Your wallet
  "RECIPIENT_ADDRESS"                             // Recipient
];

// 2. Get priority fee estimate
const priorityFee = await getPriorityFeeEstimate(connection, accountKeys, "Medium");

// 3. Add to your transaction
const priorityFeeIx = ComputeBudgetProgram.setComputeUnitPrice({
  microLamports: priorityFee
});
transaction.add(priorityFeeIx);

Implementation Guide

Core Function

Here’s a reusable function for getting priority fee estimates:
async function getPriorityFeeEstimate(connection, accountKeys, priorityLevel = "Medium") {
  const response = await fetch(connection.rpcEndpoint, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: "1",
      method: "getPriorityFeeEstimate",
      params: [{
        accountKeys: accountKeys,
        options: { 
          priorityLevel: priorityLevel,
          recommended: true 
        }
      }]
    })
  });
  
  const result = await response.json();
  
  if (result.error) {
    throw new Error(`Fee estimation failed: ${JSON.stringify(result.error)}`);
  }
  
  return result.result.priorityFeeEstimate;
}

Complete Example with Multiple Priority Levels

Account Types & Strategies

High-volume program accounts typically show higher priority fees due to competition.
// Popular program accounts
const programAccounts = [
  "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Token program
  "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", // Associated token program
  "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K"  // Metaplex program
];

const programFees = await getPriorityFeeEstimate(connection, programAccounts, "Medium");
console.log(`Program account fees: ${programFees} micro-lamports`);
Expected behavior: Higher fees due to high transaction volume and competition.

Advanced Configuration Options

Best Practices for Account Selection

Include Writable Accounts

Priority: Focus on accounts that will be modified
const writableAccounts = [
  "YOUR_WALLET",        // Paying fees
  "TOKEN_ACCOUNT",      // Being modified  
  "RECIPIENT_ACCOUNT"   // Receiving tokens
];

Add Key Programs

Context: Include relevant program accounts
const programAccounts = [
  "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // Token program
  "CUSTOM_PROGRAM_ID"                           // Your program
];

Error Handling & Fallbacks

class AccountBasedFeeEstimator {
  constructor(connection) {
    this.connection = connection;
    this.fallbackFee = 10000; // 10k micro-lamports fallback
  }

  async getEstimate(accountKeys, priorityLevel = "Medium") {
    try {
      // Primary attempt
      const estimate = await this.getPrimaryEstimate(accountKeys, priorityLevel);
      return estimate;
    } catch (error) {
      console.warn("Primary estimate failed:", error.message);
      
      // Fallback to different configuration
      try {
        return await this.getFallbackEstimate(accountKeys, priorityLevel);
      } catch (fallbackError) {
        console.warn("Fallback estimate failed:", fallbackError.message);
        return this.fallbackFee;
      }
    }
  }

  async getPrimaryEstimate(accountKeys, priorityLevel) {
    const response = await fetch(this.connection.rpcEndpoint, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: "1",
        method: "getPriorityFeeEstimate",
        params: [{
          accountKeys: accountKeys,
          options: { 
            priorityLevel: priorityLevel,
            recommended: true 
          }
        }]
      })
    });

    const result = await response.json();
    if (result.error) {
      throw new Error(result.error.message);
    }
    
    return result.result.priorityFeeEstimate;
  }

  async getFallbackEstimate(accountKeys, priorityLevel) {
    // Try with fewer accounts or different settings
    const coreAccounts = accountKeys.slice(0, 3); // Take first 3 accounts
    
    const response = await fetch(this.connection.rpcEndpoint, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: "1",
        method: "getPriorityFeeEstimate",
        params: [{
          accountKeys: coreAccounts,
          options: { 
            priorityLevel: "Medium", // Use medium as fallback
            evaluateEmptySlotAsZero: true
          }
        }]
      })
    });

    const result = await response.json();
    if (result.error) {
      throw new Error(result.error.message);
    }
    
    return result.result.priorityFeeEstimate;
  }
}

// Usage
const estimator = new AccountBasedFeeEstimator(connection);
const fee = await estimator.getEstimate(accountKeys, "High");

Limitations & Considerations

Account-based method limitations:
  1. Less accurate for read-only accounts - The algorithm focuses on writable accounts
  2. No instruction-specific analysis - Can’t consider specific operations
  3. Account activity dependency - Less accurate for inactive accounts
  4. No transaction size consideration - Doesn’t account for transaction complexity
When to upgrade to serialized transactions:
  • Production applications requiring highest accuracy
  • Complex transactions with multiple instructions
  • When instruction-specific fee patterns matter
  • Performance-critical applications