НОВОЕ: Helius приобретает Light Protocol
Представляем ускоренные вызовы getProgramAccounts (gPA)
Блог/Обновления

Представляем ускоренные вызовы getProgramAccounts (gPA)

Developer Experience Engineer0xIchigo в X0xIchigo в LinkedIn0xIchigo на GitHub
Чтение: 3 мин

Вызовы getProgramAccounts (gPA) печально известны своими проблемами. Этот метод RPC выполняет ресурсоёмкую и неэффективную операцию: обращается к ноде, чтобы получить все аккаунты, принадлежащие указанному публичному ключу. Такие вызовы часто работают медленно и имеют жёсткие ограничения по частоте запросов. Иногда они полностью запрещены (например, вызов gPA для программы Serum), если результаты ещё не кэшированы. Из-за этих проблем разработчикам приходилось искать трудоёмкие и менее эффективные альтернативы. 

Сегодня всё меняется.

Helius представляет ускоренные вызовы getProgramAccounts для всех разработчиков Solana. 

Что изменилось:

  • Мы значительно улучшили индексацию аккаунтов
  • Вызовы gPA теперь выполняются в 2–10 раз быстрее, особенно при использовании фильтров для крупных программ
  • Мы автоматически индексируем программу после одного вызова от любого разработчика, что повышает производительность для всех

Начало работы

Чтобы начать, зарегистрируйтесь в панели разработчика Helius и получите ключ API в разделе «API Keys». 

Пример getProgramAccounts

Запросим в JavaScript все аккаунты, принадлежащие программе Ore V2:

Код
const url = `https://mainnet.helius-rpc.com/?api-key=<API_KEY>`;

const getProgramAccounts = async () => {
  try {
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: "test",
        method: "getProgramAccounts",
        params: [
          "oreV2ZymfyeXgNgBdqMkumTqqAprVqgBWQfoYkrtKWQ",
          {
            "encoding": "base64",
          },

        ],

      })
    });

    const data = await response.json();

    console.log(`All Accounts Owned By The Ore v2 Program: ${JSON.stringify(data, null, 2)}`);
  } catch (error) {
    console.error(error);
  }
};

getProgramAccounts();

Разберём, как работает этот код:

  1. Настройка URL: мы создаём URL, указывающий на конечную точку Helius RPC, и передаём наш ключ API
  2. Структура запроса RPC
    • method: «getProgramAccounts» указывает, что мы хотим запросить аккаунты, принадлежащие программе
    • params — это массив из двух элементов: ID программы, которую мы хотим запросить (в данном случае программа Ore V2), и объект конфигурации запроса
  3. Кодирование: мы запрашиваем данные аккаунта в кодировке base64
  4. Обработка ошибок: мы обрабатываем возникающие ошибки с помощью блока try/catch

При выполнении этого кода в консоль будут выведены все аккаунты, принадлежащие программе Ore V2. 

Однако это базовый пример. Обычно стоит использовать фильтры, чтобы сузить результаты и повысить производительность.

Пример getProgramAccounts с фильтрами

Рассмотрим более практичный пример, в котором с помощью фильтров запрашиваются все токен-аккаунты, принадлежащие определённому адресу:

Код
const url = `https://mainnet.helius-rpc.com/?api-key=<API_KEY>`;

const getTokenAccounts = async () => {
  try {
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: "token-accounts",
        method: "getProgramAccounts",
        params: [
          "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",  // Token Program address
          {
            "encoding": "jsonParsed",  // Get parsed token data
            "filters": [
              {
                "dataSize": 165,  // Size of token account data
              },
              {
                "memcmp": {
                  "offset": 32,  // Location of owner address in the token account
                  "bytes": "YOUR_WALLET_ADDRESS"
                }
              }
            ]
          }
        ]
      })
    });
    const data = await response.json();

    data.result.forEach((account, i) => {
      const parsed = account.account.data.parsed.info;

      console.log(`-- Token Account ${i + 1}: ${account.pubkey} --`);
      console.log(`Mint: ${parsed.mint}`);
      console.log(`Amount: ${parsed.tokenAmount.uiAmount}`);
    });
  } catch (error) {
    console.error("Error fetching token accounts:", error);
  }
};

getTokenAccounts();

Этот пример развивает базовый и демонстрирует два важных способа фильтрации: фильтры dataSize и memcmp.

dataSize

Фильтр dataSize проверяет точный размер данных указанного аккаунта. Нас интересуют токен-аккаунты размером 165 байт. Фильтр сразу исключит все остальные аккаунты указанного кошелька, которые не являются токен-аккаунтами.

Фильтр memcmp (сравнение памяти)

Фильтр memcmp, или фильтр сравнения памяти, позволяет сравнивать данные, хранящиеся в определённой области памяти. Смещение задаёт позицию, с которой начинается сравнение данных. 

В нашем примере используется смещение 32, чтобы пропустить адрес минта, который хранится в первых 32 байтах памяти, поскольку нас интересует только адрес владельца. Этот фильтр вернёт только аккаунты, принадлежащие указанному адресу кошелька.

При выполнении этого кода в консоль будет выведен список всех токен-аккаунтов и их балансов для указанного адреса кошелька. Благодаря улучшенной индексации Helius такие отфильтрованные запросы выполняются значительно быстрее, чем у других традиционных провайдеров RPC.

Дополнительная помощь

Готовы избавиться от лишних сложностей и ускорить вызовы getProgramAccounts? 

Зарегистрируйтесь в панели разработчика Helius и начните создавать более производительные приложения уже сегодня. Нужна помощь? Задайте вопрос или получите поддержку в Discord-сообществе Helius!

Если вы дочитали до этого места, спасибо, anon! Укажите свой адрес электронной почты ниже, чтобы не пропускать новости Solana. Хотите продолжить обучение? Читайте свежие статьи в нашем блоге и ускорьте своё знакомство с Solana.

Подпишитесь на Helius

Следите за новостями разработки на Solana и получайте уведомления о наших публикациях