Skip to content

WebSocket ​

Gateway 在与其 REST API 相同的主机和端口上,于 /ws 提供 WebSocket 服务:

ws://localhost:3000/ws

无需认证。Gateway 会向每个已连接的客户端推送链上事件和 AI 事件;客户端也可以在同一个 socket 上订阅余额并调用一组 RPC 方法。

连接 ​

js
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 时以退避策略重连——Web 应用会以指数增长的延迟重试。

事件 ​

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
txGateway 已将一笔交易转发给节点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_anomalySentinel 将一笔已提交的交易判定为异常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)检查一次。

余额订阅 ​

js
ws.send(JSON.stringify({ type: 'subscribe_balance', address: 'neuro:<15 hex>.human' }))

Gateway 会立即回复一次,之后每个新区块后再回复一次:

json
{ "type": "balance", "address": "neuro:…", "balance": 50000000, "balance_human": "50", "nonce": 0 }

socket 关闭时订阅即结束。

通过 socket 调用 RPC ​

js
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
名称与 NFThuman_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
AIget_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

写方法需要在 params 中携带与其 REST 端点相同的签名字段(signature、public_key、nonce)。

限制 ​

限制默认值变量超出时
消息大小64 KBWS_MAX_MSG_BYTES{"type":"error","error":"message too large"}
每个连接的余额订阅数50WS_MAX_SUBS_PER_CLIENTsubscription limit exceeded
每个连接每秒的 RPC 调用数30WS_RPC_MAX_RPSrpc rate limit exceeded
失效连接清理每 30 sWS_STALE_CHECK_MS—

Python ​

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())