Перейти к основному содержанию

Параметры

programId
string
обязательно
Публичный ключ программы (закодирован в base-58)
config
object

Ответ

result
array
Массив объектов информации об аккаунтах
pubkey
string
Публичный ключ аккаунта (закодирован в base-58)
account
object
data
array
Данные аккаунта в указанном кодировании
executable
boolean
Является ли аккаунт исполняемым
lamports
number
Баланс аккаунта в lamports
owner
string
Владелец аккаунта (закодирован в base-58)
rentEpoch
number
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
  }));
}

Примечания

  1. Возвращает все аккаунты, принадлежащие конкретной программе
  2. Фильтры можно применять для сужения результатов
  3. Данные аккаунта можно нарезать для уменьшения размера ответа
  4. Ответ приходит немедленно, поскольку считывается из текущего состояния
  5. Для данных аккаунта можно указывать различные кодировки

Лучшие практики

  1. Используйте фильтры для эффективного запроса конкретных аккаунтов
  2. Рассмотрите использование dataSlice для уменьшения размера ответа
  3. Кэшируйте результаты при необходимости для снижения нагрузки на RPC
  4. Обрабатывайте большие наборы результатов с помощью пагинации
  5. Используйте подходящее кодирование в зависимости от ваших потребностей

Распространённые ошибки

КодСообщениеРешение
-32601Method not foundУбедитесь, что вы подключены к узлу Solana RPC
-32602Invalid paramsПроверьте параметры programId и config
-32007Account information unavailableУзел может выполнять начальную загрузку или синхронизацию

Примеры использования

  1. Анализ аккаунтов программы
    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. Мониторинг аккаунтов программы
    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. Пагинация аккаунтов программы
    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()
        }
      };
    }