Параметры
Массив публичных ключей аккаунтов (закодированных в base-58)
Уровень commitment (processed, confirmed, finalized)
Формат кодирования данных аккаунта (base58, base64, jsonParsed)
Смещение в данных аккаунта для начала чтения
Ответ
Слот, при котором был обработан запрос
Массив объектов информации об аккаунтах или null для несуществующих аккаунтовДанные аккаунта в указанном кодировании
Является ли аккаунт исполняемым
Баланс аккаунта в lamports
Владелец аккаунта (закодирован в base-58)
Epoch, при котором аккаунт должен будет в следующий раз заплатить аренду
Примеры кода
Базовый запрос
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -X POST -H "Content-Type: application/json" -d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getMultipleAccounts",
"params": [
["ACCOUNT1", "ACCOUNT2", "ACCOUNT3"]
]
}'
Запрос с кодированием
curl https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY -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
}
}
]
}'
Использование web3.js
import { Connection, PublicKey } from '@solana/web3.js';
const connection = new Connection('https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY');
// 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
}));
}
Примечания
- Возвращает информацию о нескольких аккаунтах в одном запросе
- Несуществующие аккаунты возвращаются как null
- Данные аккаунта можно нарезать для уменьшения размера ответа
- Ответ приходит немедленно, поскольку считывается из текущего состояния
- Для данных аккаунта можно указывать различные кодировки
Лучшие практики
- Используйте этот метод для эффективного получения нескольких аккаунтов
- Рассмотрите использование dataSlice для уменьшения размера ответа
- Кэшируйте результаты при необходимости для снижения нагрузки на RPC
- Обрабатывайте значения null для несуществующих аккаунтов
- Используйте подходящее кодирование в зависимости от ваших потребностей
Распространённые ошибки
| Код | Сообщение | Решение |
|---|
| -32601 | Method not found | Убедитесь, что вы подключены к узлу Solana RPC |
| -32602 | Invalid params | Проверьте параметры pubkeys и config |
| -32007 | Account information unavailable | Узел может выполнять начальную загрузку или синхронизацию |
Примеры использования
-
Пакетная обработка аккаунтов
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
}
};
}
-
Анализ данных аккаунтов
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
}
};
});
}
-
Мониторинг аккаунтов
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;
}
}