Skip to main content

gmsol_sdk/builders/order/
update.rs

1use gmsol_programs::gmsol_store::{
2    client::{accounts, args},
3    types,
4};
5use gmsol_solana_utils::{AtomicGroup, IntoAtomicGroup, ProgramExt};
6use typed_builder::TypedBuilder;
7
8use crate::{
9    builders::{
10        callback::{Callback, CallbackParams},
11        StoreProgram,
12    },
13    serde::StringPubkey,
14};
15
16/// Builder for the `update_order` instruction.
17#[cfg_attr(js, derive(tsify_next::Tsify))]
18#[cfg_attr(js, tsify(from_wasm_abi))]
19#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
20#[derive(Debug, Clone, TypedBuilder)]
21pub struct UpdateOrder {
22    /// Program.
23    #[cfg_attr(serde, serde(default))]
24    #[builder(default)]
25    pub program: StoreProgram,
26    /// Payer (a.k.a. owner).
27    #[builder(setter(into))]
28    pub payer: StringPubkey,
29    /// Order.
30    #[builder(setter(into))]
31    pub order: StringPubkey,
32    /// Parameters.
33    pub params: UpdateOrderParams,
34}
35
36/// Parameters for creating an order.
37#[cfg_attr(js, derive(tsify_next::Tsify))]
38#[cfg_attr(js, tsify(from_wasm_abi))]
39#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
40#[derive(Debug, Clone, TypedBuilder)]
41pub struct UpdateOrderParams {
42    /// Size delta value.
43    #[cfg_attr(serde, serde(default))]
44    #[builder(default, setter(strip_option))]
45    pub size_delta_value: Option<u128>,
46    /// Acceptable price.
47    #[cfg_attr(serde, serde(default))]
48    #[builder(default, setter(strip_option))]
49    pub acceptable_price: Option<u128>,
50    /// Trigger price.
51    #[cfg_attr(serde, serde(default))]
52    #[builder(default, setter(strip_option))]
53    pub trigger_price: Option<u128>,
54    /// Min output.
55    #[cfg_attr(serde, serde(default))]
56    #[builder(default, setter(strip_option))]
57    pub min_output: Option<u128>,
58    /// Valid from this timestamp.
59    #[cfg_attr(serde, serde(default))]
60    #[builder(default, setter(strip_option))]
61    pub valid_from_ts: Option<i64>,
62}
63
64impl From<UpdateOrderParams> for types::UpdateOrderParams {
65    fn from(params: UpdateOrderParams) -> Self {
66        Self {
67            size_delta_value: params.size_delta_value,
68            acceptable_price: params.acceptable_price,
69            trigger_price: params.trigger_price,
70            min_output: params.min_output,
71            valid_from_ts: params.valid_from_ts,
72        }
73    }
74}
75
76/// Hint for [`UpdateOrder`].
77#[cfg_attr(js, derive(tsify_next::Tsify))]
78#[cfg_attr(js, tsify(from_wasm_abi))]
79#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
80#[derive(Debug, Clone, TypedBuilder)]
81pub struct UpdateOrderHint {
82    /// Market token.
83    #[builder(setter(into))]
84    pub market_token: StringPubkey,
85    /// Callback.
86    pub callback: Option<Callback>,
87}
88
89impl IntoAtomicGroup for UpdateOrder {
90    type Hint = UpdateOrderHint;
91
92    fn into_atomic_group(self, hint: &Self::Hint) -> gmsol_solana_utils::Result<AtomicGroup> {
93        let payer = self.payer.0;
94
95        let CallbackParams {
96            callback_authority,
97            callback_program,
98            callback_shared_data_account,
99            callback_partitioned_data_account,
100            ..
101        } = self.program.get_callback_params(hint.callback.as_ref());
102
103        let update = self
104            .program
105            .anchor_instruction(args::UpdateOrderV2 {
106                params: self.params.into(),
107            })
108            .anchor_accounts(
109                accounts::UpdateOrderV2 {
110                    owner: payer,
111                    store: self.program.store.0,
112                    market: self.program.find_market_address(&hint.market_token),
113                    order: self.order.0,
114                    event_authority: self.program.find_event_authority_address(),
115                    program: self.program.id.0,
116                    callback_authority,
117                    callback_program,
118                    callback_shared_data_account,
119                    callback_partitioned_data_account,
120                },
121                true,
122            )
123            .build();
124        Ok(AtomicGroup::with_instructions(&payer, Some(update)))
125    }
126}
127
128/// Builder for the `set_should_keep_position_account` instruction.
129#[cfg_attr(js, derive(tsify_next::Tsify))]
130#[cfg_attr(js, tsify(from_wasm_abi))]
131#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
132#[derive(Debug, Clone, TypedBuilder)]
133pub struct SetShouldKeepPositionAccount {
134    /// Program.
135    #[cfg_attr(serde, serde(default))]
136    #[builder(default)]
137    pub program: StoreProgram,
138    /// Payer (a.k.a. owner).
139    #[builder(setter(into))]
140    pub payer: StringPubkey,
141    /// Order.
142    #[builder(setter(into))]
143    pub order: StringPubkey,
144    /// Whether to keep position account.
145    pub keep: bool,
146}
147
148impl IntoAtomicGroup for SetShouldKeepPositionAccount {
149    type Hint = ();
150
151    fn into_atomic_group(self, _hint: &Self::Hint) -> gmsol_solana_utils::Result<AtomicGroup> {
152        let owner = self.payer.0;
153        let ix = self
154            .program
155            .anchor_instruction(args::SetShouldKeepPositionAccount { keep: self.keep })
156            .anchor_accounts(
157                accounts::SetShouldKeepPositionAccount {
158                    owner,
159                    order: self.order.0,
160                },
161                false,
162            )
163            .build();
164
165        Ok(AtomicGroup::with_instructions(&self.payer, [ix]))
166    }
167}
168
169#[cfg(test)]
170mod tests {
171    use gmsol_solana_utils::transaction_builder::default_before_sign;
172    use solana_sdk::pubkey::Pubkey;
173
174    use crate::constants;
175
176    use super::*;
177
178    #[test]
179    fn update_order() -> crate::Result<()> {
180        let payer = Pubkey::new_unique();
181        let order = Pubkey::new_unique();
182        let market_token = Pubkey::new_unique();
183        let params = UpdateOrderParams::builder()
184            .size_delta_value(1_000 * constants::MARKET_USD_UNIT)
185            .build();
186        UpdateOrder::builder()
187            .payer(payer)
188            .order(order)
189            .params(params)
190            .build()
191            .into_atomic_group(
192                &UpdateOrderHint::builder()
193                    .market_token(market_token)
194                    .callback(None)
195                    .build(),
196            )?
197            .partially_signed_transaction_with_blockhash_and_options(
198                Default::default(),
199                Default::default(),
200                None,
201                default_before_sign,
202            )?;
203        Ok(())
204    }
205}