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

Обзор

OrbitFlare поддерживает постоянные WebSocket-соединения для получения данных Solana в реальном времени. WebSocket-подписки отправляют обновления вашему клиенту по мере их появления в блокчейне — без необходимости опроса. WebSocket-эндпоинты используют схему wss:// с теми же кодами регионов, что и HTTP API:
wss://{region}.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY
Эндпоинт основной сети с автоматической маршрутизацией:
wss://mainnet.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY
Ваш лицензионный ключ находится в разделе Лицензии вашего OrbitFlare Dashboard. Передайте его как параметр запроса api_key — тот же ключ, что используется для HTTP RPC.

Подключение

const WebSocket = require("ws");

const ws = new WebSocket(
  "wss://mainnet.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY"
);

ws.on("open", () => {
  console.log("Connected");
});

ws.on("message", (data) => {
  const msg = JSON.parse(data);
  console.log("Received:", msg);
});

ws.on("error", (err) => {
  console.error("WebSocket error:", err);
});

ws.on("close", (code, reason) => {
  console.log(`Connection closed: ${code} ${reason}`);
});
WebSocket-соединения, простаивающие более 60 секунд без обмена сообщениями, закрываются сервером. Отправляйте ping или поддерживайте активные подписки для сохранения соединения.

Методы подписки

accountSubscribe

Получайте обновления при изменении баланса lamport или данных конкретного аккаунта.
ws.on("open", () => {
  ws.send(JSON.stringify({
    jsonrpc: "2.0",
    id: 1,
    method: "accountSubscribe",
    params: [
      "83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri",
      { encoding: "base64", commitment: "confirmed" }
    ],
  }));
});
Поля обновления:
ПолеОписание
lamportsТекущий баланс в lamport
dataДанные аккаунта (кодировка определяется параметром encoding)
ownerПубличный ключ программы-владельца
executableЯвляется ли аккаунт исполняемой программой
rentEpochЭпоха, в которую следующий раз будет начислена аренда

logsSubscribe

Получайте сообщения журнала транзакций в реальном времени. Опционально фильтруйте по конкретной программе.
// All transactions
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 2,
  method: "logsSubscribe",
  params: ["all"],
}));

// Filter to a specific program
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 3,
  method: "logsSubscribe",
  params: [
    { mentions: ["675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"] }, // Raydium AMM
    { commitment: "confirmed" }
  ],
}));
Поля обновления:
ПолеОписание
signatureПодпись транзакции (base-58)
errnull при успехе, объект ошибки при сбое
logsМассив строк с сообщениями журнала

slotSubscribe

Получайте уведомление каждый раз при обработке слота.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 4,
  method: "slotSubscribe",
  params: [],
}));
Поля обновления:
ПолеОписание
slotНомер текущего слота
parentНомер родительского слота
rootНаивысший подтверждённый корневой слот

signatureSubscribe

Получайте одноразовое уведомление, когда конкретная подпись транзакции достигает заданного уровня подтверждения.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 5,
  method: "signatureSubscribe",
  params: [
    "TRANSACTION_SIGNATURE_HERE",
    { commitment: "finalized" }
  ],
}));
Подписка автоматически закрывается после отправки первого уведомления.

programSubscribe

Получайте обновления для всех аккаунтов, принадлежащих конкретной программе.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 6,
  method: "programSubscribe",
  params: [
    "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", // SPL Token
    {
      encoding: "jsonParsed",
      commitment: "confirmed",
      filters: [{ dataSize: 165 }], // Standard token account size
    }
  ],
}));

blockSubscribe

Получайте полные данные блока при его подтверждении. Требует дополнения — обратитесь в поддержку для активации.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 7,
  method: "blockSubscribe",
  params: ["all", { commitment: "confirmed", encoding: "base64" }],
}));

rootSubscribe

Получайте наивысший подтверждённый корневой слот каждый раз при его продвижении.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 8,
  method: "rootSubscribe",
  params: [],
}));

voteSubscribe

Получайте необработанные транзакции голосования по мере их появления в сети gossip. Высокий объём — фильтруйте тщательно.
ws.send(JSON.stringify({
  jsonrpc: "2.0",
  id: 9,
  method: "voteSubscribe",
  params: [],
}));

Отписка

Каждый метод подписки имеет соответствующий метод Unsubscribe. Передайте ID подписки, возвращённый в ответе на первоначальную подписку.
// Subscribe and capture the subscription ID
ws.on("message", (data) => {
  const msg = JSON.parse(data);

  // Subscription confirmation contains the subscription ID
  if (msg.id === 1 && msg.result !== undefined) {
    const subscriptionId = msg.result;
    console.log("Subscribed, ID:", subscriptionId);

    // Unsubscribe later
    ws.send(JSON.stringify({
      jsonrpc: "2.0",
      id: 10,
      method: "accountUnsubscribe",
      params: [subscriptionId],
    }));
  }
});
Доступные методы отписки: accountUnsubscribe, logsUnsubscribe, slotUnsubscribe, signatureUnsubscribe, programUnsubscribe, blockUnsubscribe, rootUnsubscribe, voteUnsubscribe.

Поддержание соединения

WebSocket-соединения закрываются после 60 секунд бездействия. Периодически отправляйте JSON-RPC ping для поддержания соединения:
const pingInterval = setInterval(() => {
  if (ws.readyState === WebSocket.OPEN) {
    ws.send(JSON.stringify({ jsonrpc: "2.0", id: 0, method: "ping" }));
  }
}, 30_000);

ws.on("close", () => clearInterval(pingInterval));

Переподключение

Реализуйте автоматическое переподключение с экспоненциальной задержкой для production-приложений:
function connect(url, onMessage) {
  let ws;
  let delay = 1000;
  let attempt = 0;

  function createConnection() {
    ws = new WebSocket(url);

    ws.on("open", () => {
      console.log("Connected (attempt", attempt + 1, ")");
      delay = 1000; // reset backoff on successful connection
      attempt = 0;
      // re-subscribe to all channels here
    });

    ws.on("message", onMessage);

    ws.on("close", () => {
      attempt++;
      const nextDelay = Math.min(delay * 2, 30_000);
      console.log(`Reconnecting in ${delay}ms...`);
      setTimeout(createConnection, delay);
      delay = nextDelay;
    });

    ws.on("error", (err) => console.error("WebSocket error:", err));
  }

  createConnection();
  return () => ws?.close();
}

const disconnect = connect(
  "wss://mainnet.rpc.orbitflare.com?api_key=YOUR_LICENSE_KEY",
  (data) => {
    const msg = JSON.parse(data);
    console.log("Update:", msg);
  }
);

Лимиты соединений

WebSocket-соединения разделяют тот же лимит на IP, что и gRPC-соединения. Подробности см. в разделе Аутентификация и лимиты.

Смотрите также