orbitflare-apex является эталонным клиентом для Apex. Он держит одно постоянное QUIC-соединение на каждый эндпоинт Apex, аутентифицируется клиентским сертификатом, производным от вашего API-ключа, отправляет одну сериализованную транзакцию на поток и переподключается с 0-RTT при обрыве соединения.
Установка
Крейт опубликован на crates.io под именемorbitflare-apex; исходный код находится на GitHub:
rpc добавляет HTTP-хелперы: getTipAccounts, JSON-RPC sendTransaction, бинарные маршруты, а также хелпер для blockhash и подтверждения на любом Solana RPC. Сам путь QUIC не имеет HTTP-зависимостей, поэтому не включайте эту фичу, если вам нужен только QUIC.
Это единственная зависимость, которая нужна, чтобы собрать и отправить транзакцию. Крейт реэкспортирует типы Solana через orbitflare_apex::prelude, закреплённые на тех версиях, с которыми работает эндпоинт, поэтому вам не нужно самостоятельно добавлять или подбирать версию ни одного крейта solana-*.
Крейт требует Rust 1.92 или новее.
Быстрый старт
Cargo.toml см. на вкладке Rust в разделе Быстрый старт.
Регионы
Region перечисляет все эндпоинты Apex. Region::parse("fra") и Region::code() преобразуют короткие коды в обе стороны, а Region::ALL содержит их список.
region.quic_endpoint() возвращает <code>.apex.orbitflare.com:7001, а region.rpc_url() возвращает http://<code>.apex.orbitflare.com. См. Эндпоинты и регионы.
Транспорты
Транспорт не влияет на приоритет и маршрутизацию. На них влияют чаевые.
API
Clone клиента обходится дёшево, и клоны разделяют одно соединение. Создайте его один раз и раздайте клоны своим задачам.
Отправляйте бандлы через
rpc::RpcClient::send_bundle(&[&[u8]]), который возвращает BundleAccepted (bundle_id и signatures). Опрашивайте bundle_statuses(&[&str]) для получения BundleStatus (state, landed_slot). До MAX_BUNDLE (4) членов, ровно один с чаевыми.Prelude
use orbitflare_apex::prelude::*; подключает всё необходимое, чтобы собрать, подписать и отправить транзакцию с чаевыми, поэтому программа, использующая клиент, не зависит напрямую ни от одного крейта solana-*. Каждый тип реэкспортируется в той версии, с которой работает эндпоинт, что избавляет от подбора версий, который иначе ломает сборку (крейты Solana смешивают wincode 0.5 и 0.6 в разных патч-релизах).
Типы публичного API (
VersionedTransaction, Instruction, Keypair, Pubkey, Signature, Hash) также доступны в корне крейта. Если вы предпочитаете собирать транзакции на своих собственных крейтах Solana, сериализуйте их сами и отправляйте байты через send_transaction_bytes, который не разделяет с клиентом граф зависимостей.
Параметры
ClientOptions реализует Default, поэтому задавайте только то, что вам нужно:
Keep-alive и переподключения
Соединение остаётся открытым благодаря QUIC PING каждую секунду при тайм-ауте простоя 30 секунд на эндпоинте Apex. В прогретом соединении отправка сводится к одному открытию потока и одной записи. Если соединение оборвалось:- Фоновая задача замечает это и сразу выполняет новое рукопожатие (
proactive_reconnect), поэтому следующая отправка обычно находит живое соединение. - Переподключение использует закэшированный сессионный тикет и отправляет ожидающую транзакцию в первом пакете рукопожатия (0-RTT). Если эндпоинт отклоняет ранние данные, клиент отправляет их повторно после рукопожатия.
- Отправка, которая не удалась из-за потери соединения, переподключается и повторяется один раз (
auto_reconnect). Установите значениеfalse, чтобы обрабатывать это самостоятельно. - При каждом переподключении имя хоста разрешается заново, поэтому клиент на
Region::Globalследует за балансировщиком к следующему ближайшему эндпоинту, когда его собственный выходит из строя, без перезапуска. Разрешение выполняется в фоновом переподключении, а не при отправке; если оно не удалось или заняло больше двух секунд, клиент сохраняет прежний адрес. Эндпоинт, заданный IP-адресом, никогда не разрешается.
health(), reconnects_total() и zero_rtt_resumptions_total() показывают, что произошло. Экспортируйте их в свои метрики.
Ошибки
HTTP-хелперы возвращают
rpc::RpcError: Http для транспортных сбоев, Rpc { code, message } для отклонения JSON-RPC или простого HTTP-маршрута и BadResponse.
Примеры в репозитории
Все примеры читаютAPEX_API_KEY, KEYPAIR_PATH (по умолчанию payer.json), SOLANA_RPC_URL и при необходимости APEX_REGION, APEX_QUIC, APEX_RPC, TIP_LAMPORTS, APEX_TX_VERSION (legacy или v1), APEX_MEMO_BYTES и APEX_CU_LIMIT. Каждый отправляет memo с чаевыми и сообщает слот, в который оно попало.
Чего клиент не делает
- Не собирает и не подписывает транзакции и не выбирает вашу приоритетную комиссию.
- Не выполняет симуляцию и preflight-проверки. Этого не делает никто между вами и лидером.