WebSocket API
I think real-time data is essential for building responsive dApps, so we invested heavily in the WebSocket layer. The Citrate WebSocket API provides a persistent, bidirectional connection for receiving real-time updates from the network. It supports standard Ethereum subscription methods as well as custom Citrate subscriptions for GhostDAG and model registry events.
Connection
Connect to the WebSocket server at:
ws://localhost:8546
For production, use wss:// with TLS. The server supports the JSON-RPC 2.0 protocol over WebSocket frames.
Connection Parameters
| Parameter | Value | Description |
|---|---|---|
| Ping interval | 30s | Server sends a ping frame every 30 seconds |
| Max message size | 10MB | Maximum size of a single WebSocket message |
| Idle timeout | 60s | Connection is closed after 60 seconds of no activity |
| Max subscriptions | 100 | Maximum concurrent subscriptions per connection |
Standard Ethereum Subscriptions
eth_subscribe
Creates a new subscription for the specified event type. Returns a subscription ID that is included in all subsequent notifications.
newHeads
Subscribe to new block headers as they are added to the chain.
// Request
{
"jsonrpc": "2.0",
"method": "eth_subscribe",
"params": ["newHeads"],
"id": 1
}
// Response
{ "jsonrpc": "2.0", "result": "0xsub1abc...", "id": 1 }
// Notification
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0xsub1abc...",
"result": {
"number": "0x1b4",
"hash": "0xblock...",
"parentHash": "0xparent...",
"timestamp": "0x65e8a000",
"gasUsed": "0x5208",
"miner": "0xminer..."
}
}
}
newPendingTransactions
Subscribe to the hashes of new pending transactions as they enter the mempool.
// Request
{
"jsonrpc": "2.0",
"method": "eth_subscribe",
"params": ["newPendingTransactions"],
"id": 2
}
// Notification
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0xsub2def...",
"result": "0xtxhash..."
}
}
logs
Subscribe to log entries that match a filter. Useful for monitoring smart contract events.
// Request
{
"jsonrpc": "2.0",
"method": "eth_subscribe",
"params": [
"logs",
{
"address": "0xContractAddress",
"topics": ["0xEventSignatureHash"]
}
],
"id": 3
}
// Notification
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0xsub3ghi...",
"result": {
"address": "0xContractAddress",
"topics": ["0xEventSignatureHash"],
"data": "0x...",
"blockNumber": "0x1b4",
"transactionHash": "0xtx...",
"logIndex": "0x0"
}
}
}
Custom Citrate Subscriptions
citrate_subscribe
Creates a subscription for Citrate-specific events. These subscriptions provide real-time visibility into the GhostDAG state, model registry, and finality checkpoints.
dagTips
Subscribe to changes in the GhostDAG tip set. A notification is emitted whenever the set of unconfirmed tips changes.
// Request
{
"jsonrpc": "2.0",
"method": "citrate_subscribe",
"params": ["dagTips"],
"id": 4
}
// Notification
{
"jsonrpc": "2.0",
"method": "citrate_subscription",
"params": {
"subscription": "0xsub4jkl...",
"result": {
"tips": ["0xblock1...", "0xblock2...", "0xblock3..."],
"tipCount": 3,
"blueScore": 14201,
"timestamp": 1709145900
}
}
}
modelRegistry
Subscribe to model registry events including new deployments, updates, and deactivations.
// Request
{
"jsonrpc": "2.0",
"method": "citrate_subscribe",
"params": ["modelRegistry", { "events": ["deploy", "update", "deactivate"] }],
"id": 5
}
// Notification
{
"jsonrpc": "2.0",
"method": "citrate_subscription",
"params": {
"subscription": "0xsub5mno...",
"result": {
"event": "deploy",
"modelId": "0xmodel...",
"name": "sentiment-v2",
"owner": "0xOwner...",
"blockNumber": "0x1b5",
"timestamp": 1709145950
}
}
}
finalityCheckpoints
Subscribe to finality checkpoint events. Notifications are emitted when a new block achieves finality in the GhostDAG.
// Request
{
"jsonrpc": "2.0",
"method": "citrate_subscribe",
"params": ["finalityCheckpoints"],
"id": 6
}
// Notification
{
"jsonrpc": "2.0",
"method": "citrate_subscription",
"params": {
"subscription": "0xsub6pqr...",
"result": {
"blockHash": "0xfinalized...",
"blockNumber": "0x1b0",
"blueScore": 14198,
"confirmations": 12,
"timestamp": 1709145850
}
}
}
Unsubscribing
To cancel a subscription, send an unsubscribe request with the subscription ID.
eth_unsubscribe
// Request
{ "jsonrpc": "2.0", "method": "eth_unsubscribe", "params": ["0xsub1abc..."], "id": 7 }
// Response
{ "jsonrpc": "2.0", "result": true, "id": 7 }
citrate_unsubscribe
// Request
{ "jsonrpc": "2.0", "method": "citrate_unsubscribe", "params": ["0xsub4jkl..."], "id": 8 }
// Response
{ "jsonrpc": "2.0", "result": true, "id": 8 }
Returns true if the subscription was successfully cancelled, false if the subscription ID was not found.
Error Handling
WebSocket-specific errors are returned as JSON-RPC error responses:
| Code | Message | Description |
|---|---|---|
| -32600 | Invalid Request | Malformed JSON-RPC message |
| -32601 | Method not found | Unknown subscription method |
| -32602 | Invalid params | Invalid subscription parameters |
| -32603 | Internal error | Server-side subscription error |
| -32000 | Subscription limit reached | Maximum of 100 concurrent subscriptions exceeded |
If the server detects that a client is not responding to ping frames, the connection is terminated after the 60-second idle timeout.