Parameters
Array of account public keys (base-58 encoded)
Commitment level (processed, confirmed, finalized)
Encoding format for account data (base58, base64, jsonParsed)
Offset into account data to start reading
Response
Slot at which the request was processed
Array of account information objects or null for non-existent accountsAccount 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": "getMultipleAccounts",
"params": [
["ACCOUNT1", "ACCOUNT2", "ACCOUNT3"]
]
}'
Request with Encoding
curl https://rpc.orbitflare.com -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getMultipleAccounts",
"params": [
["ACCOUNT1", "ACCOUNT2"],
{
"encoding": "base64",
"dataSlice": {
"offset": 0,
"length": 100
}
}
]
}'
Using web3.js
import { Connection, PublicKey } from '@solana/web3.js';
const connection = new Connection('https://rpc.orbitflare.com');
// Get multiple accounts
const accounts = await connection.getMultipleAccounts([
new PublicKey('ACCOUNT1'),
new PublicKey('ACCOUNT2')
]);
console.log('Accounts:', accounts.value);
// Get account data slices
async function getAccountDataSlices(
pubkeys: PublicKey[],
offset: number,
length: number
) {
const accounts = await connection.getMultipleAccounts(pubkeys, {
encoding: 'base64',
dataSlice: { offset, length }
});
return accounts.value.map((account, index) => ({
pubkey: pubkeys[index].toBase58(),
exists: account !== null,
data: account?.data[0],
lamports: account?.lamports
}));
}
Notes
- Returns information for multiple accounts in a single request
- Non-existent accounts are returned as null
- 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 this method to efficiently fetch multiple accounts
- Consider using dataSlice to reduce response size
- Cache results when appropriate to reduce RPC load
- Handle null values for non-existent accounts
- 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 pubkeys and config parameters |
| -32007 | Account information unavailable | Node may be bootstrapping or syncing |
Use Cases
-
Account Batch Processing
interface AccountBatch {
accounts: Array<{
pubkey: string;
exists: boolean;
lamports: number;
owner: string;
executable: boolean;
}>;
totalLamports: number;
metadata: {
timestamp: number;
slot: number;
};
}
async function processAccountBatch(
pubkeys: PublicKey[],
chunkSize: number = 100
): Promise<AccountBatch> {
const accounts: AccountBatch['accounts'] = [];
let totalLamports = 0;
for (let i = 0; i < pubkeys.length; i += chunkSize) {
const chunk = pubkeys.slice(i, i + chunkSize);
const result = await connection.getMultipleAccounts(chunk);
chunk.forEach((pubkey, index) => {
const account = result.value[index];
const exists = account !== null;
accounts.push({
pubkey: pubkey.toBase58(),
exists,
lamports: account?.lamports || 0,
owner: account?.owner.toBase58() || '',
executable: account?.executable || false
});
if (exists) {
totalLamports += account.lamports;
}
});
}
return {
accounts,
totalLamports,
metadata: {
timestamp: Date.now(),
slot: accounts[0]?.slot || 0
}
};
}
-
Account Data Analysis
interface AccountDataAnalysis {
pubkey: string;
dataSize: number;
dataHash: string;
lamports: number;
owner: string;
metadata: {
timestamp: number;
slot: number;
};
}
async function analyzeAccountData(
pubkeys: PublicKey[],
dataSlice?: { offset: number; length: number }
): Promise<AccountDataAnalysis[]> {
const accounts = await connection.getMultipleAccounts(pubkeys, {
encoding: 'base64',
dataSlice
});
return accounts.value.map((account, index) => {
const pubkey = pubkeys[index].toBase58();
if (!account) {
return {
pubkey,
dataSize: 0,
dataHash: '',
lamports: 0,
owner: '',
metadata: {
timestamp: Date.now(),
slot: accounts.context.slot
}
};
}
const data = account.data[0];
const dataSize = Buffer.from(data, 'base64').length;
return {
pubkey,
dataSize,
dataHash: require('crypto')
.createHash('sha256')
.update(data)
.digest('hex'),
lamports: account.lamports,
owner: account.owner.toBase58(),
metadata: {
timestamp: Date.now(),
slot: accounts.context.slot
}
};
});
}
-
Account Monitoring
interface AccountChange {
pubkey: string;
type: 'created' | 'deleted' | 'modified';
previous: any;
current: any;
difference: number;
}
class AccountMonitor {
private previousAccounts: Map<string, any> = new Map();
async monitorAccounts(
pubkeys: PublicKey[],
interval: number = 5000
): Promise<AccountChange[]> {
const accounts = await connection.getMultipleAccounts(pubkeys);
const changes: AccountChange[] = [];
pubkeys.forEach((pubkey, index) => {
const address = pubkey.toBase58();
const current = accounts.value[index];
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;
}
}