Skip to content

WebSocket ​

The gateway serves a WebSocket at /ws on the same host and port as its REST API:

ws://localhost:3000/ws

No authentication. The gateway pushes chain and AI events to every connected client; a client can also subscribe to balances and call a set of RPC methods over the same socket.

Connecting ​

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
  }
}

Every server message is JSON with a type. Events put their payload in data; balance, rpc_reply and error carry their fields at the top level.

Reconnect on close with a back-off — the web app retries with an exponentially growing delay.

Events ​

The gateway polls the node every POLL_NODE_INTERVAL_MS (default 2 000 ms) and turns what it sees into events.

typeWhendata fields
initRight after connectingheight, tps, finality_ms, shard_count, validator_count, blocks, txs, total_blocks, total_txs
metricsEvery polltps, height, finality_ms
new_blockA new height is seenThe block as returned by GET /api/v1/blocks/:height
validator_updateEvery 10 blocksnodes, total_staked, height
txThe gateway forwarded a transaction to the nodehash, from, to, value, gas, gas_price, shard, timestamp, block
faucetFaucet credited an addressaddress, amount, tx_hash
tx_heldA transfer was held by the Sentinel policytx_hash, to, value_human
tx_releasedA held transfer was releasedtx_hash, to, value_human
tx_cancelledA held transfer was cancelledtx_hash, to, value_human
tx_anomalySentinel scored a submitted transaction as anomaloustx_hash, score, category
oracle_decisionAn AI decision was loggedmodel, kind, subject, decision, confidence, timestamp
model_voting_updateAI models are waiting for validator confirmationsmodels, height
contract_alertUnusual call volume on a contract, or a low-score contract starts being calledaddress, alert, severity, call_count, delta, timestamp, model

tx is a submission notice

The tx event fires when the gateway hands the transaction to the node, before it is in a block — its status field is not authoritative. Track finality with new_block, a balance subscription, or GET /api/v1/transactions/:hash.

Contract alerts are checked every SENTINEL_CHECK_INTERVAL_MS (default 30 000 ms).

Balance subscription ​

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

The gateway answers at once and again after every new block:

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

Subscriptions end when the socket closes.

RPC over the socket ​

js
ws.send(JSON.stringify({ type: 'rpc', id: 1, method: 'get_account', params: { address: 'neuro:…' } }))
// → { "type": "rpc_reply", "id": 1, "result": { … }, "error": null }

The methods mirror REST endpoints and return the same data:

GroupMethods
Chainget_status, get_blocks, get_block, get_block_txs, get_txs, search_tx, get_account
Validatorsget_validator, get_validators
Names and NFTshuman_name_price, register_human, get_my_nfts, get_nft, transfer_nft
Governanceget_governance_params, get_proposals, get_proposal, create_proposal, cast_vote
Vaultsget_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
Contractsget_contracts, get_contract, get_contract_events, deploy_contract, call_contract, update_contract_score, get_certificates, get_certificate, get_contract_certificate, certify_contract
Test networksfaucet

Write methods need the same signed fields as their REST endpoint (signature, public_key, nonce) inside params.

Limits ​

LimitDefaultVariableOn excess
Message size64 KBWS_MAX_MSG_BYTES{"type":"error","error":"message too large"}
Balance subscriptions per connection50WS_MAX_SUBS_PER_CLIENTsubscription limit exceeded
RPC calls per second per connection30WS_RPC_MAX_RPSrpc rate limit exceeded
Dead-connection sweepevery 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())