ig_client/application/services/
order_service.rs1use 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
17pub struct OrderServiceImpl<T: IgHttpClient> {
19 config: Arc<Config>,
20 client: Arc<T>,
21}
22
23impl<T: IgHttpClient> OrderServiceImpl<T> {
24 pub fn new(config: Arc<Config>, client: Arc<T>) -> Self {
26 Self { config, client }
27 }
28
29 pub fn get_config(&self) -> Arc<Config> {
34 self.config.clone()
35 }
36
37 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}