Skip to main content

jup_ag_sdk/types/
trigger.rs

1use crate::types::to_comma_string;
2use serde::{Deserialize, Serialize};
3
4/// Request for a base64-encoded unsigned trigger order creation transaction
5///
6/// [Official API docs](https://dev.jup.ag/docs/api/trigger-api/create-order)
7#[derive(Debug, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase")]
9pub struct CreateTriggerOrder {
10    /// The mint address of the input token.
11    ///
12    /// Example: `"So11111111111111111111111111111111111111112"` (SOL)
13    pub input_mint: String,
14
15    /// The mint address of the output token.
16    ///
17    /// Example: `"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"`
18    pub output_mint: String,
19
20    /// Maker address
21    pub maker: String,
22
23    /// fee payer address
24    pub payer: String,
25
26    /// making and taking amount inputs
27    pub params: Params,
28
29    /// In microlamports, defaults to 95th percentile of priority fees
30    /// Default value: auto
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub compute_unit_price: Option<String>,
33
34    /// A token account (via the Referral Program) that will receive the fees
35    #[serde(skip_serializing_if = "Option::is_none")]
36    pub fee_account: Option<String>,
37
38    /// If either input or output mint is native SOL
39    /// Default value: true
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub wrap_and_unwrap_sol: Option<bool>,
42}
43
44#[derive(Debug, Serialize, Deserialize)]
45#[serde(rename_all = "camelCase")]
46pub struct Params {
47    /// Amount of input mint to swap
48    pub making_amount: String,
49
50    /// Amount of output mint to receive
51    pub taking_amount: String,
52
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub expired_at: Option<String>,
55
56    /// Amount of slippage the order can be executed with
57    /// Default value: 0
58    #[serde(skip_serializing_if = "Option::is_none")]
59    pub slippage_bps: Option<String>,
60
61    /// Requires the feeAccount parameter, the amount of fees in bps that will be sent to the fee account
62    #[serde(skip_serializing_if = "Option::is_none")]
63    pub fee_bps: Option<String>,
64}
65
66impl CreateTriggerOrder {
67    /// Creates a new trigger order with required parameters
68    pub fn new(
69        input_mint: &str,
70        output_mint: &str,
71        maker: &str,
72        payer: &str,
73        making_amount: u64,
74        taking_amount: u64,
75    ) -> Self {
76        Self {
77            input_mint: input_mint.to_string(),
78            output_mint: output_mint.to_string(),
79            maker: maker.to_string(),
80            payer: payer.to_string(),
81            params: Params::new(making_amount, taking_amount),
82            compute_unit_price: None,
83            fee_account: None,
84            wrap_and_unwrap_sol: None,
85        }
86    }
87
88    /// Sets the compute unit price in microlamports
89    /// Default value: auto
90    pub fn compute_unit_price(mut self, price: &str) -> Self {
91        self.compute_unit_price = Some(price.to_string());
92        self
93    }
94
95    /// Sets the fee account for referral program
96    pub fn fee_account(mut self, account: &str) -> Self {
97        self.fee_account = Some(account.to_string());
98        self
99    }
100
101    /// Sets whether to wrap and unwrap SOL
102    pub fn wrap_and_unwrap_sol(mut self, wrap: bool) -> Self {
103        self.wrap_and_unwrap_sol = Some(wrap);
104        self
105    }
106
107    /// Sets the expiration time for the order
108    pub fn expired_at(mut self, expired_at: &str) -> Self {
109        self.params.expired_at = Some(expired_at.to_string());
110        self
111    }
112
113    /// Sets the slippage in basis points
114    /// Default value: 0
115    pub fn slippage_bps(mut self, slippage: &str) -> Self {
116        self.params.slippage_bps = Some(slippage.to_string());
117        self
118    }
119
120    /// Sets the fee in basis points (requires fee_account to be set)
121    pub fn fee_bps(mut self, fee: &str) -> Self {
122        self.params.fee_bps = Some(fee.to_string());
123        self
124    }
125}
126
127impl Params {
128    /// Creates new parameters with required amounts
129    pub fn new(making_amount: u64, taking_amount: u64) -> Self {
130        Self {
131            making_amount: making_amount.to_string(),
132            taking_amount: taking_amount.to_string(),
133            expired_at: None,
134            slippage_bps: None,
135            fee_bps: None,
136        }
137    }
138
139    /// Sets expiration time (Unix timestamp or relative time)
140    pub fn expired_at(mut self, expired_at: &str) -> Self {
141        self.expired_at = Some(expired_at.to_string());
142        self
143    }
144
145    /// Sets slippage tolerance in basis points
146    pub fn slippage_bps(mut self, slippage: &str) -> Self {
147        self.slippage_bps = Some(slippage.to_string());
148        self
149    }
150
151    /// Sets fee in basis points
152    pub fn fee_bps(mut self, fee: &str) -> Self {
153        self.fee_bps = Some(fee.to_string());
154        self
155    }
156}
157
158#[derive(Debug, Serialize, Deserialize)]
159#[serde(rename_all = "camelCase")]
160pub struct TriggerResponse {
161    /// Required to make a request to /execute
162    pub request_id: String,
163
164    /// Unsigned base-64 encoded transaction
165    #[serde(default)]
166    pub transaction: String,
167
168    /// cancel trigger orders
169    #[serde(default)]
170    pub transactions: Option<Vec<String>>,
171
172    /// solana PDA Trigger Order account
173    #[serde(default)]
174    pub order: Option<String>,
175
176    pub code: u8,
177}
178
179#[derive(Debug, Serialize, Deserialize)]
180#[serde(rename_all = "camelCase")]
181pub struct ExecuteTriggerOrder {
182    /// The request ID  
183    pub request_id: String,
184
185    /// The base-58 signed transaction to execute
186    pub signed_transaction: String,
187}
188
189impl ExecuteTriggerOrder {
190    pub fn new(request_id: &str, signed_transaction: &str) -> Self {
191        Self {
192            request_id: request_id.to_string(),
193            signed_transaction: signed_transaction.to_string(),
194        }
195    }
196}
197
198#[derive(Debug, Serialize, Deserialize)]
199pub struct ExecuteTriggerOrderResponse {
200    pub code: u8,
201
202    /// transaction signature
203    pub signature: String,
204
205    /// status of the transaction
206    pub status: String,
207
208    /// solana PDA Trigger Order account
209    #[serde(default)]
210    pub order: Option<String>,
211}
212
213#[derive(Debug, Serialize, Deserialize)]
214#[serde(rename_all = "camelCase")]
215pub struct CancelTriggerOrder {
216    /// maker address
217    pub maker: String,
218
219    /// solana PDA Trigger Order account
220    pub order: String,
221
222    /// In microlamports, defaults to 95th percentile of priority fees
223    /// Default value: auto
224    #[serde(skip_serializing_if = "Option::is_none")]
225    pub compute_unit_price: Option<String>,
226}
227
228impl CancelTriggerOrder {
229    /// Arguments:
230    /// maker: &str - The maker's wallet address
231    /// order: &str - The solana PDA Trigger Order account
232    pub fn new(maker: &str, order: &str) -> Self {
233        Self {
234            maker: maker.to_string(),
235            order: order.to_string(),
236            compute_unit_price: None,
237        }
238    }
239}
240
241#[derive(Debug, Serialize, Deserialize)]
242#[serde(rename_all = "camelCase")]
243pub struct CancelTriggerOrders {
244    pub maker: String,
245
246    /// solana PDA Trigger Order account
247    #[serde(serialize_with = "to_comma_string")]
248    pub order: Vec<String>,
249
250    /// In microlamports, defaults to 95th percentile of priority fees
251    /// Default value: auto
252    #[serde(skip_serializing_if = "Option::is_none")]
253    pub compute_unit_price: Option<String>,
254}
255
256impl CancelTriggerOrders {
257    /// Arguments:
258    /// maker: &str - The maker's wallet address
259    /// orders: Vec<String> - Vector of solana PDA Trigger Order accounts
260    pub fn new(maker: &str, orders: Vec<String>) -> Self {
261        Self {
262            maker: maker.to_string(),
263            order: orders,
264            compute_unit_price: None,
265        }
266    }
267
268    /// Sets the compute unit price in microlamports
269    pub fn compute_unit_price(mut self, price: &str) -> Self {
270        self.compute_unit_price = Some(price.to_string());
271        self
272    }
273}
274
275#[derive(Debug, Serialize, Deserialize)]
276#[serde(rename_all = "camelCase")]
277pub struct GetTriggerOrders {
278    /// user wallet address to retrive orders for
279    pub user: String,
280
281    /// Default value: 1
282    pub page: Option<String>,
283
284    /// Whether to include failed transactions, expects 'true' or 'false'
285    /// Possible values: [true, false]
286    pub include_failed_tx: Option<String>,
287
288    /// The status of the orders to return
289    /// Possible values: [active, history]
290    pub order_status: OrderStatus,
291
292    /// The input mint to filter by
293    pub input_mint: Option<String>,
294
295    /// The output mint to filter by
296    pub output_mint: Option<String>,
297}
298
299#[derive(Debug, Serialize, Deserialize)]
300#[serde(rename_all = "camelCase")]
301pub enum OrderStatus {
302    Active,
303    History,
304}
305
306impl GetTriggerOrders {
307    /// Creates a new request to get trigger orders for a user
308    pub fn new(user: &str, order_status: OrderStatus) -> Self {
309        Self {
310            user: user.to_string(),
311            page: None,
312            include_failed_tx: Some("false".to_string()),
313            order_status,
314            input_mint: None,
315            output_mint: None,
316        }
317    }
318
319    /// Sets the page number for pagination
320    pub fn page(mut self, page: &str) -> Self {
321        self.page = Some(page.to_string());
322        self
323    }
324
325    /// Sets whether to include failed transactions
326    pub fn include_failed_tx(mut self, include: bool) -> Self {
327        self.include_failed_tx = Some(include.to_string());
328        self
329    }
330
331    /// Sets the order status to filter by
332    pub fn order_status(mut self, status: OrderStatus) -> Self {
333        self.order_status = status;
334        self
335    }
336
337    /// Sets the input mint to filter by
338    pub fn input_mint(mut self, mint: &str) -> Self {
339        self.input_mint = Some(mint.to_string());
340        self
341    }
342
343    /// Sets the output mint to filter by
344    pub fn output_mint(mut self, mint: &str) -> Self {
345        self.output_mint = Some(mint.to_string());
346        self
347    }
348}
349
350/// orders associated to the provided user wallet address
351#[derive(Debug, Serialize, Deserialize)]
352#[serde(rename_all = "camelCase")]
353pub struct OrderResponse {
354    pub user: String,
355    pub order_status: String,
356    pub orders: Vec<Order>,
357    pub total_pages: u32,
358    pub page: u32,
359}
360
361#[derive(Debug, Serialize, Deserialize)]
362#[serde(rename_all = "camelCase")]
363pub struct Order {
364    pub user_pubkey: String,
365    pub order_key: String,
366    pub input_mint: String,
367    pub output_mint: String,
368    pub making_amount: String,
369    pub taking_amount: String,
370    pub remaining_making_amount: String,
371    pub remaining_taking_amount: String,
372    pub raw_making_amount: String,
373    pub raw_taking_amount: String,
374    pub raw_remaining_making_amount: String,
375    pub raw_remaining_taking_amount: String,
376    pub slippage_bps: String,
377    #[serde(default)]
378    pub expired_at: Option<String>,
379    pub created_at: String,
380    pub updated_at: String,
381    pub status: String,
382    pub open_tx: String,
383    pub close_tx: String,
384    pub program_version: String,
385    pub trades: Vec<Trade>,
386}
387
388#[derive(Debug, Serialize, Deserialize)]
389#[serde(rename_all = "camelCase")]
390pub struct Trade {
391    pub order_key: String,
392    pub keeper: String,
393    pub input_mint: String,
394    pub output_mint: String,
395    pub input_amount: String,
396    pub output_amount: String,
397    pub raw_input_amount: String,
398    pub raw_output_amount: String,
399    pub fee_mint: String,
400    pub fee_amount: String,
401    pub raw_fee_amount: String,
402    pub tx_id: String,
403    pub confirmed_at: String,
404    pub action: String,
405    #[serde(default)]
406    pub product_meta: Option<serde_json::Value>, // Flexible for null or arbitrary JSON
407}