WebSocket
Gateway는 REST API와 같은 호스트와 포트에서 /ws 경로로 WebSocket을 제공합니다:
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
}
}서버가 보내는 모든 메시지는 type이 있는 JSON입니다. 이벤트는 페이로드를 data에 담고, balance, rpc_reply, error는 필드를 최상위 수준에 둡니다.
close 시에는 백오프를 두고 다시 연결하십시오 — 웹 앱은 지수적으로 늘어나는 지연을 두고 재시도합니다.
이벤트
Gateway는 POLL_NODE_INTERVAL_MS(기본값 2 000 ms)마다 노드를 폴링하고, 확인한 내용을 이벤트로 변환합니다.
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 | 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 ms)마다 확인됩니다.
잔액 구독
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 KB | 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())