WebSocket

Real-time subscriptions via WebSocket for accounts, transactions, logs, slots, and programs. Subscribe to on-chain events and receive push notifications as they happen.

Connection

Connect to wss://api.falconq.xyz/v1/ws with your API key as a query parameter. Authentication is validated during the WebSocket upgrade handshake.

const WebSocket = require('ws')

const ws = new WebSocket(
  'wss://api.falconq.xyz/v1/ws?api-key=fq_rpc_live_YOUR_KEY'
)

ws.on('open', () => {
  console.log('Connected to FalconQ WebSocket')
})

ws.on('message', (data) => {
  const response = JSON.parse(data.toString())
  console.log('Message:', response)
})

ws.on('error', (err) => {
  console.error('WebSocket error:', err.message)
})

ws.on('close', (code, reason) => {
  console.log('Disconnected:', code, reason.toString())
})

Multiple subscriptions may be active simultaneously on a single connection. If commitment is unspecified, the default is finalized.

WebSocket streaming requires an All Access subscription, which allows up to 3 concurrent connections per account. Messages are capped at 10 MB, and the server pings every 30 seconds — unresponsive connections are closed, so reply to pings (most libraries do this automatically).

Subscription Methods

MethodDescription
accountSubscribeTrack balance and data changes for a specific account
logsSubscribeSubscribe to program log output for transactions
programSubscribeTrack all account changes for a program
signatureSubscribeMonitor a specific transaction signature for confirmation
slotSubscribeReceive notifications for each new slot
blockSubscribeSubscribe to new block notifications
rootSubscribeTrack root slot updates (finalized slots)
slotsUpdatesSubscribeReceive detailed slot update events
voteSubscribeSubscribe to vote transaction updates

accountSubscribe

Subscribe to an account to receive notifications when the lamports or data for a given account public key changes.

Parameters: account address (string), optional config with encoding (base58, base64, base64+zstd, jsonParsed) and commitment.

ws.on('open', () => {
  ws.send(JSON.stringify({
    jsonrpc: '2.0',
    id: 1,
    method: 'accountSubscribe',
    params: [
      'vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg',
      { encoding: 'jsonParsed', commitment: 'confirmed' }
    ]
  }))
})

ws.on('message', (data) => {
  const msg = JSON.parse(data.toString())

  if (msg.result && typeof msg.result === 'number') {
    console.log('Subscription ID:', msg.result)
  }

  if (msg.method === 'accountNotification') {
    const { value } = msg.params.result
    console.log('Account updated:', {
      lamports: value.lamports,
      owner: value.owner,
      data: value.data,
    })
  }
})
Subscription Response
{
  "jsonrpc": "2.0",
  "result": 23784,
  "id": 1
}
Notification
{
  "jsonrpc": "2.0",
  "method": "accountNotification",
  "params": {
    "result": {
      "context": { "slot": 5199307 },
      "value": {
        "data": { "program": "system", "parsed": { ... } },
        "executable": false,
        "lamports": 33594,
        "owner": "11111111111111111111111111111111",
        "rentEpoch": 635,
        "space": 80
      }
    },
    "subscription": 23784
  }
}

logsSubscribe

Subscribe to transaction logging. Filter by all transactions, all with votes, or a specific address.

Filters: "all" (all non-vote txns), "allWithVotes", or { mentions: ["<pubkey>"] } (single address only).

// Subscribe to logs for a specific program
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  id: 2,
  method: 'logsSubscribe',
  params: [
    { mentions: ['TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'] },
    { commitment: 'confirmed' }
  ]
}))

// Subscribe to all non-vote transaction logs
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  id: 3,
  method: 'logsSubscribe',
  params: [
    'all',
    { commitment: 'confirmed' }
  ]
}))

ws.on('message', (data) => {
  const msg = JSON.parse(data.toString())
  if (msg.method === 'logsNotification') {
    const { signature, err, logs } = msg.params.result.value
    console.log('Tx:', signature, err ? 'FAILED' : 'OK')
    console.log('Logs:', logs)
  }
})
Notification
{
  "jsonrpc": "2.0",
  "method": "logsNotification",
  "params": {
    "result": {
      "context": { "slot": 5208469 },
      "value": {
        "signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXF...",
        "err": null,
        "logs": [
          "Program 11111111111111111111111111111111 invoke [1]",
          "Program 11111111111111111111111111111111 success"
        ]
      }
    },
    "subscription": 24040
  }
}

programSubscribe

Subscribe to all accounts owned by a specific program. Useful for monitoring protocol state changes.

// Subscribe to all Token Program account changes
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  id: 4,
  method: 'programSubscribe',
  params: [
    'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
    {
      encoding: 'jsonParsed',
      commitment: 'confirmed',
      filters: [{ dataSize: 165 }]
    }
  ]
}))

ws.on('message', (data) => {
  const msg = JSON.parse(data.toString())
  if (msg.method === 'programNotification') {
    const { pubkey, account } = msg.params.result.value
    console.log('Account:', pubkey, 'Lamports:', account.lamports)
  }
})

signatureSubscribe

Subscribe to receive a notification when a transaction with the given signature reaches the specified commitment level. The subscription is automatically cancelled after notification.

// Wait for a transaction to be confirmed
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  id: 5,
  method: 'signatureSubscribe',
  params: [
    '5Pj5fCupXLUePYn18JkY8SrRaWFiUctuDTRwvUy2ML9y...',
    { commitment: 'confirmed' }
  ]
}))

ws.on('message', (data) => {
  const msg = JSON.parse(data.toString())
  if (msg.method === 'signatureNotification') {
    const { err } = msg.params.result.value
    console.log('Transaction', err ? 'FAILED' : 'CONFIRMED')
  }
})

slotSubscribe

Subscribe to receive notifications when a new slot is processed by the validator.

ws.send(JSON.stringify({
  jsonrpc: '2.0',
  id: 6,
  method: 'slotSubscribe'
}))

ws.on('message', (data) => {
  const msg = JSON.parse(data.toString())
  if (msg.method === 'slotNotification') {
    const { slot, parent, root } = msg.params.result
    console.log('Slot:', slot, 'Parent:', parent, 'Root:', root)
  }
})

blockSubscribe

Subscribe to receive notifications when a new block is confirmed. Can filter by program or receive all blocks.

// Subscribe to all blocks
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  id: 7,
  method: 'blockSubscribe',
  params: [
    'all',
    {
      commitment: 'confirmed',
      encoding: 'jsonParsed',
      transactionDetails: 'signatures',
      maxSupportedTransactionVersion: 0
    }
  ]
}))

Unsubscribing

Every subscription returns a numeric subscription ID. Use the corresponding unsubscribe method to stop receiving updates.

// Unsubscribe from account updates (subscription ID from response)
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  id: 99,
  method: 'accountUnsubscribe',
  params: [23784]
}))

// Unsubscribe from logs
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  id: 100,
  method: 'logsUnsubscribe',
  params: [24040]
}))

// Unsubscribe from program updates
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  id: 101,
  method: 'programUnsubscribe',
  params: [subscriptionId]
}))

// Unsubscribe from slot updates
ws.send(JSON.stringify({
  jsonrpc: '2.0',
  id: 102,
  method: 'slotUnsubscribe',
  params: [subscriptionId]
}))

Reconnection Best Practices

WebSocket connections can drop due to network issues. Implement exponential backoff reconnection:

const WebSocket = require('ws')

let reconnectAttempts = 0
const MAX_RECONNECT_DELAY = 30000

function connect() {
  const ws = new WebSocket(
    'wss://api.falconq.xyz/v1/ws?api-key=fq_rpc_live_YOUR_KEY'
  )

  ws.on('open', () => {
    reconnectAttempts = 0
    console.log('Connected')

    ws.send(JSON.stringify({
      jsonrpc: '2.0', id: 1,
      method: 'accountSubscribe',
      params: ['YOUR_ADDRESS', { encoding: 'jsonParsed', commitment: 'confirmed' }]
    }))
  })

  ws.on('close', () => {
    const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), MAX_RECONNECT_DELAY)
    reconnectAttempts++
    console.log('Reconnecting in', delay, 'ms (attempt', reconnectAttempts + ')')
    setTimeout(connect, delay)
  })

  ws.on('error', (err) => {
    console.error('Error:', err.message)
    ws.close()
  })

  ws.on('message', (data) => {
    const msg = JSON.parse(data.toString())
    if (msg.method?.endsWith('Notification')) {
      console.log('Update:', msg.params.result.value)
    }
  })
}

connect()