Предварительные требования
Вам понадобится:
- Node.js 18+ (или среда Rust для Rust-клиента)
- URL эндпоинта gRPC OrbitFlare и токен (доступны в разделе Лицензии вашей Панели управления)
Установка
Установите официальный TypeScript-клиент Yellowstone gRPC:
npm install @triton-one/yellowstone-grpc
Или через yarn:
yarn add @triton-one/yellowstone-grpc
Подключение к эндпоинту
import Client, { CommitmentLevel, SubscribeRequest } from "@triton-one/yellowstone-grpc";
const GRPC_URL = "https://your-endpoint.grpc.orbitflare.com";
const X_TOKEN = "YOUR_GRPC_TOKEN";
const client = new Client(GRPC_URL, X_TOKEN, {
"grpc.max_receive_message_length": 64 * 1024 * 1024, // 64 МиБ
});
URL gRPC и токен находятся в разделе Лицензии Панели управления OrbitFlare. Токен передаётся вторым аргументом в new Client().
Открытие потока
const stream = await client.subscribe();
const streamClosed = new Promise<void>((resolve, reject) => {
stream.on("error", (error) => {
console.error("Ошибка потока:", error);
reject(error);
stream.end();
});
stream.on("end", () => resolve());
stream.on("close", () => resolve());
});
stream.on("data", (data) => {
if (data.slot) {
console.log("Обновление слота:", data.slot.slot);
} else if (data.transaction) {
console.log("Транзакция:", data.transaction);
} else if (data.account) {
console.log("Обновление аккаунта:", data.account);
} else if (data.pong) {
console.log("Получен pong");
}
});
Отправка первой подписки
Подписка на все обновления слотов на уровне подтверждения confirmed:
const subscribeRequest: SubscribeRequest = {
slots: {
slot: { filterByCommitment: true },
},
commitment: CommitmentLevel.CONFIRMED,
accounts: {},
accountsDataSlice: [],
transactions: {},
transactionsStatus: {},
blocks: {},
blocksMeta: {},
entry: {},
};
await new Promise<void>((resolve, reject) => {
stream.write(subscribeRequest, (err) => {
if (err == null) resolve();
else reject(err);
});
});
await streamClosed;
Поддержание соединения
Облачные балансировщики нагрузки завершают незанятые соединения gRPC примерно через 10 минут. Отправляйте ping каждые 30 секунд:
const pingRequest: SubscribeRequest = {
ping: { id: 1 },
accounts: {},
accountsDataSlice: [],
transactions: {},
transactionsStatus: {},
blocks: {},
blocksMeta: {},
slots: {},
entry: {},
};
const pingInterval = setInterval(async () => {
await new Promise<void>((resolve, reject) => {
stream.write(pingRequest, (err) => {
if (err == null) resolve();
else reject(err);
});
});
}, 30_000);
streamClosed.finally(() => clearInterval(pingInterval));
Автоматическое переподключение
Для production-приложений реализуйте автоматическое переподключение с экспоненциальной задержкой:
async function connectWithRetry(maxRetries = 10) {
let attempt = 0;
let delay = 1000;
while (attempt < maxRetries) {
try {
const stream = await client.subscribe();
// ... подключить обработчики и отправить подписку
await streamClosed;
break;
} catch (err) {
attempt++;
console.error(`Ошибка потока (попытка ${attempt}):`, err);
if (attempt >= maxRetries) throw err;
await new Promise((r) => setTimeout(r, delay));
delay = Math.min(delay * 2, 30_000);
}
}
}
Следующие шаги