use gmsol_programs::gmsol_store::{
client::{accounts, args},
types,
};
use gmsol_solana_utils::{AtomicGroup, IntoAtomicGroup, ProgramExt};
use typed_builder::TypedBuilder;
use crate::{
builders::{
callback::{Callback, CallbackParams},
StoreProgram,
},
serde::StringPubkey,
};
#[cfg_attr(js, derive(tsify_next::Tsify))]
#[cfg_attr(js, tsify(from_wasm_abi))]
#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, TypedBuilder)]
pub struct UpdateOrder {
#[cfg_attr(serde, serde(default))]
#[builder(default)]
pub program: StoreProgram,
#[builder(setter(into))]
pub payer: StringPubkey,
#[builder(setter(into))]
pub order: StringPubkey,
pub params: UpdateOrderParams,
}
#[cfg_attr(js, derive(tsify_next::Tsify))]
#[cfg_attr(js, tsify(from_wasm_abi))]
#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, TypedBuilder)]
pub struct UpdateOrderParams {
#[cfg_attr(serde, serde(default))]
#[builder(default, setter(strip_option))]
pub size_delta_value: Option<u128>,
#[cfg_attr(serde, serde(default))]
#[builder(default, setter(strip_option))]
pub acceptable_price: Option<u128>,
#[cfg_attr(serde, serde(default))]
#[builder(default, setter(strip_option))]
pub trigger_price: Option<u128>,
#[cfg_attr(serde, serde(default))]
#[builder(default, setter(strip_option))]
pub min_output: Option<u128>,
#[cfg_attr(serde, serde(default))]
#[builder(default, setter(strip_option))]
pub valid_from_ts: Option<i64>,
}
impl From<UpdateOrderParams> for types::UpdateOrderParams {
fn from(params: UpdateOrderParams) -> Self {
Self {
size_delta_value: params.size_delta_value,
acceptable_price: params.acceptable_price,
trigger_price: params.trigger_price,
min_output: params.min_output,
valid_from_ts: params.valid_from_ts,
}
}
}
#[cfg_attr(js, derive(tsify_next::Tsify))]
#[cfg_attr(js, tsify(from_wasm_abi))]
#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, TypedBuilder)]
pub struct UpdateOrderHint {
#[builder(setter(into))]
pub market_token: StringPubkey,
pub callback: Option<Callback>,
}
impl IntoAtomicGroup for UpdateOrder {
type Hint = UpdateOrderHint;
fn into_atomic_group(self, hint: &Self::Hint) -> gmsol_solana_utils::Result<AtomicGroup> {
let payer = self.payer.0;
let CallbackParams {
callback_authority,
callback_program,
callback_shared_data_account,
callback_partitioned_data_account,
..
} = self.program.get_callback_params(hint.callback.as_ref());
let update = self
.program
.anchor_instruction(args::UpdateOrderV2 {
params: self.params.into(),
})
.anchor_accounts(
accounts::UpdateOrderV2 {
owner: payer,
store: self.program.store.0,
market: self.program.find_market_address(&hint.market_token),
order: self.order.0,
event_authority: self.program.find_event_authority_address(),
program: self.program.id.0,
callback_authority,
callback_program,
callback_shared_data_account,
callback_partitioned_data_account,
},
true,
)
.build();
Ok(AtomicGroup::with_instructions(&payer, Some(update)))
}
}
#[cfg_attr(js, derive(tsify_next::Tsify))]
#[cfg_attr(js, tsify(from_wasm_abi))]
#[cfg_attr(serde, derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, TypedBuilder)]
pub struct SetShouldKeepPositionAccount {
#[cfg_attr(serde, serde(default))]
#[builder(default)]
pub program: StoreProgram,
#[builder(setter(into))]
pub payer: StringPubkey,
#[builder(setter(into))]
pub order: StringPubkey,
pub keep: bool,
}
impl IntoAtomicGroup for SetShouldKeepPositionAccount {
type Hint = ();
fn into_atomic_group(self, _hint: &Self::Hint) -> gmsol_solana_utils::Result<AtomicGroup> {
let owner = self.payer.0;
let ix = self
.program
.anchor_instruction(args::SetShouldKeepPositionAccount { keep: self.keep })
.anchor_accounts(
accounts::SetShouldKeepPositionAccount {
owner,
order: self.order.0,
},
false,
)
.build();
Ok(AtomicGroup::with_instructions(&self.payer, [ix]))
}
}
#[cfg(test)]
mod tests {
use gmsol_solana_utils::transaction_builder::default_before_sign;
use solana_sdk::pubkey::Pubkey;
use crate::constants;
use super::*;
#[test]
fn update_order() -> crate::Result<()> {
let payer = Pubkey::new_unique();
let order = Pubkey::new_unique();
let market_token = Pubkey::new_unique();
let params = UpdateOrderParams::builder()
.size_delta_value(1_000 * constants::MARKET_USD_UNIT)
.build();
UpdateOrder::builder()
.payer(payer)
.order(order)
.params(params)
.build()
.into_atomic_group(
&UpdateOrderHint::builder()
.market_token(market_token)
.callback(None)
.build(),
)?
.partially_signed_transaction_with_blockhash_and_options(
Default::default(),
Default::default(),
None,
default_before_sign,
)?;
Ok(())
}
}