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