Документация

Справочник RPC API

HTTP-интерфейс, который узел отдаёт кошелькам: четыре метода, JSON для состояния и ошибок и компактное двоичное кодирование блоков и платежей.

Тестовая сеть: монеты ничего не стоят

Адрес публичного тестового узла — https://node.tint.top. Интерфейс никогда не видит ключей и сумм: кошелёк отправляет готовые платежи и читает целые блоки, которые расшифровывает сам.

Методы

Метод и путьЧто отвечает
GET /v1/statusГде сейчас цепочка, в JSON.
GET /v1/blocks/{height}Один финализированный блок в проводном кодировании.
GET /v1/blocks?from=NБлоки с платежами начиная с высоты N, пачкой блоков.
POST /v1/transactionsПринимает платёж в проводном кодировании; отвечает его идентификатором в JSON.

GET /v1/status

запрос
curl -s https://node.tint.top/v1/status
ответ (значения для примера)
{
  "chain_id": 6073471695170043905,
  "height": 128431,
  "tip": "9f3c…e21a",
  "genesis": "04b7…c9d0",
  "queued": 0,
  "pools": [
    { "asset": 1, "native": 20000000000000, "other": 10000000000000, "fee_bps": 30 }
  ]
}
ПолеСмысл
chain_idИдентификатор сети, вшитый в каждую подпись и хеш блока.
heightВысота последнего финализированного блока.
tipХеш последнего финализированного блока, hex.
genesisХеш первого блока, hex. У двух тестовых сетей может быть один chain_id; по этому хешу их различают.
queuedПлатежей, ожидающих блока.
pools[].assetМонета, которую пул обменивает на родную (1 — TUSD).
pools[].native, pools[].otherЧто держит пул, в единицах (1 монета = 100 000 000 единиц), на последнем финализированном блоке.
pools[].fee_bpsКомиссия пула в десятитысячных долях; 30 — это 0,3 %.

GET /v1/blocks/{height}

Возвращает один финализированный блок как application/octet-stream. Финализированный блок не меняется, поэтому в ответе Cache-Control: public, max-age=31536000, immutable. Нечисловая высота даёт invalid_height, неизвестная — not_found.

GET /v1/blocks?from=N

Возвращает блоки с платежами начиная с высоты N одной пачкой (application/octet-stream) вместе с последней высотой, за которую ответ отвечает (through). Догоняющий кошелёк спрашивает снова с высоты после through. Ответ растёт вместе с цепочкой, поэтому он идёт с Cache-Control: no-store. from — целое число.

POST /v1/transactions

Отправьте готовый платёж в проводном кодировании как тело запроса. Собирает его кошелёк; формат описан в модуле wire.rs крейта tint-core: поля фиксированной ширины, у каждого значения одно допустимое кодирование, лишних байтов в конце нет.

запрос
curl -s -X POST https://node.tint.top/v1/transactions \
  -H 'content-type: application/octet-stream' \
  --data-binary @payment.bin
ответ
{ "txid": "5be1…07af" }

Транзакция начинается с актива (u32), высоты срока действия (u64) и вида (0 — платёж, 1 — обмен), затем идёт пачка: флаги, баланс значений, якорь, число действий и сами действия с доказательством. У обмена добавляются купленная монета, внесённая сумма и вторая пачка.

Ошибки

Ошибки приходят в JSON: {"error":{"code":"...","message":"..."}}.

HTTPcodeСмысл
400malformedТело — не платёж.
400invalid_heightВысота или from — не целое число.
404not_foundНет финализированного блока такой высоты или нет такого ресурса.
409double_spendЗапись этого платежа уже потрачена.
409conflictДругой ожидающий платёж тратит одну из тех же записей.
409price_movedПул больше не даёт того, что просит этот обмен.
413too_largeПлатёж больше, чем допускает цепочка.
422rejectedПлатёж нарушает правило цепочки; в сообщении сказано, какое.
429rate_limitedЭтот клиентский адрес исчерпал свой запас запросов. Повторите после времени из заголовка Retry-After.
500internalУзел не смог проверить или закодировать.
503busy, queue_fullУзел проверяет другие платежи или его очередь полна. Повторите; Retry-After: 1.

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

По умолчанию каждому клиентскому адресу можно 50 запросов в секунду постоянно, с всплеском в 100, и одновременно проверяются не больше 4 платежей на всех клиентов. Операторы могут менять оба числа. За обратным прокси узел считает клиентов по последнему адресу, который прокси записал в X-Forwarded-For; более ранним записям он не верит.

Пример: следить за цепочкой

python (на сервере)
import json, time, urllib.request

BASE = "https://node.tint.top"

while True:
    with urllib.request.urlopen(f"{BASE}/v1/status", timeout=10) as r:
        status = json.load(r)
    print(status["height"], status["queued"])
    time.sleep(5)

Оператор узла по этому интерфейсу может узнать только сетевой адрес, с которого пришёл платёж. Суммы, отправители и получатели — внутри доказательства и зашифрованных записей.