Parameters
Program public key (base-58 encoded)
Commitment level (processed, confirmed, finalized)
Encoding format for account data (base58, base64, jsonParsed)
Offset into account data to start reading
Array of filter objects to apply to accountsOffset into account data to compare
Base-58 encoded bytes to match
Account data size to match
Response
Array of account information objectsAccount public key (base-58 encoded)
Account data in the specified encoding
Whether the account is executable
Account balance in lamports
Account owner (base-58 encoded)
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
- Returns all accounts owned by a specific program
- Filters can be applied to narrow down results
- Account data can be sliced to reduce response size
- The response is immediate as it reads from the current state
- Different encodings can be specified for account data
Best Practices
- Use filters to efficiently query specific accounts
- Consider using dataSlice to reduce response size
- Cache results when appropriate to reduce RPC load
- Handle large result sets with pagination
- Use appropriate encoding based on your needs
Common Errors
Code | Message | Solution |
---|
-32601 | Method not found | Verify you’re connected to a Solana RPC node |
-32602 | Invalid params | Check programId and config parameters |
-32007 | Account information unavailable | Node may be bootstrapping or syncing |
Use Cases
-
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()
}
};
});
}
-
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;
}
}
-
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()
}
};
}