fmp_rust_sdk/
websocket.rs1mod connection;
15mod protocol;
16mod standard;
17mod streams;
18mod types;
19
20pub use types::{
21 CloseInfo, ControlEvent, LoginConfirmation, MarketUpdate, QuoteUpdate, TradeUpdate,
22 WebSocketCluster, WebSocketConfig, WebSocketError, WebSocketEvent,
23};
24
25use crate::plan::Subscription;
26use connection::{Connection, Socket};
27use protocol::{TickerCommand, TickerData, normalize_symbols, validate_connection};
28use url::Url;
29
30pub use standard::StandardWebSocketClient;
31pub use streams::{
32 AuthenticationStatus, Heartbeat, MarketStream, StreamConfig, StreamEntitlements, StreamQuote,
33};
34
35#[derive(Debug)]
39pub struct WebSocketClient {
40 connection: Connection,
41 cluster: WebSocketCluster,
42}
43
44impl WebSocketClient {
45 pub async fn connect(
47 api_key: &str,
48 subscription: &Subscription,
49 cluster: WebSocketCluster,
50 config: WebSocketConfig,
51 ) -> Result<Self, WebSocketError> {
52 let endpoint =
53 Url::parse(cluster.endpoint()).map_err(|error| WebSocketError::Configuration {
54 reason: format!("invalid documented cluster URL: {error}"),
55 })?;
56 Self::connect_to(api_key, subscription, cluster, endpoint, config).await
57 }
58
59 pub async fn connect_to(
61 api_key: &str,
62 subscription: &Subscription,
63 cluster: WebSocketCluster,
64 endpoint: Url,
65 config: WebSocketConfig,
66 ) -> Result<Self, WebSocketError> {
67 validate_connection(api_key, subscription, cluster, &endpoint)?;
68 Ok(Self {
69 connection: Connection::connect(api_key, endpoint, config).await?,
70 cluster,
71 })
72 }
73
74 pub const fn cluster(&self) -> WebSocketCluster {
76 self.cluster
77 }
78
79 pub async fn subscribe(&mut self, symbols: &[&str]) -> Result<(), WebSocketError> {
81 let command = TickerCommand {
82 event: "subscribe",
83 data: TickerData {
84 ticker: normalize_symbols(symbols)?,
85 },
86 };
87 let json = serde_json::to_string(&command).map_err(|error| {
88 self.connection
89 .protocol_error(&error.to_string(), "subscribe serialization")
90 })?;
91 self.connection.send_text(json, "subscribe").await
92 }
93
94 pub async fn unsubscribe(&mut self, symbols: &[&str]) -> Result<(), WebSocketError> {
96 let command = TickerCommand {
97 event: "unsubscribe",
98 data: TickerData {
99 ticker: normalize_symbols(symbols)?,
100 },
101 };
102 let json = serde_json::to_string(&command).map_err(|error| {
103 self.connection
104 .protocol_error(&error.to_string(), "unsubscribe serialization")
105 })?;
106 self.connection.send_text(json, "unsubscribe").await
107 }
108
109 pub async fn next_event(&mut self) -> Result<WebSocketEvent, WebSocketError> {
111 self.connection.next_event().await
112 }
113
114 pub async fn close(self) -> Result<(), WebSocketError> {
116 self.connection.close().await
117 }
118}