ig_client/application/services/
order_service.rs1use async_trait::async_trait;
2use reqwest::Method;
3use std::sync::Arc;
4use tracing::{debug, info};
5
6use crate::{
7 application::models::order::{
8 ClosePositionRequest, ClosePositionResponse, CreateOrderRequest, CreateOrderResponse,
9 OrderConfirmation, UpdatePositionRequest,
10 },
11 config::Config,
12 error::AppError,
13 session::interface::IgSession,
14 transport::http_client::IgHttpClient,
15};
16
17#[async_trait]
19pub trait OrderService: Send + Sync {
20 async fn create_order(
22 &self,
23 session: &IgSession,
24 order: &CreateOrderRequest,
25 ) -> Result<CreateOrderResponse, AppError>;
26
27 async fn get_order_confirmation(
29 &self,
30 session: &IgSession,
31 deal_reference: &str,
32 ) -> Result<OrderConfirmation, AppError>;
33
34 async fn update_position(
36 &self,
37 session: &IgSession,
38 deal_id: &str,
39 update: &UpdatePositionRequest,
40 ) -> Result<(), AppError>;
41
42 async fn close_position(
44 &self,
45 session: &IgSession,
46 close_request: &ClosePositionRequest,
47 ) -> Result<ClosePositionResponse, AppError>;
48}
49
50pub struct OrderServiceImpl<T: IgHttpClient> {
52 config: Arc<Config>,
53 client: Arc<T>,
54}
55
56impl<T: IgHttpClient> OrderServiceImpl<T> {
57 pub fn new(config: Arc<Config>, client: Arc<T>) -> Self {
59 Self { config, client }
60 }
61
62 pub fn get_config(&self) -> Arc<Config> {
67 self.config.clone()
68 }
69
70 pub fn set_config(&mut self, config: Arc<Config>) {
75 self.config = config;
76 }
77}
78
79#[async_trait]
80impl<T: IgHttpClient + 'static> OrderService for OrderServiceImpl<T> {
81 async fn create_order(
82 &self,
83 session: &IgSession,
84 order: &CreateOrderRequest,
85 ) -> Result<CreateOrderResponse, AppError> {
86 info!("Creating order for: {}", order.epic);
87
88 let result = self
89 .client
90 .request::<CreateOrderRequest, CreateOrderResponse>(
91 Method::POST,
92 "positions/otc",
93 session,
94 Some(order),
95 "2",
96 )
97 .await?;
98
99 debug!("Order created with reference: {}", result.deal_reference);
100 Ok(result)
101 }
102
103 async fn get_order_confirmation(
104 &self,
105 session: &IgSession,
106 deal_reference: &str,
107 ) -> Result<OrderConfirmation, AppError> {
108 let path = format!("confirms/{}", deal_reference);
109 info!("Getting confirmation for order: {}", deal_reference);
110
111 let result = self
112 .client
113 .request::<(), OrderConfirmation>(Method::GET, &path, session, None, "1")
114 .await?;
115
116 debug!("Confirmation obtained for order: {}", deal_reference);
117 Ok(result)
118 }
119
120 async fn update_position(
121 &self,
122 session: &IgSession,
123 deal_id: &str,
124 update: &UpdatePositionRequest,
125 ) -> Result<(), AppError> {
126 let path = format!("positions/otc/{}", deal_id);
127 info!("Updating position: {}", deal_id);
128
129 self.client
130 .request::<UpdatePositionRequest, ()>(Method::PUT, &path, session, Some(update), "2")
131 .await?;
132
133 debug!("Position updated: {}", deal_id);
134 Ok(())
135 }
136
137 async fn close_position(
138 &self,
139 session: &IgSession,
140 close_request: &ClosePositionRequest,
141 ) -> Result<ClosePositionResponse, AppError> {
142 info!("Closing position: {}", close_request.deal_id);
143
144 let result = self
145 .client
146 .request::<ClosePositionRequest, ClosePositionResponse>(
147 Method::POST,
148 "positions/otc",
149 session,
150 Some(close_request),
151 "1",
152 )
153 .await?;
154
155 debug!("Position closed with reference: {}", result.deal_reference);
156 Ok(result)
157 }
158}