Parameters

programId
string
required
Program public key (base-58 encoded)
config
object

Response

result
array
Array of account information objects
pubkey
string
Account public key (base-58 encoded)
account
object
data
array
Account data in the specified encoding
executable
boolean
Whether the account is executable
lamports
number
Account balance in lamports
owner
string
Account owner (base-58 encoded)
rentEpoch
number
Epoch at which the account will next owe rent

Code Examples

Basic Request

curl https://rpc.orbitflare.com -X POST -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "getProgramAccounts",
  "params": [
    "PROGRAM_ID"
  ]
}'

Request with Filters

curl https://rpc.orbitflare.com -X POST -H "Content-Type: application/json" -d '{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "getProgramAccounts",
  "params": [
    "PROGRAM_ID",
    {
      "filters": [
        {
          "dataSize": 165
        },
        {
          "memcmp": {
            "offset": 0,
            "bytes": "BASE58_ENCODED_BYTES"
          }
        }
      ]
    }
  ]
}'

Using web3.js

import { Connection, PublicKey } from '@solana/web3.js';

const connection = new Connection('https://rpc.orbitflare.com');

// Get all program accounts
const accounts = await connection.getProgramAccounts(
  new PublicKey('PROGRAM_ID')
);
console.log('Accounts:', accounts);

// Get filtered program accounts
async function getFilteredProgramAccounts(
  programId: PublicKey,
  filters: any[]
) {
  const accounts = await connection.getProgramAccounts(programId, {
    filters
  });
  
  return accounts.map(({ pubkey, account }) => ({
    pubkey: pubkey.toBase58(),
    data: account.data,
    lamports: account.lamports,
    owner: account.owner.toBase58(),
    executable: account.executable
  }));
}

Notes

  1. Returns all accounts owned by a specific program
  2. Filters can be applied to narrow down results
  3. Account data can be sliced to reduce response size
  4. The response is immediate as it reads from the current state
  5. Different encodings can be specified for account data

Best Practices

  1. Use filters to efficiently query specific accounts
  2. Consider using dataSlice to reduce response size
  3. Cache results when appropriate to reduce RPC load
  4. Handle large result sets with pagination
  5. Use appropriate encoding based on your needs

Common Errors

CodeMessageSolution
-32601Method not foundVerify you’re connected to a Solana RPC node
-32602Invalid paramsCheck programId and config parameters
-32007Account information unavailableNode may be bootstrapping or syncing

Use Cases

  1. Program Account Analysis
    interface ProgramAccountAnalysis {
      pubkey: string;
      dataSize: number;
      dataHash: string;
      lamports: number;
      metadata: {
        timestamp: number;
      };
    }
    
    async function analyzeProgramAccounts(
      programId: PublicKey,
      filters?: any[]
    ): Promise<ProgramAccountAnalysis[]> {
      const accounts = await connection.getProgramAccounts(programId, {
        filters,
        encoding: 'base64'
      });
      
      return accounts.map(({ pubkey, account }) => {
        const data = account.data[0];
        const dataSize = Buffer.from(data, 'base64').length;
        
        return {
          pubkey: pubkey.toBase58(),
          dataSize,
          dataHash: require('crypto')
            .createHash('sha256')
            .update(data)
            .digest('hex'),
          lamports: account.lamports,
          metadata: {
            timestamp: Date.now()
          }
        };
      });
    }
    
  2. Program Account Monitoring
    interface ProgramAccountChange {
      pubkey: string;
      type: 'created' | 'deleted' | 'modified';
      previous: any;
      current: any;
      difference: number;
    }
    
    class ProgramAccountMonitor {
      private previousAccounts: Map<string, any> = new Map();
      
      async monitorProgramAccounts(
        programId: PublicKey,
        filters?: any[],
        interval: number = 5000
      ): Promise<ProgramAccountChange[]> {
        const accounts = await connection.getProgramAccounts(programId, {
          filters
        });
        const changes: ProgramAccountChange[] = [];
        
        accounts.forEach(({ pubkey, account }) => {
          const address = pubkey.toBase58();
          const current = account;
          const previous = this.previousAccounts.get(address);
          
          if (!previous && current) {
            changes.push({
              pubkey: address,
              type: 'created',
              previous: null,
              current,
              difference: current.lamports
            });
          } else if (previous && !current) {
            changes.push({
              pubkey: address,
              type: 'deleted',
              previous,
              current: null,
              difference: -previous.lamports
            });
          } else if (previous && current) {
            const difference = current.lamports - previous.lamports;
            if (difference !== 0 || current.data[0] !== previous.data[0]) {
              changes.push({
                pubkey: address,
                type: 'modified',
                previous,
                current,
                difference
              });
            }
          }
          
          this.previousAccounts.set(address, current);
        });
        
        return changes;
      }
    }
    
  3. Program Account Pagination
    interface ProgramAccountPage {
      accounts: Array<{
        pubkey: string;
        data: any;
        lamports: number;
      }>;
      total: number;
      page: number;
      pageSize: number;
      metadata: {
        timestamp: number;
      };
    }
    
    async function getProgramAccountPage(
      programId: PublicKey,
      page: number = 1,
      pageSize: number = 100,
      filters?: any[]
    ): Promise<ProgramAccountPage> {
      const accounts = await connection.getProgramAccounts(programId, {
        filters,
        encoding: 'base64'
      });
      
      const start = (page - 1) * pageSize;
      const end = start + pageSize;
      const pageAccounts = accounts.slice(start, end);
      
      return {
        accounts: pageAccounts.map(({ pubkey, account }) => ({
          pubkey: pubkey.toBase58(),
          data: account.data[0],
          lamports: account.lamports
        })),
        total: accounts.length,
        page,
        pageSize,
        metadata: {
          timestamp: Date.now()
        }
      };
    }