Для разработчиков / API приложений

HTTP API приложений

Рядом с сетью стоят четыре собственных сервиса. Ни один из них не является сетью, ни один не версионируется, и каждый отказывает по-своему - ради этого раздел и существует.

Что это такое

Интерфейс сети - это JSON-RPC. Всё на этих страницах - то, что приложение построило для себя и оставило доступным: индекс Postgres поверх спула логов секвенсера, процесс, держащий ключ, игровой цикл. Это удобно, это своё, и это не является источником истины.

Чтение отсюда - не чтение из сети

Каждая цифра здесь прошла через индексатор, кеш или и то и другое. Остановившийся индексатор продолжает отвечать своим последним состоянием, и ни одно поле в ответе об этом не говорит; единственные маршруты, которые вам это скажут, - маршруты здоровья, и их надо спросить. Если от ответа зависят деньги, читайте сеть.

A read-only view of what the Pepper indexer has derived from the chain's logs: constant-product pools, concentrated pools, swaps, liquidity events and positions. It reads Postgres rather than the chain, deliberately.

Стек
Python, standard-library ThreadingHTTPServer, psycopg pool of at most 8 connections, HTTP/1.1
Смонтирован
/api/ on the Pepper origin

The archive the node deliberately is not. Blocks, mini-blocks, transactions, receipts, logs, call traces, decoded transfers, accounts, tokens, NFTs and the name-service record, all from a Postgres index fed by the sequencer's own log spool.

Стек
Python, standard-library ThreadingHTTPServer, psycopg pool of at most 12 connections, plus live reads against the node
Смонтирован
/api/ on the explorer origin

The only first-party service that WRITES to the chain. It holds the faucet operator key and submits the drip on your behalf, which is why the page needs no wallet.

Стек
Python, standard-library SimpleHTTPRequestHandler serving a static site as well as the API, signing with eth-account
Смонтирован
its own origin; the home origin re-exposes two of its routes

A WebSocket server for the games, with a small HTTP surface beside it for health and for the figures the site's chrome draws. The socket is the interface; the HTTP routes are a snapshot of it.

Стек
Node, `ws` in noServer mode behind a plain http server, one event loop for eight game rooms
Смонтирован
/api/ and /ws/ on the arcade origin

Где они отвечают

СервисБазовый URL
API обозревателяhttps://explorer.picklechain.xyz/api/также смонтирован на /api/ сайтами сервиса имён и набора инструментов
API DEX Pepperhttps://pepper.picklechain.xyz/api/только тот же источник; браузер с другого источника вызвать его не может
Кранhttps://faucet.picklechain.xyzдомашний источник заново отдаёт POST /drip и GET /faucet-status
Аркадаhttps://minigame.picklechain.xyz/api/и сокет на wss://minigame.picklechain.xyz/ws/<room>

Ни у одного из этих сервисов нет собственного имени хоста. Каждый - это монтирование /api/ на источнике какого-то фронтенда, что делает публичную базу фактом nginx, а не фактом сервиса: развёртывание, которое переносит сайт, переносит вместе с ним и его API, а путь внутри остаётся тем же. В стеке, который вы запускаете сами, те же сервисы отвечают на локальной петле, на порту, который называет страница каждого из них.

Никакого версионирования, нигде

Нет ни /v1, ни заголовка версии, ни политики устаревания ни у одного из четырёх. В репозитории нет также ни документа OpenAPI, ни JSON Schema, так что поле может сменить форму между двумя развёртываниями, и сравнить будет не с чем. Читайте защитно: игнорируйте ключи, которых не знаете, и не падайте на ключе, который исчез.

Аутентификация

Ни один из четырёх не требует аутентификации, и важно здесь то, что каждый из них может сделать без неё.

  • Обозреватель, API DEX и аркада не требуют ничего. Они только на чтение и публичны. Обозреватель отвечает 405 на любой POST; API DEX не реализует никакого глагола, кроме GET.
  • Кран тоже ничего не требует, и он пишет в сеть. Именно поэтому его квота строга и резервируется до того, как что-либо подписано.

У сокета аркады нет аутентификации, а процесс держит ключ

Перед ним нет слоя аутентификации, и он не планируется: прокси передаёт апгрейд, и всё. Защищает его то, что каждое измерение соединения ограничено - количество, источник, размер кадра, частота сообщений, буферизованные байты, - и каждое переполнение отбрасывается, а не ставится в очередь. Ничто из сказанного клиентом по этому сокету ничего не авторизует; кто может играть, решают контракты.

Вызов из браузера

CORS настроен для каждого сервиса по-своему, и между собой они не согласованы, так что первое, что надо установить, - может ли страница с вашего источника вообще вызвать нужный вам сервис.

  • API DEX не отправляет заголовка CORS и не имеет обработчика OPTIONS. fetch из браузера с другого источника отказывает наглухо, тогда как тот же запрос с сервера проходит, - это тот вид бага, который списывают на сеть. Проксируйте его или вызывайте с бэкенда.
  • Обозреватель и кран держат списки разрешённых. Предварительный запрос с источника, которого в списке нет, получает отказ 403 - это по крайней мере внятный ответ.
  • Аркада проверяет Origin при апгрейде и отказывает 403 до рукопожатия, так что сокет вовсе не открывается, вместо того чтобы открыться и замолчать.

Пределы и постраничность

Частоту запросов ограничивает только обозреватель. Остальные три опираются на ограничение сверху, квоту или потолок соединений.

СервисПредел
Pepper DEX API`limit` is clamped to 1..500 on every list route and defaults to 50. There is no request-rate limit in the service.
Explorer API300 requests per minute per client address, then 429. Request bodies are capped at 600,000 bytes. Live streams are capped at 32 concurrent.
FaucetQuota is reserved before the transaction is signed: 5 a day per address seen, 2 a day per funded address, 1000 a day in total. Request bodies are capped at 4096 bytes.
Arcade server256 sockets in total and 8 per source address, then the upgrade is refused 429. Inbound frames are 4 KiB at most and rate-limited per socket. A socket more than 512 KiB behind is cut.

Ограниченный сверху список молча становится коротким

Попросите у API DEX тысячу свопов и получите пятьсот, с 200 и без единого признака, что ответ обрезали. Попросите у обозревателя двести блоков и получите сто. Ни один из двух сервисов не возвращает итог на большинстве маршрутов списков, так что нет поля, с которым можно сравнить длину вашей страницы, - единственный сигнал, что есть ещё, это то, что вы получили ровно предел.

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

Соглашения

СоглашениеValue
VersioningNone of them is versionedno /v1, no version header, no deprecation policy. A field can change shape between two deployments. Read defensively and pin nothing.
SchemaThere is no OpenAPI documentand no JSON Schema anywhere in the repository. Every shape documented here was read out of a route handler, which is why each record names the line.
Errors{"error": "..."}a human-readable string, occasionally with a second key. There are no error codes and no stable error strings - match on the HTTP status, never on the message.
Cachingcache-control: no-storeon every route of all four services, without exception. Nothing here is safe to cache, and nothing offers you an ETag to revalidate against.
Content typeJSONwith two exceptions: the explorer's logo route returns raw image bytes, and its live route is an event stream.
Unitsnot uniformtoken amounts and wei are DECIMAL STRINGS, not numbers, because they do not survive a double. Mini-block timestamps are in MICROSECONDS. Concentrated-pool swap amounts are SIGNED.

Суммы - строки, и некоторые из них знаковые

Количества токенов, wei и балансы возвращаются повсюду десятичными СТРОКАМИ, потому что они не переживают double. Разбирайте их типом длинной арифметики. На маршрутах концентрированных пулов суммы к тому же знаковые - одна нога каждого свопа отрицательна, и именно это говорит, в какую сторону прошла сделка, - так что сумма, не берущая модули, сводит целый рынок к нулю.

javascript
// The shape of a careful call against any of these: a timeout, a status check
// before the body, and a big-integer parse of anything that looks like money.
const res = await fetch(`${BASE}/pools`, { signal: AbortSignal.timeout(5000) });
if (!res.ok) throw new Error(`pools: ${res.status}`);          // never the message
const { pools } = await res.json();                              // an object, not an array
const reserve0 = BigInt(pools[0].reserve0);                      // a decimal string

Когда один из них лежит

Каждый из четырёх отказывает по-своему, и только один из этих отказов выглядит отказом снаружи.

  • API DEX отвечает 503 index not ready, когда база данных недоступна или индексатор ни разу не отработал, так что таблиц не существует. Это честный случай. Нечестный - индексатор, который ОСТАНОВИЛСЯ: все маршруты продолжают отвечать тем состоянием, до которого он дошёл, и говорит об этом только lagBlocks на /health.
  • Обозреватель продолжает отдавать индекс, когда узел недоступен, а те части ответа, которым нужно живое чтение - баланс, запись сервиса имён, ожидающий баланс маршрутизатора комиссий, - возвращаются нулевыми или отсутствуют, а не дают ошибку. Следить надо за полем indexLag на /stats.
  • Кран отвечает 502, когда узел не отвечает, и ничего не было подписано. 503 означает, что у него кончились средства или что drip сделал revert.
  • /ready аркады отвечает 503, когда её сокет к узлу упал или когда последний мини-блок, который она ПРИМЕНИЛА, старше пяти секунд. Измерение прибытия вместо этого позволяло заклинившему процессу отвечать 200, когда ничего не двигалось.
Повторяйте статус, а не запись

Пишет только кран, и 502 от него означает, что ничего не было отправлено - вот его повторить безопасно. 503 после того, как транзакция ушла, - нет: drip мог долететь, а резервирование квоты уже откатили, так что опрашивайте сеть на предмет квитанции, а не отправляйте снова.

Что задокументировано в другом месте

  • The node. Chain state, transactions, logs and subscriptions are JSON-RPC and are documented in this reference's own RPC pages, not here.
  • Contracts. What the pools, the faucet and the games actually do on chain - their functions, their events and their revert reasons - is the contract reference.
  • Prices. Several answers here carry a dollar figure or a price snapshot. Those fields come from a layer this page does not own; read its own reference for what the number means, how old it is and when it is absent.