WebSocket
Gateway обслуговує WebSocket за шляхом /ws на тому ж хості й порту, що і REST API:
ws://localhost:3000/wsБез автентифікації. Gateway надсилає події мережі й AI кожному підключеному клієнту; клієнт також може підписатися на баланси і викликати набір RPC-методів через той самий сокет.
Підключення
const ws = new WebSocket('ws://localhost:3000/ws')
ws.onmessage = (e) => {
const msg = JSON.parse(e.data)
switch (msg.type) {
case 'init': console.log('height', msg.data.height); break
case 'new_block': console.log('block', msg.data.height, msg.data.proposer); break
case 'tx_held': console.warn('held', msg.data.tx_hash); break
}
}Кожне повідомлення сервера — JSON з полем type. Події кладуть вміст у data; balance, rpc_reply і error мають поля на верхньому рівні.
Перепідключайтеся при close із затримкою — вебзастосунок повторює спроби з експоненційно зростаючою паузою.
Події
Gateway опитує ноду кожні POLL_NODE_INTERVAL_MS (за замовчуванням 2 000 мс) і перетворює побачене на події.
type | Коли | Поля data |
|---|---|---|
init | Одразу після підключення | height, tps, finality_ms, shard_count, validator_count, blocks, txs, total_blocks, total_txs |
metrics | Кожне опитування | tps, height, finality_ms |
new_block | З'явилася нова висота | Блок у вигляді, як його повертає GET /api/v1/blocks/:height |
validator_update | Кожні 10 блоків | nodes, total_staked, height |
tx | Gateway передав транзакцію ноді | hash, from, to, value, gas, gas_price, shard, timestamp, block |
faucet | Кран поповнив адресу | address, amount, tx_hash |
tx_held | Переказ утримано політикою Sentinel | tx_hash, to, value_human |
tx_released | Утриманий переказ звільнено | tx_hash, to, value_human |
tx_cancelled | Утриманий переказ скасовано | tx_hash, to, value_human |
tx_anomaly | Sentinel оцінив надіслану транзакцію як аномальну | tx_hash, score, category |
oracle_decision | Записано рішення AI | model, kind, subject, decision, confidence, timestamp |
model_voting_update | AI-моделі чекають підтверджень валідаторів | models, height |
contract_alert | Незвичний обсяг викликів контракту або контракт з низькою оцінкою почали викликати | address, alert, severity, call_count, delta, timestamp, model |
tx — повідомлення про надсилання
Подія tx виникає, коли gateway передає транзакцію ноді, ще до потрапляння в блок — її поле status не остаточне. Стежте за фіналізацією через new_block, підписку на баланс або GET /api/v1/transactions/:hash.
Сповіщення контрактів перевіряються кожні SENTINEL_CHECK_INTERVAL_MS (за замовчуванням 30 000 мс).
Підписка на баланс
ws.send(JSON.stringify({ type: 'subscribe_balance', address: 'neuro:<15 hex>.human' }))Gateway відповідає одразу і знову після кожного нового блоку:
{ "type": "balance", "address": "neuro:…", "balance": 50000000, "balance_human": "50", "nonce": 0 }Підписки завершуються, коли сокет закривається.
RPC через сокет
ws.send(JSON.stringify({ type: 'rpc', id: 1, method: 'get_account', params: { address: 'neuro:…' } }))
// → { "type": "rpc_reply", "id": 1, "result": { … }, "error": null }Методи відповідають REST-ендпоінтам і повертають ті самі дані:
| Група | Методи |
|---|---|
| Мережа | get_status, get_blocks, get_block, get_block_txs, get_txs, search_tx, get_account |
| Валідатори | get_validator, get_validators |
| Імена і NFT | human_name_price, register_human, get_my_nfts, get_nft, transfer_nft |
| Управління | get_governance_params, get_proposals, get_proposal, create_proposal, cast_vote |
| Сховища | get_vault_config, list_member_vaults, get_vault_proposals, create_vault_proposal, sign_vault_proposal, add_vault_member, set_vault_threshold |
| AI | get_oracle_log, get_oracle_entry, get_model_registry, get_model_registry_entry, register_model |
| Контракти | get_contracts, get_contract, get_contract_events, deploy_contract, call_contract, update_contract_score, get_certificates, get_certificate, get_contract_certificate, certify_contract |
| Тестові мережі | faucet |
Записуючим методам потрібні ті самі підписані поля, що і їхньому REST-ендпоінту (signature, public_key, nonce), усередині params.
Ліміти
| Ліміт | За замовчуванням | Змінна | При перевищенні |
|---|---|---|---|
| Розмір повідомлення | 64 КБ | WS_MAX_MSG_BYTES | {"type":"error","error":"message too large"} |
| Підписок на баланс на з'єднання | 50 | WS_MAX_SUBS_PER_CLIENT | subscription limit exceeded |
| RPC-викликів за секунду на з'єднання | 30 | WS_RPC_MAX_RPS | rpc rate limit exceeded |
| Очищення мертвих з'єднань | кожні 30 с | WS_STALE_CHECK_MS | — |
Python
import asyncio, json, websockets
async def listen():
async with websockets.connect("ws://localhost:3000/ws") as ws:
await ws.send(json.dumps({"type": "subscribe_balance", "address": "neuro:<15 hex>.human"}))
async for raw in ws:
msg = json.loads(raw)
print(msg["type"], msg.get("data", msg))
asyncio.run(listen())