1use std::{future::Future, ops::Deref};
2
3use anchor_lang::system_program;
4use gmsol_programs::gmsol_store::client::{accounts, args};
5use gmsol_solana_utils::transaction_builder::TransactionBuilder;
6use solana_sdk::{pubkey::Pubkey, signer::Signer};
7
8pub trait VirtualInventoryOps<C> {
10 fn close_virtual_inventory_account(
12 &self,
13 store: &Pubkey,
14 virtual_inventory: &Pubkey,
15 ) -> crate::Result<TransactionBuilder<C>>;
16
17 fn disable_virtual_inventory(
19 &self,
20 store: &Pubkey,
21 virtual_inventory: &Pubkey,
22 ) -> crate::Result<TransactionBuilder<C>>;
23
24 fn leave_disabled_virtual_inventory(
26 &self,
27 store: &Pubkey,
28 market: &Pubkey,
29 virtual_inventory: &Pubkey,
30 ) -> crate::Result<TransactionBuilder<C>>;
31
32 fn create_virtual_inventory_for_swaps(
34 &self,
35 store: &Pubkey,
36 index: u32,
37 long_amount_decimals: u8,
38 short_amount_decimals: u8,
39 ) -> crate::Result<TransactionBuilder<C, Pubkey>>;
40
41 fn join_virtual_inventory_for_swaps(
43 &self,
44 store: &Pubkey,
45 market: &Pubkey,
46 virtual_inventory_for_swaps: &Pubkey,
47 hint_token_map: Option<&Pubkey>,
48 ) -> impl Future<Output = crate::Result<TransactionBuilder<C>>>;
49
50 fn leave_virtual_inventory_for_swaps(
52 &self,
53 store: &Pubkey,
54 market: &Pubkey,
55 virtual_inventory_for_swaps: &Pubkey,
56 ) -> crate::Result<TransactionBuilder<C>>;
57
58 fn create_virtual_inventory_for_positions(
60 &self,
61 store: &Pubkey,
62 index_token: &Pubkey,
63 ) -> crate::Result<TransactionBuilder<C, Pubkey>>;
64
65 fn join_virtual_inventory_for_positions(
67 &self,
68 store: &Pubkey,
69 market: &Pubkey,
70 virtual_inventory_for_positions: &Pubkey,
71 ) -> crate::Result<TransactionBuilder<C>>;
72
73 fn leave_virtual_inventory_for_positions(
75 &self,
76 store: &Pubkey,
77 market: &Pubkey,
78 virtual_inventory_for_positions: &Pubkey,
79 ) -> crate::Result<TransactionBuilder<C>>;
80}
81
82impl<C: Deref<Target = impl Signer> + Clone> VirtualInventoryOps<C> for crate::Client<C> {
83 fn close_virtual_inventory_account(
84 &self,
85 store: &Pubkey,
86 virtual_inventory: &Pubkey,
87 ) -> crate::Result<TransactionBuilder<C>> {
88 let txn = self
89 .store_transaction()
90 .anchor_accounts(accounts::CloseVirtualInventory {
91 authority: self.payer(),
92 store: *store,
93 store_wallet: self.find_store_wallet_address(store),
94 virtual_inventory: *virtual_inventory,
95 })
96 .anchor_args(args::CloseVirtualInventory {});
97
98 Ok(txn)
99 }
100
101 fn disable_virtual_inventory(
102 &self,
103 store: &Pubkey,
104 virtual_inventory: &Pubkey,
105 ) -> crate::Result<TransactionBuilder<C>> {
106 let txn = self
107 .store_transaction()
108 .anchor_accounts(accounts::DisableVirtualInventory {
109 authority: self.payer(),
110 store: *store,
111 virtual_inventory: *virtual_inventory,
112 })
113 .anchor_args(args::DisableVirtualInventory {});
114 Ok(txn)
115 }
116
117 fn leave_disabled_virtual_inventory(
118 &self,
119 store: &Pubkey,
120 market: &Pubkey,
121 virtual_inventory: &Pubkey,
122 ) -> crate::Result<TransactionBuilder<C>> {
123 let txn = self
124 .store_transaction()
125 .anchor_accounts(accounts::LeaveDisabledVirtualInventory {
126 authority: self.payer(),
127 store: *store,
128 virtual_inventory: *virtual_inventory,
129 market: *market,
130 })
131 .anchor_args(args::LeaveDisabledVirtualInventory {});
132 Ok(txn)
133 }
134
135 fn create_virtual_inventory_for_swaps(
136 &self,
137 store: &Pubkey,
138 index: u32,
139 long_amount_decimals: u8,
140 short_amount_decimals: u8,
141 ) -> crate::Result<TransactionBuilder<C, Pubkey>> {
142 let virtual_inventory = self.find_virtual_inventory_for_swaps_address(store, index);
143 let txn = self
144 .store_transaction()
145 .anchor_accounts(accounts::CreateVirtualInventoryForSwaps {
146 authority: self.payer(),
147 store: *store,
148 virtual_inventory,
149 system_program: system_program::ID,
150 })
151 .anchor_args(args::CreateVirtualInventoryForSwaps {
152 index,
153 long_amount_decimals,
154 short_amount_decimals,
155 })
156 .output(virtual_inventory);
157 Ok(txn)
158 }
159
160 async fn join_virtual_inventory_for_swaps(
161 &self,
162 store: &Pubkey,
163 market: &Pubkey,
164 virtual_inventory_for_swaps: &Pubkey,
165 hint_token_map: Option<&Pubkey>,
166 ) -> crate::Result<TransactionBuilder<C>> {
167 let token_map = match hint_token_map {
168 Some(address) => *address,
169 None => self
170 .authorized_token_map_address(store)
171 .await?
172 .ok_or(crate::Error::NotFound)?,
173 };
174 let txn = self
175 .store_transaction()
176 .anchor_accounts(accounts::JoinVirtualInventoryForSwaps {
177 authority: self.payer(),
178 store: *store,
179 token_map,
180 virtual_inventory: *virtual_inventory_for_swaps,
181 market: *market,
182 })
183 .anchor_args(args::JoinVirtualInventoryForSwaps {});
184
185 Ok(txn)
186 }
187
188 fn leave_virtual_inventory_for_swaps(
189 &self,
190 store: &Pubkey,
191 market: &Pubkey,
192 virtual_inventory_for_swaps: &Pubkey,
193 ) -> crate::Result<TransactionBuilder<C>> {
194 let txn = self
195 .store_transaction()
196 .anchor_accounts(accounts::LeaveVirtualInventoryForSwaps {
197 authority: self.payer(),
198 store: *store,
199 virtual_inventory: *virtual_inventory_for_swaps,
200 market: *market,
201 })
202 .anchor_args(args::LeaveVirtualInventoryForSwaps {});
203
204 Ok(txn)
205 }
206
207 fn create_virtual_inventory_for_positions(
208 &self,
209 store: &Pubkey,
210 index_token: &Pubkey,
211 ) -> crate::Result<TransactionBuilder<C, Pubkey>> {
212 let virtual_inventory =
213 self.find_virtual_inventory_for_positions_address(store, index_token);
214 let txn = self
215 .store_transaction()
216 .anchor_accounts(accounts::CreateVirtualInventoryForPositions {
217 authority: self.payer(),
218 store: *store,
219 index_token: *index_token,
220 virtual_inventory,
221 system_program: system_program::ID,
222 })
223 .anchor_args(args::CreateVirtualInventoryForPositions {})
224 .output(virtual_inventory);
225 Ok(txn)
226 }
227
228 fn join_virtual_inventory_for_positions(
229 &self,
230 store: &Pubkey,
231 market: &Pubkey,
232 virtual_inventory_for_positions: &Pubkey,
233 ) -> crate::Result<TransactionBuilder<C>> {
234 let txn = self
235 .store_transaction()
236 .anchor_accounts(accounts::JoinVirtualInventoryForPositions {
237 authority: self.payer(),
238 store: *store,
239 virtual_inventory: *virtual_inventory_for_positions,
240 market: *market,
241 })
242 .anchor_args(args::JoinVirtualInventoryForPositions {});
243
244 Ok(txn)
245 }
246
247 fn leave_virtual_inventory_for_positions(
248 &self,
249 store: &Pubkey,
250 market: &Pubkey,
251 virtual_inventory_for_positions: &Pubkey,
252 ) -> crate::Result<TransactionBuilder<C>> {
253 let txn = self
254 .store_transaction()
255 .anchor_accounts(accounts::LeaveVirtualInventoryForPositions {
256 authority: self.payer(),
257 store: *store,
258 virtual_inventory: *virtual_inventory_for_positions,
259 market: *market,
260 })
261 .anchor_args(args::LeaveVirtualInventoryForPositions {});
262
263 Ok(txn)
264 }
265}