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
| Method | Description |
|---|---|
| accountSubscribe | Track balance and data changes for a specific account |
| logsSubscribe | Subscribe to program log output for transactions |
| programSubscribe | Track all account changes for a program |
| signatureSubscribe | Monitor a specific transaction signature for confirmation |
| slotSubscribe | Receive notifications for each new slot |
| blockSubscribe | Subscribe to new block notifications |
| rootSubscribe | Track root slot updates (finalized slots) |
| slotsUpdatesSubscribe | Receive detailed slot update events |
| voteSubscribe | Subscribe 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()