Skip to main content

Выберите транспорт

Все транспорты применяют одно и то же правило чаевых, одну и ту же валидацию и одну и ту же маршрутизацию. Транспорт меняет только то, как байты попадают на эндпоинт Apex. Ограничения на размер транзакции везде одинаковы: транзакции legacy и v0 до 1232 байт, транзакции v1 до 4096 байт.

Соберите подписанную транзакцию с чаевыми

Примеры на этой странице используют один общий хелпер для каждого языка. Он собирает memo-транзакцию с вычислительным бюджетом и чаевыми, подписывает её и умеет подтверждать подпись. Запустите его напрямую, чтобы вывести подписанную транзакцию в base64: именно её используют примеры с cURL. Сначала задайте переменные окружения:
Для примеров с cURL подписывайте свежую транзакцию перед каждой отправкой:
Транзакция действительна, только пока действителен её blockhash, примерно от 60 до 90 секунд, поэтому подписывайте непосредственно перед отправкой.

JSON-RPC sendTransaction

Отправьте POST в корень эндпоинта Apex. Это стандартный для Solana формат sendTransaction, поэтому существующий код переносится заменой URL и добавлением API-ключа.
Ответ:
Apex не выполняет симуляцию и preflight-проверки. skipPreflight и preflightCommitment ни на что не влияют. Если вам нужна симуляция, вызовите simulateTransaction на своём обычном RPC перед отправкой.

Простые HTTP-маршруты

Эти маршруты находятся рядом с JSON-RPC на том же хосте и порту и обходятся без обёртки JSON-RPC. На бинарных маршрутах параметры передаются флагами запроса: ?mev_protect=1 и &max_retries=N. Ошибки возвращаются в JSON с HTTP-статусом: {"error": "<label>", "message": "..."}. См. Ошибки и лимиты запросов.

POST /send

POST /send-bin

Самый дешёвый HTTP-путь: на входе нет ни base64, ни JSON. Тело запроса содержит сериализованную транзакцию, байт в байт.

POST /send-batch

Отправьте до 16 независимых транзакций в одном запросе. Тело представляет собой последовательность фреймов:
Каждая транзакция принимается отдельно. Пакет не атомарен: одни фреймы могут быть приняты, а другие отклонены. Для исполнения по принципу «всё или ничего» используйте Бандлы.
Если сам запрос корректен, ответ всегда приходит с HTTP 200 и содержит по одному результату на фрейм в порядке фреймов:

GET /ping

Возвращает pong. API-ключ не нужен. Используйте его, чтобы заранее открыть и прогреть HTTP-соединение и чтобы поддерживать простаивающее соединение. См. Лучшие практики.

CORS

Каждый HTTP-ответ содержит Access-Control-Allow-Origin: *, а на предварительные запросы OPTIONS даётся ответ, поэтому все перечисленные выше маршруты работают из браузерного кода. Прежде чем передавать ключ во фронтенд, прочитайте замечания о браузерах.

QUIC

QUIC является самым быстрым способом отправки. Вы держите одно постоянное соединение с эндпоинтом Apex, которое один раз аутентифицируется клиентским сертификатом, производным от вашего API-ключа, и открываете один поток на каждую транзакцию. В прогретом соединении отправка сводится к одному открытию потока и одной записи, то есть к нескольким микросекундам времени клиента. Есть два вида потоков:

Rust

Крейт apex-sender-client реализует весь транспорт: сертификат, keep-alive, возобновление 0-RTT и переподключения. Эта программа отправляет по одной транзакции в потоке каждого вида. Она использует тот же Cargo.toml, что и Быстрый старт.

Коды допуска

Двунаправленный поток отвечает одним из этих кодов: Отклонение окончательно для этого пакета. Транспортную ошибку до получения ответа можно безопасно повторять, потому что эндпоинт отсеивает дубликаты по подписи.

QUIC из других языков

Вы можете реализовать транспорт на любом языке, для которого есть библиотека QUIC с поддержкой клиентских сертификатов. Соединение
  • QUIC (RFC 9000) с TLS 1.3 и ALPN solana-tpu.
  • Сертификат сервера представляет собой самоподписанную заглушку. Не проверяйте его.
  • Клиент должен предъявить сертификат, производный от вашего API-ключа.
  • Держите одно открытое соединение на каждый эндпоинт Apex. Регулярно отправляйте QUIC PING (клиент на Rust отправляет пинг каждую секунду). Тайм-аут простоя эндпоинта составляет 30 секунд. 0-RTT включён.
Пакет транзакции Откройте поток, запишите ровно один пакет и завершите поток:
Это в точности bincode от { wire_transaction: Vec<u8>, mev_protect: bool, max_retry: Option<u16> } со стандартными параметрами bincode: целые фиксированной длины в little-endian. Весь пакет должен быть не больше 4160 байт. Фрейм допуска (только для двунаправленных потоков)
В Rust эталонной реализацией обоих фреймов служат wire::encode_packet и wire::decode_admission.