Параметры
Публичный ключ программы (закодирован в base-58)
Уровень commitment (processed, confirmed, finalized)
Формат кодирования данных аккаунта (base58, base64, jsonParsed)
Смещение в данных аккаунта для начала чтения
Массив объектов фильтров для применения к аккаунтамСмещение в данных аккаунта для сравнения
Байты в кодировке base-58 для сопоставления
Размер данных аккаунта для сопоставления
Ответ
Массив объектов информации об аккаунтахПубличный ключ аккаунта (закодирован в base-58)
Данные аккаунта в указанном кодировании
Является ли аккаунт исполняемым
Баланс аккаунта в 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": "getProgramAccounts",
"params": [
"PROGRAM_ID"
]
}'
Запрос с фильтрами
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": "getProgramAccounts",
"params": [
"PROGRAM_ID",
{
"filters": [
{
"dataSize": 165
},
{
"memcmp": {
"offset": 0,
"bytes": "BASE58_ENCODED_BYTES"
}
}
]
}
]
}'
Использование web3.js
import { Connection, PublicKey } from '@solana/web3.js';
const connection = new Connection('https://fra.rpc.orbitflare.com?api_key=YOUR-API-KEY');
// 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
}));
}
Примечания
- Возвращает все аккаунты, принадлежащие конкретной программе
- Фильтры можно применять для сужения результатов
- Данные аккаунта можно нарезать для уменьшения размера ответа
- Ответ приходит немедленно, поскольку считывается из текущего состояния
- Для данных аккаунта можно указывать различные кодировки
Лучшие практики
- Используйте фильтры для эффективного запроса конкретных аккаунтов
- Рассмотрите использование dataSlice для уменьшения размера ответа
- Кэшируйте результаты при необходимости для снижения нагрузки на RPC
- Обрабатывайте большие наборы результатов с помощью пагинации
- Используйте подходящее кодирование в зависимости от ваших потребностей
Распространённые ошибки
| Код | Сообщение | Решение |
|---|
| -32601 | Method not found | Убедитесь, что вы подключены к узлу Solana RPC |
| -32602 | Invalid params | Проверьте параметры programId и config |
| -32007 | Account information unavailable | Узел может выполнять начальную загрузку или синхронизацию |
Примеры использования
-
Анализ аккаунтов программы
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()
}
};
});
}
-
Мониторинг аккаунтов программы
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;
}
}
-
Пагинация аккаунтов программы
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()
}
};
}