ig_client/application/services/
order_service.rs

1use crate::application::services::OrderService;
2use crate::{
3    application::models::order::{
4        ClosePositionRequest, ClosePositionResponse, CreateOrderRequest, CreateOrderResponse,
5        OrderConfirmation, UpdatePositionRequest,
6    },
7    config::Config,
8    error::AppError,
9    session::interface::IgSession,
10    transport::http_client::IgHttpClient,
11};
12use async_trait::async_trait;
13use reqwest::Method;
14use std::sync::Arc;
15use tracing::{debug, info};
16
17/// Implementation of the order service
18pub struct OrderServiceImpl<T: IgHttpClient> {
19    config: Arc<Config>,
20    client: Arc<T>,
21}
22
23impl<T: IgHttpClient> OrderServiceImpl<T> {
24    /// Creates a new instance of the order service
25    pub fn new(config: Arc<Config>, client: Arc<T>) -> Self {
26        Self { config, client }
27    }
28
29    /// Gets the current configuration
30    ///
31    /// # Returns
32    /// * The current configuration as an `Arc<Config>`
33    pub fn get_config(&self) -> Arc<Config> {
34        self.config.clone()
35    }
36
37    /// Sets a new configuration
38    ///
39    /// # Arguments
40    /// * `config` - The new configuration to use
41    pub fn set_config(&mut self, config: Arc<Config>) {
42        self.config = config;
43    }
44}
45
46#[async_trait]
47impl<T: IgHttpClient + 'static> OrderService for OrderServiceImpl<T> {
48    async fn create_order(
49        &self,
50        session: &IgSession,
51        order: &CreateOrderRequest,
52    ) -> Result<CreateOrderResponse, AppError> {
53        info!("Creating order for: {}", order.epic);
54
55        let result = self
56            .client
57            .request::<CreateOrderRequest, CreateOrderResponse>(
58                Method::POST,
59                "positions/otc",
60                session,
61                Some(order),
62                "2",
63            )
64            .await?;
65
66        debug!("Order created with reference: {}", result.deal_reference);
67        Ok(result)
68    }
69
70    async fn get_order_confirmation(
71        &self,
72        session: &IgSession,
73        deal_reference: &str,
74    ) -> Result<OrderConfirmation, AppError> {
75        let path = format!("confirms/{}", deal_reference);
76        info!("Getting confirmation for order: {}", deal_reference);
77
78        let result = self
79            .client
80            .request::<(), OrderConfirmation>(Method::GET, &path, session, None, "1")
81            .await?;
82
83        debug!("Confirmation obtained for order: {}", deal_reference);
84        Ok(result)
85    }
86
87    async fn update_position(
88        &self,
89        session: &IgSession,
90        deal_id: &str,
91        update: &UpdatePositionRequest,
92    ) -> Result<(), AppError> {
93        let path = format!("positions/otc/{}", deal_id);
94        info!("Updating position: {}", deal_id);
95
96        self.client
97            .request::<UpdatePositionRequest, ()>(Method::PUT, &path, session, Some(update), "2")
98            .await?;
99
100        debug!("Position updated: {}", deal_id);
101        Ok(())
102    }
103
104    async fn close_position(
105        &self,
106        session: &IgSession,
107        close_request: &ClosePositionRequest,
108    ) -> Result<ClosePositionResponse, AppError> {
109        info!("Closing position: {}", close_request.deal_id);
110
111        let result = self
112            .client
113            .request::<ClosePositionRequest, ClosePositionResponse>(
114                Method::POST,
115                "positions/otc",
116                session,
117                Some(close_request),
118                "1",
119            )
120            .await?;
121
122        debug!("Position closed with reference: {}", result.deal_reference);
123        Ok(result)
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    use super::*;
130    use crate::config::Config;
131    use crate::transport::http_client::IgHttpClientImpl;
132    use std::sync::Arc;
133
134    #[test]
135    fn test_get_and_set_config() {
136        let config = Arc::new(Config::new());
137        let client = Arc::new(IgHttpClientImpl::new(config.clone()));
138        let mut service = OrderServiceImpl::new(config.clone(), client.clone());
139
140        let cfg1 = service.get_config();
141        assert!(Arc::ptr_eq(&cfg1, &config));
142
143        let new_cfg = Arc::new(Config::default());
144        service.set_config(new_cfg.clone());
145        assert!(Arc::ptr_eq(&service.get_config(), &new_cfg));
146    }
147}