RTDS (Real-Time Data Streaming)
RTDS delivers streaming price updates for assets such as BTC, ETH, SOL, and more. You specify which assets to track by symbol, and the server pushes new prices as they arrive from upstream data sources. No authentication is needed.
Endpoint
Section titled “Endpoint”wss://api.openfish.fun/ws/rtdsProtocol
Section titled “Protocol”Subscribe
Section titled “Subscribe”Once connected, send a JSON message listing the asset symbols you want to receive:
{ "channel": "price", "assets": ["BTC", "ETH", "SOL"]}| Field | Type | Description |
|---|---|---|
channel | string | Must be "price" for price subscriptions |
assets | string[] | List of asset symbols (case-insensitive) |
Subscription Acknowledgment
Section titled “Subscription Acknowledgment”The server replies with a confirmation that includes every symbol you are currently tracking:
{ "type": "subscribed", "assets": ["BTC", "ETH", "SOL"]}Adding More Assets
Section titled “Adding More Assets”You can expand your subscription at any time by sending another message. New symbols are merged into the existing set rather than replacing it:
{ "channel": "price", "assets": ["XRP", "DOGE"]}Response:
{ "type": "subscribed", "assets": ["BTC", "ETH", "SOL", "XRP", "DOGE"]}Price Tick Format
Section titled “Price Tick Format”After subscribing, price updates arrive as they are ingested from external feeds:
{ "asset": "BTC", "price": "67123.45", "source": "binance", "timestamp": 1700000000}| Field | Type | Description |
|---|---|---|
asset | string | Asset symbol (uppercase) |
price | string | Current price as a string for precision |
source | string | Data source identifier (e.g., "binance") |
timestamp | number | Unix timestamp in seconds |
Heartbeat
Section titled “Heartbeat”WebSocket PING frames are sent by the server every 10 seconds. Reply with PONG frames to hold the connection open. Most WebSocket libraries handle this transparently.
Rust SDK Example
Section titled “Rust SDK Example”use openfish_client_sdk::ws::RtdsSocket;use futures_util::StreamExt;
#[tokio::main]async fn main() -> anyhow::Result<()> { let mut ws = RtdsSocket::connect("wss://api.openfish.fun/ws/rtds").await?;
// Subscribe to BTC and ETH price feeds ws.subscribe_assets(&["BTC", "ETH"]).await?;
while let Some(tick) = ws.next().await { println!( "[{}] {} = {} (source: {})", tick.timestamp, tick.asset, tick.price, tick.source ); }
Ok(())}Advanced: Building a Price Cache
Section titled “Advanced: Building a Price Cache”Trading bots that need instant access to the most recent price can maintain an in-memory map fed by the RTDS stream:
use openfish_client_sdk::ws::RtdsSocket;use std::collections::HashMap;use std::sync::{Arc, RwLock};use futures_util::StreamExt;
#[tokio::main]async fn main() -> anyhow::Result<()> { let prices: Arc<RwLock<HashMap<String, f64>>> = Arc::new(RwLock::new(HashMap::new())); let prices_clone = prices.clone();
tokio::spawn(async move { let mut ws = RtdsSocket::connect("wss://api.openfish.fun/ws/rtds") .await .expect("Failed to connect"); ws.subscribe_assets(&["BTC", "ETH", "SOL"]).await.expect("subscribe failed");
while let Some(tick) = ws.next().await { if let Ok(val) = tick.price.parse::<f64>() { prices_clone.write().unwrap().insert(tick.asset.clone(), val); } } });
// Elsewhere in your application: // let btc_price = prices.read().unwrap().get("BTC").copied();
Ok(())}Supported Assets
Section titled “Supported Assets”Symbols are normalized to uppercase on the server side. Commonly available symbols include:
| Symbol | Asset |
|---|---|
BTC | Bitcoin |
ETH | Ethereum |
SOL | Solana |
XRP | XRP |
The full set of available symbols depends on which upstream data feeds are active. Subscribing to an unrecognized symbol does not produce an error — the server silently includes it in your subscription set and will begin delivering ticks if the feed becomes available later.
Next Steps
Section titled “Next Steps”- Sports Channel — Live game scores.
- Market Channel — Order book events.
- WebSocket Overview — All available channels.