deribit_fix/client/
fix_client.rs

1//! Deribit FIX client implementation
2
3use crate::{
4    config::DeribitFixConfig,
5    connection::Connection,
6    error::{DeribitFixError, Result},
7    session::Session,
8};
9use deribit_base::prelude::{NewOrderRequest, Position};
10use std::sync::Arc;
11use tokio::sync::Mutex;
12use tracing::info;
13
14/// Main Deribit FIX client
15pub struct DeribitFixClient {
16    /// Client configuration
17    pub config: DeribitFixConfig,
18    connection: Option<Arc<Mutex<Connection>>>,
19    session: Option<Arc<Mutex<Session>>>,
20}
21
22impl DeribitFixClient {
23    /// Create a new Deribit FIX client
24    pub async fn new(config: DeribitFixConfig) -> Result<Self> {
25        config.validate()?;
26
27        Ok(Self {
28            config,
29            connection: None,
30            session: None,
31        })
32    }
33
34    /// Connect to the Deribit FIX server
35    pub async fn connect(&mut self) -> Result<()> {
36        info!(
37            "Connecting to Deribit FIX server at {}",
38            self.config.connection_url()
39        );
40
41        // Create connection
42        let connection = Connection::new(&self.config).await?;
43        self.connection = Some(Arc::new(Mutex::new(connection)));
44
45        // Create session
46        let session = Session::new(&self.config, self.connection.as_ref().unwrap().clone())?;
47        self.session = Some(Arc::new(Mutex::new(session)));
48
49        // Perform logon
50        self.logon().await?;
51
52        info!("Successfully connected to Deribit FIX server");
53        Ok(())
54    }
55
56    /// Disconnect from the server
57    pub async fn disconnect(&mut self) -> Result<()> {
58        info!("Disconnecting from Deribit FIX server");
59
60        if let Some(session) = &self.session {
61            let mut session_guard = session.lock().await;
62            session_guard.logout().await?;
63        }
64
65        if let Some(connection) = &self.connection {
66            let mut connection_guard = connection.lock().await;
67            connection_guard.close().await?;
68        }
69
70        self.connection = None;
71        self.session = None;
72
73        info!("Successfully disconnected from Deribit FIX server");
74        Ok(())
75    }
76
77    /// Check if the client is connected
78    pub fn is_connected(&self) -> bool {
79        self.connection.is_some() && self.session.is_some()
80    }
81
82    /// Get the current session state
83    pub fn get_session_state(&self) -> Option<crate::session::SessionState> {
84        if let Some(session) = &self.session {
85            // Try to get the session state without blocking
86            if let Ok(session_guard) = session.try_lock() {
87                Some(session_guard.get_state())
88            } else {
89                // Session is locked, return None to indicate we can't check right now
90                None
91            }
92        } else {
93            None
94        }
95    }
96
97    /// Perform FIX logon
98    async fn logon(&self) -> Result<()> {
99        if let Some(session) = &self.session {
100            let mut session_guard = session.lock().await;
101            session_guard.logon().await?;
102        }
103        Ok(())
104    }
105
106    /// Send a new order
107    pub async fn send_order(&self, order: NewOrderRequest) -> Result<String> {
108        if let Some(session) = &self.session {
109            let mut session_guard = session.lock().await;
110            session_guard.send_new_order(order)
111        } else {
112            Err(DeribitFixError::Session("Not connected".to_string()))
113        }
114    }
115
116    /// Cancel an order
117    pub async fn cancel_order(&self, order_id: String) -> Result<()> {
118        if let Some(session) = &self.session {
119            let mut session_guard = session.lock().await;
120            session_guard.cancel_order(order_id)
121        } else {
122            Err(DeribitFixError::Session("Not connected".to_string()))
123        }
124    }
125
126    /// Subscribe to market data
127    pub async fn subscribe_market_data(&self, symbol: String) -> Result<()> {
128        if let Some(session) = &self.session {
129            let mut session_guard = session.lock().await;
130            session_guard.subscribe_market_data(symbol)
131        } else {
132            Err(DeribitFixError::Session("Not connected".to_string()))
133        }
134    }
135
136    /// Get account positions
137    pub async fn get_positions(&self) -> Result<Vec<Position>> {
138        if let Some(session) = &self.session {
139            let mut session_guard = session.lock().await;
140            session_guard.request_positions()
141        } else {
142            Err(DeribitFixError::Session("Not connected".to_string()))
143        }
144    }
145
146    /// Receive and process a message from the server
147    pub async fn receive_message(&self) -> Result<Option<crate::model::message::FixMessage>> {
148        if let Some(session) = &self.session {
149            let mut session_guard = session.lock().await;
150            session_guard.receive_and_process_message().await
151        } else {
152            Err(DeribitFixError::Session("Not connected".to_string()))
153        }
154    }
155}