Обзор
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) |
err | null при успехе, объект ошибки при сбое |
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-соединения. Подробности см. в разделе Аутентификация и лимиты.
Смотрите также