Skip to main content

dhan_rs/api/
super_order.rs

1//! Super Order endpoints.
2
3use crate::client::{DhanClient, required_path_segment};
4use crate::error::{DhanError, Result};
5use crate::types::orders::OrderResponse;
6use crate::types::super_order::*;
7
8impl DhanClient {
9    /// Place a new super order.
10    ///
11    /// **Endpoint:** `POST /v2/super/orders`
12    pub async fn place_super_order(&self, req: &PlaceSuperOrderRequest) -> Result<OrderResponse> {
13        self.post("/v2/super/orders", req).await
14    }
15
16    /// Modify a pending super order.
17    ///
18    /// **Endpoint:** `PUT /v2/super/orders/{order-id}`
19    pub async fn modify_super_order(
20        &self,
21        order_id: &str,
22        req: &ModifySuperOrderRequest,
23    ) -> Result<OrderResponse> {
24        let order_id = required_path_segment("order_id", order_id)?;
25        self.put(&format!("/v2/super/orders/{order_id}"), req).await
26    }
27
28    /// Cancel a super order leg.
29    ///
30    /// Cancelling the `ENTRY_LEG` cancels all legs.
31    ///
32    /// **Endpoint:** `DELETE /v2/super/orders/{order-id}/{order-leg}`
33    pub async fn cancel_super_order(&self, order_id: &str, leg: &str) -> Result<OrderResponse> {
34        let order_id = required_path_segment("order_id", order_id)?;
35        validate_super_order_leg(leg)?;
36        self.delete(&format!("/v2/super/orders/{order_id}/{leg}"))
37            .await
38    }
39
40    /// Cancel a super order leg when the server follows the HTML contract and
41    /// returns a successful empty response.
42    ///
43    /// Dhan's linked OpenAPI describes a `200` JSON [`OrderResponse`] for this
44    /// operation, while the HTML page describes `202 Accepted` with no body.
45    /// [`Self::cancel_super_order`] models the OpenAPI form; this method models
46    /// the HTML form without attempting to deserialize an empty response.
47    ///
48    /// **Endpoint:** `DELETE /v2/super/orders/{order-id}/{order-leg}`
49    pub async fn cancel_super_order_no_content(&self, order_id: &str, leg: &str) -> Result<()> {
50        let order_id = required_path_segment("order_id", order_id)?;
51        validate_super_order_leg(leg)?;
52        self.delete_no_content(&format!("/v2/super/orders/{order_id}/{leg}"))
53            .await
54    }
55
56    /// Retrieve all super orders for the day.
57    ///
58    /// **Endpoint:** `GET /v2/super/orders`
59    pub async fn get_super_orders(&self) -> Result<Vec<SuperOrderDetail>> {
60        self.get("/v2/super/orders").await
61    }
62}
63
64fn validate_super_order_leg(leg: &str) -> Result<()> {
65    if matches!(leg, "ENTRY_LEG" | "TARGET_LEG" | "STOP_LOSS_LEG") {
66        Ok(())
67    } else {
68        Err(DhanError::InvalidArgument(
69            "leg must be ENTRY_LEG, TARGET_LEG, or STOP_LOSS_LEG".into(),
70        ))
71    }
72}