Skip to main content

Принята не значит попала в блок

Успешный ответ означает, что эндпоинт Apex получил вашу транзакцию и отправляет её лидерам наперегонки, пока она не попадёт в блок или пока не истечёт её blockhash. Он не означает, что транзакция попала в блок. Подтверждайте каждую отправку через getSignatureStatuses на Solana RPC. См. Лучшие практики.

Почему принятая транзакция не попала в блок

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

Ошибки JSON-RPC

Ошибки простых HTTP-маршрутов

На /send и /send-bin успехом считается HTTP 200 с {"signature": "..."}. /send-batch отвечает 200 с {"attempted": n, "accepted": n, "rejected": n, "results": [...]}, где каждый результат, в порядке фреймов, представляет собой либо {"signature": "..."}, либо {"error": "<label>", "message": "..."}. /send-bundle отвечает 200 с {"bundle_id": "...", "signatures": ["...", "..."]}. Ошибки возвращаются в JSON с машиночитаемой меткой и понятным человеку сообщением:
Сначала ветвите логику по HTTP-статусу. Это стабильная часть контракта. Незнакомую метку при статусе 400 трактуйте как «исправьте транзакцию».
/send-batch отвечает 200 всякий раз, когда сам запрос сформирован правильно, и сообщает о каждом фрейме отдельно внутри results. Проверяйте rejected и каждую запись, а не только код статуса. См. POST /send-batch. Метка bundle (HTTP 400) означает, что бандл отклонён целиком: в нём больше 4 участников, есть повторяющийся участник, бандлы недоступны для этого ключа или эндпоинта либо его отклонил block engine. Когда его отклоняет block engine, сообщение называет причину, если Apex её распознал (участник уже обработан, blockhash истёк или неизвестен, участник уже встречался block engine), а иначе гласит “the block engine rejected the bundle”; повтор того же бандла снова завершится ошибкой. Проблема отдельного участника сохраняет собственную метку. Участник больше своего лимита (4096 байт для v1, 1232 для legacy и v0) возвращается как malformed с сообщением, в котором назван этот лимит, два участника с чаевыми дают multiple_tips, а отсутствие участника с чаевыми даёт no_tip. Бандл, который эндпоинт не может сейчас передать в block engine, получает ответ busy (HTTP 503, JSON-RPC -32603): лимит эндпоинта на block engine в эту секунду исчерпан, block engine ограничивает эндпоинт по частоте или не ответил. Ничего не отправлено; повторите чуть позже или отправьте транзакции по отдельности. Метка nonce_used (HTTP 400, JSON-RPC -32602) означает отказ для durable nonce транзакции, подписанной на значение nonce, которое эндпоинт уже видел заменённым: этот nonce использовала другая транзакция, поэтому эта никогда не попадёт в блок. Ничего не отправляется. Значение, которого эндпоинт ещё не видел, принимается как обычно.

Ошибки чаевых подробно

Коды допуска QUIC

Двунаправленный QUIC-поток отвечает одним кодом допуска. Однонаправленный поток ничего не возвращает, поэтому на время интеграции используйте двунаправленный поток. Если отклонено само рукопожатие QUIC, соединение закрывается с ошибкой приложения 1 (нет клиентского сертификата), 2 (неизвестный ключ) или 3 (слишком много соединений). См. Аутентификация. В клиенте на Rust send_transaction_with_response превращает отклонение в Error::Rejected { code, message }, а транзакция больше 4096 байт завершается локальной ошибкой Error::TooLarge до того, как что-либо будет отправлено. В клиенте на Go SendTransactionWithResponse возвращает *apex.RejectedError с теми же Code и Message, а слишком большая транзакция завершается локальной ошибкой *apex.TooLargeError.

Какие ошибки повторять

Принятую транзакцию отправлять повторно не нужно. Apex уже повторяет её отправку, пока она не попадёт в блок или пока не истечёт blockhash. Если к этому моменту она не попала в блок, соберите её заново со свежим blockhash и отправьте новую транзакцию.

Лимиты запросов

Лимиты запросов действуют на каждый API-ключ и задаются тарифом ключа. Лимит считает транзакции в секунду по всем транспортам: JSON-RPC, HTTP-маршруты и QUIC расходуют одну и ту же квоту, а каждый фрейм пакета считается одной транзакцией. Стандартный тариф допускает 5 транзакций в секунду без запаса на всплеск: не больше 5 одновременно. Тариф pro допускает 50 в секунду и ещё 10 одновременно сверх этого. Лимит, согласованный для вашего аккаунта, заменяет скорость тарифа, а запас на всплеск остаётся прежним. При превышении лимита вы получаете -32029, HTTP 429 или код допуска 2. Отклонённая транзакция не ставится в очередь, поэтому отправьте её снова чуть позже, если она всё ещё важна. Лимит и минимум чаевых вашего тарифа показаны рядом с ключом в панели управления OrbitFlare в разделе Dashboard > Apex. Чтобы повысить их, свяжитесь с командой в Discord.

Ограничения вкратце