GreatVoyage-v4.8.2.2) не изменены, запрос и ответ передаются байт в байт. Всё, что| Адрес (production) | node.usdtpull.com:443 |
| Адрес (staging) | node.test.usdtpull.com:443 |
| Транспорт | HTTP/2 поверх TLS (ALPN h2), не plaintext |
| Типы вызовов | только unary; стримовые методы контракта на прокси не зарегистрированы |
| Максимальный размер сообщения | 64 МБ в каждую сторону |
| Server reflection | включён (grpc.reflection.v1 и v1alpha), доступен без API-ключа |
POST /v1/api-keys). У ключа есть списокPermissionDenied /ERR_NODE_SUBSCRIPTION_NOT_FOUND. Покупается по REST:allowedIps и его максимум фиксируются в подписке в момент покупки — последующееДва независимых allowlist'а. IP вызывающего должен присутствовать и в списке API-ключа, и в
списке подписки. Это самая частая причинаPermissionDeniedна корректно подписанном запросе.
| Ключ | Значение |
|---|---|
x-api-key | публичная часть API-ключа |
x-timestamp | Unix-время в секундах; расхождение с сервером — не больше 2 минут |
x-nonce | уникальная строка на каждый запрос (UUID подходит); повтор в пределах 5 минут отклоняется как replay |
x-signature | base64 от HMAC-SHA256, см. ниже |
{timestamp}\n{nonce}\n{fullMethod}fullMethod — полное имя метода с ведущим слэшем, как оно идёт в HTTP/2-фрейме:/protocol.Wallet/GetNowBlock2. Разделитель — \n (LF, не CRLF).signature = base64( HMAC-SHA256( key = secret, message = "{timestamp}\n{nonce}\n{fullMethod}" ) )secret — приватная часть ключа: она показывается один раз при создании, на сервере хранитсяgrpcurl):.proto не нужны:protocol.Wallet (full node), protocol.WalletSolidity (solidity node),protocol.WalletExtension, protocol.Database, protocol.Monitor, protocol.Network.WalletSolidity уходят на solidity-ноду,.proto-файлы. Если клиент генерирует код заранее — берите немодифицированные протоколыGreatVoyage-v4.8.2.2 (protocol/src/main/protos): корень — api/api.proto, онcore/Tron.proto и core/contract/*.proto. Те же файлы мы отдаём интеграторамGetNowBlock2 с пустым запросом:GetAccount. Поле address имеет тип bytes, то есть в JSON у grpcurl это0x41 + 20 байт), а не base58:fullMethod входит в payload, а nonce одноразовый.x-error-code — стабильный машинный код (те же коды, что и в REST);x-retry-after-seconds — только там, где повтор имеет смысл (лимиты и квота).| Статус | x-error-code | Причина |
|---|---|---|
Unauthenticated | ERR_API_KEY_MISSING_SIGNATURE_HEADERS | не передан один из четырёх заголовков |
Unauthenticated | ERR_API_KEY_INVALID_SIGNATURE | payload собран иначе: не тот fullMethod, CRLF вместо LF, не тот secret |
Unauthenticated | ERR_API_KEY_TIMESTAMP_INVALID | часы клиента разошлись с сервером больше чем на 2 минуты |
Unauthenticated | ERR_API_KEY_REPLAY | повторно использован nonce |
Unauthenticated | ERR_API_KEY_NOT_FOUND / ERR_API_KEY_EXPIRED | ключ удалён или истёк |
Unauthenticated | ERR_API_KEY_IP_NOT_AUTHORIZED | IP не в allowlist ключа |
PermissionDenied | ERR_NODE_IP_NOT_ALLOWED | IP не в allowlist подписки |
PermissionDenied | ERR_NODE_SUBSCRIPTION_NOT_FOUND / ERR_NODE_SUBSCRIPTION_EXPIRED | нет активной подписки |
PermissionDenied | ERR_AUTH_USER_BANNED | пользователь заблокирован |
ResourceExhausted | ERR_TOO_MANY_REQUESTS | превышен rps или rpm тарифа |
ResourceExhausted | ERR_NODE_REQUEST_QUOTA_EXCEEDED | исчерпана квота запросов за период подписки |
Unavailable | — | нода недоступна; повторять с backoff |
Unimplemented | — | метод вне контракта ноды или стримовый |
MaxRequestsPerSecond берётся из тарифа, лимит в минуту выводится как rps × 60, сверхуGET /v1/node-subscription/current.node.usdtpull.com:443. Загружать .protocore/Tron.proto и core/contract/*.proto) руками.x-api-key, x-timestamp, x-nonce,x-signature. Подпись зависит от метода и времени, поэтому для отладки её удобно