gateio_rs/api/spot/create_price_order.rs
1use crate::http::{Credentials, Method, request::Request};
2use serde_json::{Map, Value, json};
3
4/// # SpotPriceTrigger
5///
6/// Trigger conditions for price-triggered orders
7///
8/// ##### price:
9/// Trigger price that will activate the order
10///
11/// ##### rule:
12/// Trigger rule:
13/// - ">=" : Order triggers when market price is greater than or equal to trigger price
14/// - "<=" : Order triggers when market price is less than or equal to trigger price
15///
16/// ##### expiration:
17/// Valid duration in seconds (optional)
18/// If not set, the order will remain active until manually cancelled
19#[derive(Debug, Clone)]
20pub struct SpotPriceTrigger {
21 /// Trigger price that will activate the order
22 pub price: String,
23 /// Trigger rule ('>=' or '<=')
24 pub rule: String,
25 /// Valid duration in seconds (optional)
26 pub expiration: Option<i64>,
27}
28
29impl SpotPriceTrigger {
30 /// Create a new price trigger condition
31 pub fn new(price: &str, rule: &str) -> Self {
32 Self {
33 price: price.to_owned(),
34 rule: rule.to_owned(),
35 expiration: None,
36 }
37 }
38
39 /// Set the trigger expiration time in seconds
40 pub fn expiration(mut self, expiration: i64) -> Self {
41 self.expiration = Some(expiration);
42 self
43 }
44}
45
46/// # SpotPricePutOrder
47///
48/// The order to be placed when the trigger condition is met
49///
50/// ##### order_type:
51/// Order type - currently only "limit" orders are supported for price-triggered orders
52///
53/// ##### side:
54/// Order side:
55/// - "buy" : Buy order
56/// - "sell" : Sell order
57///
58/// ##### price:
59/// Limit order price - the price at which the order will be placed when triggered
60///
61/// ##### amount:
62/// Order amount - the quantity to trade
63///
64/// ##### account:
65/// Trading account type:
66/// - "normal" : Normal spot trading account
67/// - "margin" : Margin trading account
68/// - "unified" : Unified trading account
69///
70/// ##### time_in_force:
71/// Time in force for the triggered order:
72/// - "gtc" : Good Till Cancelled (default)
73/// - "ioc" : Immediate Or Cancel
74/// - "fok" : Fill Or Kill
75/// - "poc" : Post Only
76#[derive(Debug, Clone)]
77pub struct SpotPricePutOrder {
78 /// Order type (currently only "limit" supported)
79 pub order_type: String,
80 /// Order side ("buy" or "sell")
81 pub side: String,
82 /// Limit order price
83 pub price: String,
84 /// Order amount/quantity
85 pub amount: String,
86 /// Trading account type
87 pub account: Option<String>,
88 /// Time in force for the triggered order
89 pub time_in_force: Option<String>,
90}
91
92impl SpotPricePutOrder {
93 /// Create a new order to place when triggered
94 pub fn new(order_type: &str, side: &str, price: &str, amount: &str) -> Self {
95 Self {
96 order_type: order_type.to_owned(),
97 side: side.to_owned(),
98 price: price.to_owned(),
99 amount: amount.to_owned(),
100 account: None,
101 time_in_force: None,
102 }
103 }
104
105 /// Set the trading account type
106 pub fn account(mut self, account: &str) -> Self {
107 self.account = Some(account.to_owned());
108 self
109 }
110
111 /// Set the time in force for the triggered order
112 pub fn time_in_force(mut self, time_in_force: &str) -> Self {
113 self.time_in_force = Some(time_in_force.to_owned());
114 self
115 }
116}
117
118/// # Create a price-triggered order
119///
120/// A price-triggered order (also known as conditional order) will not enter the order book
121/// until the trigger condition is met. Once triggered, it will attempt to place a limit order
122/// at the preset price and amount.
123///
124/// ## Important Notes:
125///
126/// - The conditional order does not occupy your balance until it is triggered
127/// - Make sure to set aside enough balance for this order
128/// - A price condition order can only be triggered one time
129/// - When using "<=", the trigger price should be less than the current market price
130/// - When using ">=", the trigger price should be greater than the current market price
131/// - Only limit orders are supported as the triggered order type
132///
133/// ## Status Values:
134/// - "open" : Waiting to trigger
135/// - "cancelled" : Manually cancelled
136/// - "finish" : Successfully executed
137/// - "failed" : Failed to execute
138/// - "expired" : Expired
139///
140/// [Gate API Documentation](https://www.gate.com/docs/developers/apiv4/#create-a-price-triggered-order)
141pub struct CreatePriceOrder {
142 /// Trigger conditions for the order
143 pub trigger: SpotPriceTrigger,
144 /// Order details to execute when triggered
145 pub put: SpotPricePutOrder,
146 /// Currency pair for the order
147 pub market: String,
148 /// Request expiration time in milliseconds
149 pub x_gate_exp_time: Option<u128>,
150 /// API credentials for authentication
151 pub credentials: Option<Credentials>,
152}
153
154impl CreatePriceOrder {
155 /// Create a new price-triggered order request
156 pub fn new(
157 market: &str,
158 trigger_price: &str,
159 trigger_rule: &str,
160 order_side: &str,
161 order_price: &str,
162 order_amount: &str,
163 ) -> Self {
164 Self {
165 trigger: SpotPriceTrigger::new(trigger_price, trigger_rule),
166 put: SpotPricePutOrder::new("limit", order_side, order_price, order_amount),
167 market: market.to_owned(),
168 x_gate_exp_time: None,
169 credentials: None,
170 }
171 }
172
173 /// Set the trigger conditions
174 pub fn trigger(mut self, trigger: SpotPriceTrigger) -> Self {
175 self.trigger = trigger;
176 self
177 }
178
179 /// Set the order details to execute when triggered
180 pub fn put(mut self, put: SpotPricePutOrder) -> Self {
181 self.put = put;
182 self
183 }
184
185 /// Set the trigger expiration time in seconds
186 pub fn trigger_expiration(mut self, expiration: i64) -> Self {
187 self.trigger.expiration = Some(expiration);
188 self
189 }
190
191 /// Set the trading account type for the triggered order
192 pub fn account(mut self, account: &str) -> Self {
193 self.put.account = Some(account.to_owned());
194 self
195 }
196
197 /// Set the time in force for the triggered order
198 pub fn time_in_force(mut self, time_in_force: &str) -> Self {
199 self.put.time_in_force = Some(time_in_force.to_owned());
200 self
201 }
202
203 /// Specify the expiration time (milliseconds);
204 /// If the GATE receives the request time greater than the expiration time, the request will be rejected
205 pub fn x_gate_exp_time(mut self, x_gate_exp_time: u128) -> Self {
206 self.x_gate_exp_time = Some(x_gate_exp_time);
207 self
208 }
209
210 /// Set API credentials for authentication
211 pub fn credentials(mut self, creds: Credentials) -> Self {
212 self.credentials = Some(creds);
213 self
214 }
215}
216
217impl From<CreatePriceOrder> for Request {
218 fn from(request: CreatePriceOrder) -> Request {
219 let params = Vec::new();
220 let mut payload = Map::new();
221
222 // Add market (currency pair)
223 payload.insert("market".to_string(), json!(request.market));
224
225 // Add trigger object
226 let mut trigger_obj = Map::new();
227 trigger_obj.insert("price".to_string(), json!(request.trigger.price));
228 trigger_obj.insert("rule".to_string(), json!(request.trigger.rule));
229
230 if let Some(expiration) = request.trigger.expiration {
231 trigger_obj.insert("expiration".to_string(), json!(expiration));
232 }
233
234 payload.insert("trigger".to_string(), Value::Object(trigger_obj));
235
236 // Add put object (the order to be placed when triggered)
237 let mut put_obj = Map::new();
238 put_obj.insert("type".to_string(), json!(request.put.order_type));
239 put_obj.insert("side".to_string(), json!(request.put.side));
240 put_obj.insert("price".to_string(), json!(request.put.price));
241 put_obj.insert("amount".to_string(), json!(request.put.amount));
242
243 if let Some(account) = request.put.account {
244 put_obj.insert("account".to_string(), json!(account));
245 }
246
247 if let Some(time_in_force) = request.put.time_in_force {
248 put_obj.insert("time_in_force".to_string(), json!(time_in_force));
249 }
250
251 payload.insert("put".to_string(), Value::Object(put_obj));
252
253 let payload_json = Value::Object(payload);
254
255 Request {
256 method: Method::Post,
257 path: "/api/v4/spot/price_orders".into(),
258 params,
259 payload: payload_json.to_string(),
260 x_gate_exp_time: request.x_gate_exp_time,
261 credentials: request.credentials,
262 sign: true,
263 }
264 }
265}