ig_client/application/services/
order_service.rs1use crate::application::models::account::WorkingOrders;
2use crate::application::models::order::{
3 ClosePositionRequest, ClosePositionResponse, CreateOrderRequest, CreateOrderResponse,
4 OrderConfirmation, UpdatePositionRequest, UpdatePositionResponse,
5};
6use crate::application::models::working_order::{
7 CreateWorkingOrderRequest, CreateWorkingOrderResponse,
8};
9use crate::application::services::interfaces::order::OrderService;
10use crate::config::Config;
11use crate::error::AppError;
12use crate::session::interface::IgSession;
13use crate::transport::http_client::IgHttpClient;
14use async_trait::async_trait;
15use reqwest::Method;
16use std::sync::Arc;
17use tracing::{debug, info};
18
19pub struct OrderServiceImpl<T: IgHttpClient> {
21 config: Arc<Config>,
22 client: Arc<T>,
23}
24
25impl<T: IgHttpClient> OrderServiceImpl<T> {
26 pub fn new(config: Arc<Config>, client: Arc<T>) -> Self {
28 Self { config, client }
29 }
30
31 pub fn get_config(&self) -> Arc<Config> {
36 self.config.clone()
37 }
38
39 pub fn set_config(&mut self, config: Arc<Config>) {
44 self.config = config;
45 }
46}
47
48#[async_trait]
49impl<T: IgHttpClient + 'static> OrderService for OrderServiceImpl<T> {
50 async fn create_order(
51 &self,
52 session: &IgSession,
53 order: &CreateOrderRequest,
54 ) -> Result<CreateOrderResponse, AppError> {
55 info!("Creating order for: {}", order.epic);
56
57 let result = self
58 .client
59 .request::<CreateOrderRequest, CreateOrderResponse>(
60 Method::POST,
61 "positions/otc",
62 session,
63 Some(order),
64 "2",
65 )
66 .await?;
67
68 debug!("Order created with reference: {}", result.deal_reference);
69 Ok(result)
70 }
71
72 async fn get_order_confirmation(
73 &self,
74 session: &IgSession,
75 deal_reference: &str,
76 ) -> Result<OrderConfirmation, AppError> {
77 let path = format!("confirms/{}", deal_reference);
78 info!("Getting confirmation for order: {}", deal_reference);
79
80 let result = self
81 .client
82 .request::<(), OrderConfirmation>(Method::GET, &path, session, None, "1")
83 .await?;
84
85 debug!("Confirmation obtained for order: {}", deal_reference);
86 Ok(result)
87 }
88
89 async fn update_position(
90 &self,
91 session: &IgSession,
92 deal_id: &str,
93 update: &UpdatePositionRequest,
94 ) -> Result<UpdatePositionResponse, AppError> {
95 let path = format!("positions/otc/{}", deal_id);
96 info!("Updating position: {}", deal_id);
97
98 let result = self
99 .client
100 .request::<UpdatePositionRequest, UpdatePositionResponse>(
101 Method::PUT,
102 &path,
103 session,
104 Some(update),
105 "2",
106 )
107 .await?;
108
109 debug!(
110 "Position updated: {} with deal reference: {}",
111 deal_id, result.deal_reference
112 );
113 Ok(result)
114 }
115
116 async fn close_position(
117 &self,
118 session: &IgSession,
119 close_request: &ClosePositionRequest,
120 ) -> Result<ClosePositionResponse, AppError> {
121 info!("Closing position: {}", close_request.deal_id);
122
123 let result = self
124 .client
125 .request::<ClosePositionRequest, ClosePositionResponse>(
126 Method::POST,
127 "positions/otc",
128 session,
129 Some(close_request),
130 "1",
131 )
132 .await?;
133
134 debug!("Position closed with reference: {}", result.deal_reference);
135 Ok(result)
136 }
137
138 async fn get_working_orders(&self, session: &IgSession) -> Result<WorkingOrders, AppError> {
139 info!("Getting all working orders");
140
141 let result = self
142 .client
143 .request::<(), WorkingOrders>(Method::GET, "workingorders", session, None, "2")
144 .await?;
145
146 debug!("Retrieved {} working orders", result.working_orders.len());
147 Ok(result)
148 }
149
150 async fn create_working_order(
151 &self,
152 session: &IgSession,
153 order: &CreateWorkingOrderRequest,
154 ) -> Result<CreateWorkingOrderResponse, AppError> {
155 info!("Creating working order for: {}", order.epic);
156
157 let result = self
158 .client
159 .request::<CreateWorkingOrderRequest, CreateWorkingOrderResponse>(
160 Method::POST,
161 "workingorders/otc",
162 session,
163 Some(order),
164 "2",
165 )
166 .await?;
167
168 debug!(
169 "Working order created with reference: {}",
170 result.deal_reference
171 );
172 Ok(result)
173 }
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179 use crate::config::Config;
180 use crate::transport::http_client::IgHttpClientImpl;
181 use std::sync::Arc;
182
183 #[test]
184 fn test_get_and_set_config() {
185 let config = Arc::new(Config::new());
186 let client = Arc::new(IgHttpClientImpl::new(config.clone()));
187 let mut service = OrderServiceImpl::new(config.clone(), client.clone());
188
189 let cfg1 = service.get_config();
190 assert!(Arc::ptr_eq(&cfg1, &config));
191
192 let new_cfg = Arc::new(Config::default());
193 service.set_config(new_cfg.clone());
194 assert!(Arc::ptr_eq(&service.get_config(), &new_cfg));
195 }
196}