VIZ.cx
← Learn

Stream live operations

10 minintermediate

wss://api.viz.cx/ws/ops emits a message for every operation applied to the chain within ~5 blocks of the tip. This makes it easy to react to live awards, transfers, and other events without polling.

Step 1 — Connect and log all operations

Each message is a JSON-encoded operation record. The op field is a [type, data] tuple, e.g. ['award', { initiator: 'alice', receiver: 'bob', energy: 100 }].

const ws = new WebSocket('wss://api.viz.cx/ws/ops')

ws.onopen = () => console.log('connected')

ws.onmessage = (event) => {
  const item = JSON.parse(event.data)
  // item shape:
  // { trx_id, block, trx_in_block, op_in_trx, virtual_op, timestamp, op }
  const [opType, opData] = item.op
  console.log(item.timestamp, opType, opData)
}

ws.onclose = () => console.log('disconnected')
ws.onerror = (e) => console.error('ws error', e)

Step 2 — Filter by operation type

Most apps care about a subset of op types. Filter by checking opType. Common types: award, transfer, account_create, delegate_vesting_shares.

ws.onmessage = (event) => {
  const item = JSON.parse(event.data)
  const [opType, opData] = item.op

  // Only react to award operations
  if (opType !== 'award') return

  console.log(
    `${opData.initiator} awarded ${opData.receiver}`,
    `energy: ${opData.energy / 100}%`,
    opData.memo ?? ''
  )
}

Step 3 — Add reconnect logic

WebSocket connections drop. A simple 3-second retry on onclose is sufficient for most use cases.

function connect() {
  const ws = new WebSocket('wss://api.viz.cx/ws/ops')

  ws.onmessage = (event) => {
    const item = JSON.parse(event.data)
    const [opType, opData] = item.op
    if (opType === 'award') {
      console.log(`award: ${opData.initiator} → ${opData.receiver}`)
    }
  }

  ws.onclose = () => {
    console.log('reconnecting in 3s…')
    setTimeout(connect, 3000)
  }

  ws.onerror = () => ws.close()

  return ws
}

const ws = connect()