Skip to main content

gmsol_sdk/js/instructions/
create_shift.rs

1use std::collections::HashSet;
2
3use gmsol_solana_utils::{AtomicGroup, IntoAtomicGroup, ParallelGroup};
4use serde::{Deserialize, Serialize};
5use tsify_next::Tsify;
6use wasm_bindgen::prelude::*;
7
8use crate::{
9    builders::{shift::CreateShift, token::PrepareTokenAccounts, user::PrepareUser, StoreProgram},
10    js::instructions::BuildTransactionOptions,
11    serde::StringPubkey,
12};
13
14use super::{TransactionGroup, TransactionGroupOptions};
15
16#[derive(Debug, Serialize, Deserialize, Tsify, Clone)]
17#[tsify(into_wasm_abi, from_wasm_abi)]
18pub struct CreateShiftParamsJs {
19    pub from_market_token: StringPubkey,
20    pub to_market_token: StringPubkey,
21    #[serde(default)]
22    pub receiver: Option<StringPubkey>,
23    #[serde(default)]
24    pub from_market_token_amount: Option<u128>,
25    #[serde(default)]
26    pub min_to_market_token_amount: Option<u128>,
27    #[serde(default)]
28    pub skip_to_market_token_ata_creation: Option<bool>,
29}
30
31#[derive(Debug, Serialize, Deserialize, Tsify)]
32#[tsify(into_wasm_abi, from_wasm_abi)]
33pub struct CreateShiftOptions {
34    pub recent_blockhash: String,
35    pub payer: StringPubkey,
36    #[serde(default)]
37    pub program: Option<StoreProgram>,
38    #[serde(default)]
39    pub compute_unit_price_micro_lamports: Option<u64>,
40    #[serde(default)]
41    pub compute_unit_min_priority_lamports: Option<u64>,
42    #[serde(default)]
43    pub transaction_group: TransactionGroupOptions,
44}
45
46#[wasm_bindgen]
47pub struct CreateShiftsBuilder {
48    payer: StringPubkey,
49    tokens: HashSet<StringPubkey>,
50    groups: Vec<AtomicGroup>,
51    transaction_group: TransactionGroupOptions,
52    build: BuildTransactionOptions,
53}
54
55#[wasm_bindgen]
56pub fn create_shifts_builder(
57    shifts: Vec<CreateShiftParamsJs>,
58    options: CreateShiftOptions,
59) -> crate::Result<CreateShiftsBuilder> {
60    let mut tokens = HashSet::default();
61    let mut groups: Vec<AtomicGroup> = Vec::with_capacity(shifts.len());
62
63    for params in shifts.into_iter() {
64        tokens.insert(params.to_market_token);
65
66        let program = options.program.clone().unwrap_or_default();
67        let builder = CreateShift::builder()
68            .program(program)
69            .payer(options.payer)
70            .from_market_token(params.from_market_token)
71            .to_market_token(params.to_market_token)
72            .from_market_token_amount(
73                params
74                    .from_market_token_amount
75                    .unwrap_or_default()
76                    .try_into()?,
77            )
78            .min_to_market_token_amount(
79                params
80                    .min_to_market_token_amount
81                    .unwrap_or_default()
82                    .try_into()?,
83            )
84            .skip_to_market_token_ata_creation(
85                params.skip_to_market_token_ata_creation.unwrap_or_default(),
86            );
87
88        let built = if let Some(r) = params.receiver {
89            builder.receiver(r).build()
90        } else {
91            builder.build()
92        };
93
94        let ag = built.into_atomic_group(&())?;
95        groups.push(ag);
96    }
97
98    Ok(CreateShiftsBuilder {
99        payer: options.payer,
100        tokens,
101        groups,
102        transaction_group: options.transaction_group,
103        build: BuildTransactionOptions {
104            recent_blockhash: options.recent_blockhash,
105            compute_unit_price_micro_lamports: options.compute_unit_price_micro_lamports,
106            compute_unit_min_priority_lamports: options.compute_unit_min_priority_lamports,
107        },
108    })
109}
110
111#[wasm_bindgen]
112impl CreateShiftsBuilder {
113    pub fn build_with_options(
114        self,
115        transaction_group: Option<TransactionGroupOptions>,
116        build: Option<BuildTransactionOptions>,
117    ) -> crate::Result<TransactionGroup> {
118        let mut group = transaction_group.unwrap_or(self.transaction_group).build();
119
120        let prepare_user = PrepareUser::builder()
121            .payer(self.payer)
122            .build()
123            .into_atomic_group(&())?;
124
125        let prepare_tokens = PrepareTokenAccounts::builder()
126            .owner(self.payer)
127            .payer(self.payer)
128            .tokens(self.tokens)
129            .build()
130            .into_atomic_group(&())?;
131
132        let build = build.unwrap_or(self.build);
133        TransactionGroup::new(
134            group
135                .add(prepare_user)?
136                .add(prepare_tokens)?
137                .add(self.groups.into_iter().collect::<ParallelGroup>())?
138                .optimize(false),
139            &build.recent_blockhash,
140            build.compute_unit_price_micro_lamports,
141            build.compute_unit_min_priority_lamports,
142        )
143    }
144}
145
146#[wasm_bindgen]
147pub fn create_shifts(
148    shifts: Vec<CreateShiftParamsJs>,
149    options: CreateShiftOptions,
150) -> crate::Result<TransactionGroup> {
151    create_shifts_builder(shifts, options)?.build_with_options(None, None)
152}