Jetstream v2 обслуживается на тех же эндпоинтах, что и v1 — отдельного хоста нет. Сервис
JetstreamV2 предоставляется через то же HTTP/2-соединение и маршрутизируется по пути gRPC-метода,
поэтому вы подключаетесь к региону, ближайшему к вашей инфраструктуре, точно так же, как и для v1.
США
Европа
Азиатско-Тихоокеанский регион
Город
Идентификатор региона
Эндпоинт
Нью-Йорк
ny
http://ny.jetstream.orbitflare.com
Солт-Лейк-Сити
slc
http://slc.jetstream.orbitflare.com
Город
Идентификатор региона
Эндпоинт
Франкфурт
fra
http://fra.jetstream.orbitflare.com
Амстердам
ams
http://ams.jetstream.orbitflare.com
Лондон
lon
http://lon.jetstream.orbitflare.com
Дублин
dub
http://dub.jetstream.orbitflare.com
Шяуляй, Литва
siau
http://siau.jetstream.orbitflare.com
Город
Идентификатор региона
Эндпоинт
Токио
jp
http://jp.jetstream.orbitflare.com
Сингапур
sgp
http://sgp.jetstream.orbitflare.com
Jetstream использует обычный http:// (не https://) для gRPC-соединений. gRPC согласовывает
собственную безопасность транспорта через HTTP/2. Используйте https:// только если ваш выделенный
узел явно этого требует.
Аутентификация такая же, как в v1: укажите ваш API-ключ в gRPC-заголовке метаданных x-token или
используйте аутентификацию по белому списку IP. Подробнее см. в разделе
Аутентификация.
Этот документ описывает спецификацию Protocol Buffer (protobuf), используемую OrbitFlare Jetstream v2.
Полную спецификацию можно найти в нашем репозитории на GitHub —
скачайте там jetstream_v2.proto, чтобы сгенерировать ваш клиент, или используйте определение,
воспроизведённое ниже. Пакет jetstream.v2 полностью независим от v1 — сгенерируйте из него отдельный
клиент.
SubscribeTransactions — это двунаправленный поток. Клиент отправляет последовательность сообщений
запросов — каждое несёт ровно одну полезную нагрузку — чтобы управлять своей подпиской, пока поток
открыт.
Фильтры добавляются динамически, пока поток открыт. Каждый фильтр несёт выбранный клиентом
filter_id, который возвращается в каждой совпавшей транзакции и в подтверждении валидации.
message AddFilters { repeated TxFilter filters = 1;}message TxFilter { string filter_id = 1; // client-provided, max 127 chars SubscribeRequestFilterTransactions filter = 2;}message SubscribeRequestFilterTransactions { repeated string account_include = 1; repeated string account_exclude = 2; repeated string account_required = 3; // account_required matches a tx that references AT LEAST ONE of these accounts // (any-of — identical to account_include, and identical to v1). It is NOT the // "tx must contain ALL of these accounts" meaning. // Opt-in enrichment. Default false = lean response (core fields only). Set // true to also receive fee_payer / writable_accounts / program_ids / // compute_unit_price / compute_limit / tx_size. Applies to the whole // subscription: if any of your active filters sets this true, every // transaction you receive is enriched. bool include_enrichment = 4;}
Фильтр должен указывать хотя бы один из account_include / account_exclude / account_required.
Пустые (совпадающие со всем) фильтры отклоняются — см. FilterResult.
Каждое сообщение в потоке несёт серверную временную метку и монотонно возрастающий номер sequence
(на поток), чтобы клиенты могли обнаруживать пропуски. Устанавливается ровно одна полезная нагрузка.
message Heartbeat { // Server wall-clock at emit time, milliseconds since Unix epoch. Lets // clients measure one-way skew / network delay and age out stale // connections. uint64 server_ts_ms = 1;}
Каждая совпавшая транзакция перечисляет значения filter_id, с которыми она совпала, за которыми
следует сама транзакция.
message FilteredTransaction { repeated string filter_ids = 1; TransactionMessage transaction = 2;}// TransactionMessage — a flat transaction representation (all fields inline).// Fields 1-13 are the core transaction and are always present (the default// "lean" output). Fields 14-22 are optional enrichment, emitted only when the// session opts in via SubscribeRequestFilterTransactions.include_enrichment.message TransactionMessage { // Identity / placement uint64 slot = 1; bytes signature = 2; // primary signature (signatures[0]) uint32 tx_index = 3; // position of this tx within its entry // Full signature set (repeated bytes) repeated bytes signatures = 4; // Always false: vote transactions are filtered out and never delivered (v1 and v2). bool is_vote = 5; // Message header uint32 num_required_signatures = 6; uint32 num_readonly_signed_accounts = 7; uint32 num_readonly_unsigned_accounts = 8; // Recent blockhash bytes recent_blockhash = 9; // Versioned-transaction flag. bool versioned = 10; // Core body contents repeated bytes account_keys = 11; repeated CompiledInstruction instructions = 12; repeated MessageAddressTableLookup address_table_lookups = 13; // Enrichment — emitted only when the session opts in via // SubscribeRequestFilterTransactions.include_enrichment. bytes fee_payer = 14; repeated bytes writable_accounts = 15; repeated bytes program_ids = 16; // Compute-unit price (micro-lamports per CU) from SetComputeUnitPrice; 0 if unset. // The per-CU price, NOT the total priority fee — total priority fee in lamports // ~= compute_unit_price * compute_limit / 1_000_000. uint64 compute_unit_price = 17; // Explicit SetComputeUnitLimit only; 0 if the tx sets none (no implicit // 200k-CU-per-instruction default is applied). uint32 compute_limit = 18; uint32 tx_size = 19; // Resolved addresses from a versioned tx's address_table_lookups. Emitted // only when enrichment is opted in (same gate as fields 14-19). Empty for a // legacy (non-versioned) tx; when a lookup can't be fully resolved, // alt_resolution_incomplete (field 22) is set and any addresses that did // resolve are still included. repeated bytes loaded_writable_addresses = 20; repeated bytes loaded_readonly_addresses = 21; // Set true when one or more of this transaction's address_table_lookups could // NOT be fully resolved, so the loaded_writable_addresses / // loaded_readonly_addresses above are INCOMPLETE. When true, resolve the tx's // accounts yourself from address_table_lookups (fetch the tables via // RPC). Default false = fully resolved. Emitted only under // enrichment (same gate as fields 14-21). bool alt_resolution_incomplete = 22;}
SubscribeSlots — это серверный поток событий жизненного цикла слотов. Он не принимает параметров —
откройте поток и получайте события по мере продвижения слотов.
// SubscribeSlots takes no request parameters.message SubscribeSlotsRequest {}enum SlotStatus { SLOT_STATUS_UNSPECIFIED = 0; SLOT_STATUS_ALIVE = 1; // first shred of this slot received SLOT_STATUS_COMPLETE = 2; // last shred of this slot received SLOT_STATUS_DEAD = 3; // slot skipped, or superseded by later slots without completing}message SlotEvent { uint64 slot = 1; SlotStatus status = 2; // 32-byte pubkey. Empty bytes (proto3 default) means the current leader is // unavailable. bytes current_leader = 3; // Parent slot, from the first shred received for this slot. 0 means // "unknown parent" (e.g. a DEAD event for a slot that was never observed). uint64 parent_slot = 4; uint64 sequence = 5; // monotonic per-stream}
Всегда задавайте хотя бы одно ограничение по аккаунту; пустые фильтры отклоняются.
Используйте стабильный, уникальный filter_id для каждого фильтра, чтобы вы могли сопоставлять совпадения и удалять фильтры позже.
Обогащение
Держите include_enrichment выключенным, если вам не нужны дополнительные поля — экономный вывод
меньше. Его включение не добавляет задержки; единственная цена — умеренно больший размер сообщения.
Обогащение действует на всю подписку: его включение на любом одном фильтре обогащает каждую транзакцию, которую получает сессия.
Последовательность и переподключение
Отслеживайте номер sequence для обнаружения потерянных сообщений.
Реализуйте автоматическое переподключение; при переподключении повторно отправляйте ваш AddFilters.
Живость
Используйте Heartbeat и Ping/Pong, чтобы подтвердить, что поток исправен, и измерять задержку.