gmsol_store/instructions/
virtual_inventory.rs1use anchor_lang::prelude::*;
2use gmsol_utils::InitSpace;
3
4use crate::{
5 constants::MARKET_DECIMALS,
6 internal,
7 states::{
8 market::virtual_inventory::{
9 VirtualInventory, VIRTUAL_INVENTORY_FOR_POSITIONS_SEED,
10 VIRTUAL_INVENTORY_FOR_SWAPS_SEED,
11 },
12 Market, Store, TokenMapHeader, TokenMapLoader,
13 },
14 CoreError,
15};
16
17#[derive(Accounts)]
19pub struct CloseVirtualInventory<'info> {
20 #[account(mut)]
22 pub authority: Signer<'info>,
23 pub store: AccountLoader<'info, Store>,
25 #[account(mut, seeds = [Store::WALLET_SEED, store.key().as_ref()], bump)]
27 pub store_wallet: SystemAccount<'info>,
28 #[account(
30 mut,
31 close = store_wallet,
32 has_one = store,
33 constraint = virtual_inventory.load()?.ref_count() == 0,
34 )]
35 pub virtual_inventory: AccountLoader<'info, VirtualInventory>,
36}
37
38impl CloseVirtualInventory<'_> {
39 pub(crate) fn invoke_unchecked(_ctx: Context<Self>) -> Result<()> {
44 Ok(())
45 }
46}
47
48impl<'info> internal::Authentication<'info> for CloseVirtualInventory<'info> {
49 fn authority(&self) -> &Signer<'info> {
50 &self.authority
51 }
52
53 fn store(&self) -> &AccountLoader<'info, Store> {
54 &self.store
55 }
56}
57
58#[derive(Accounts)]
60pub struct DisableVirtualInventory<'info> {
61 pub authority: Signer<'info>,
63 pub store: AccountLoader<'info, Store>,
65 #[account(
67 mut,
68 has_one = store,
69 constraint = !virtual_inventory.load()?.is_disabled() @ CoreError::PreconditionsAreNotMet,
70 )]
71 pub virtual_inventory: AccountLoader<'info, VirtualInventory>,
72}
73
74impl<'info> internal::Authentication<'info> for DisableVirtualInventory<'info> {
75 fn authority(&self) -> &Signer<'info> {
76 &self.authority
77 }
78
79 fn store(&self) -> &AccountLoader<'info, Store> {
80 &self.store
81 }
82}
83
84impl DisableVirtualInventory<'_> {
85 pub(crate) fn invoke_unchecked(ctx: Context<Self>) -> Result<()> {
90 ctx.accounts.virtual_inventory.load_mut()?.disable()?;
91 Ok(())
92 }
93}
94
95#[derive(Accounts)]
97pub struct LeaveDisabledVirtualInventory<'info> {
98 pub authority: Signer<'info>,
100 pub store: AccountLoader<'info, Store>,
102 #[account(
104 mut,
105 has_one = store,
106 constraint = virtual_inventory.load()?.is_disabled() @ CoreError::PreconditionsAreNotMet,
107 )]
108 pub virtual_inventory: AccountLoader<'info, VirtualInventory>,
109 #[account(mut, has_one = store)]
111 pub market: AccountLoader<'info, Market>,
112}
113
114impl<'info> internal::Authentication<'info> for LeaveDisabledVirtualInventory<'info> {
115 fn authority(&self) -> &Signer<'info> {
116 &self.authority
117 }
118
119 fn store(&self) -> &AccountLoader<'info, Store> {
120 &self.store
121 }
122}
123
124impl LeaveDisabledVirtualInventory<'_> {
125 pub(crate) fn invoke_unchecked(ctx: Context<Self>) -> Result<()> {
130 let address = ctx.accounts.virtual_inventory.key();
131 let mut market = ctx.accounts.market.load_mut()?;
132 let mut virtual_inventory = ctx.accounts.virtual_inventory.load_mut()?;
133 market.leave_disabled_virtual_inventory_unchecked(&address, &mut virtual_inventory)?;
134 Ok(())
135 }
136}
137
138#[derive(Accounts)]
140#[instruction(index: u32)]
141pub struct CreateVirtualInventoryForSwaps<'info> {
142 #[account(mut)]
144 pub authority: Signer<'info>,
145 pub store: AccountLoader<'info, Store>,
147 #[account(
149 init,
150 payer = authority,
151 space = 8 + VirtualInventory::INIT_SPACE,
152 seeds = [VIRTUAL_INVENTORY_FOR_SWAPS_SEED, store.key().as_ref(), &index.to_le_bytes()],
153 bump,
154 )]
155 pub virtual_inventory: AccountLoader<'info, VirtualInventory>,
156 pub system_program: Program<'info, System>,
158}
159
160impl CreateVirtualInventoryForSwaps<'_> {
161 pub(crate) fn invoke_unchecked(
166 ctx: Context<Self>,
167 index: u32,
168 long_amount_decimals: u8,
169 short_amount_decimals: u8,
170 ) -> Result<()> {
171 ctx.accounts.virtual_inventory.load_init()?.init(
172 ctx.bumps.virtual_inventory,
173 index,
174 ctx.accounts.store.key(),
175 long_amount_decimals,
176 short_amount_decimals,
177 );
178 Ok(())
179 }
180}
181
182impl<'info> internal::Authentication<'info> for CreateVirtualInventoryForSwaps<'info> {
183 fn authority(&self) -> &Signer<'info> {
184 &self.authority
185 }
186
187 fn store(&self) -> &AccountLoader<'info, Store> {
188 &self.store
189 }
190}
191
192#[derive(Accounts)]
195pub struct JoinVirtualInventoryForSwaps<'info> {
196 pub authority: Signer<'info>,
198 pub store: AccountLoader<'info, Store>,
200 #[account(has_one = store)]
202 pub token_map: AccountLoader<'info, TokenMapHeader>,
203 #[account(
205 mut,
206 seeds = [VIRTUAL_INVENTORY_FOR_SWAPS_SEED, store.key().as_ref(), &virtual_inventory.load()?.index.to_le_bytes()],
207 bump = virtual_inventory.load()?.bump,
208 has_one = store,
209 constraint = !virtual_inventory.load()?.is_disabled() @ CoreError::PreconditionsAreNotMet,
210 )]
211 pub virtual_inventory: AccountLoader<'info, VirtualInventory>,
212 #[account(mut, has_one = store, constraint = !market.load()?.is_pure())]
214 pub market: AccountLoader<'info, Market>,
215}
216
217impl JoinVirtualInventoryForSwaps<'_> {
218 pub(crate) fn invoke_unchecked(ctx: Context<Self>) -> Result<()> {
223 let address = ctx.accounts.virtual_inventory.key();
224 let mut virtual_inventory = ctx.accounts.virtual_inventory.load_mut()?;
225 let token_map = ctx.accounts.token_map.load_token_map()?;
226 ctx.accounts
227 .market
228 .load_mut()?
229 .join_virtual_inventory_for_swaps_unchecked(
230 &address,
231 &mut virtual_inventory,
232 &token_map,
233 )?;
234 Ok(())
235 }
236}
237
238impl<'info> internal::Authentication<'info> for JoinVirtualInventoryForSwaps<'info> {
239 fn authority(&self) -> &Signer<'info> {
240 &self.authority
241 }
242
243 fn store(&self) -> &AccountLoader<'info, Store> {
244 &self.store
245 }
246}
247
248#[derive(Accounts)]
251pub struct LeaveVirtualInventoryForSwaps<'info> {
252 pub authority: Signer<'info>,
254 pub store: AccountLoader<'info, Store>,
256 #[account(
258 mut,
259 seeds = [VIRTUAL_INVENTORY_FOR_SWAPS_SEED, store.key().as_ref(), &virtual_inventory.load()?.index.to_le_bytes()],
260 bump = virtual_inventory.load()?.bump,
261 has_one = store,
262 constraint = !virtual_inventory.load()?.is_disabled() @ CoreError::PreconditionsAreNotMet,
263 )]
264 pub virtual_inventory: AccountLoader<'info, VirtualInventory>,
265 #[account(mut, has_one = store, constraint = !market.load()?.is_pure())]
267 pub market: AccountLoader<'info, Market>,
268}
269
270impl LeaveVirtualInventoryForSwaps<'_> {
271 pub(crate) fn invoke_unchecked(ctx: Context<Self>) -> Result<()> {
276 let address = ctx.accounts.virtual_inventory.key();
277 let mut market = ctx.accounts.market.load_mut()?;
278 let virtual_inventory_for_swaps = market
279 .virtual_inventory_for_swaps()
280 .ok_or_else(|| error!(CoreError::PreconditionsAreNotMet))?;
281 require_keys_eq!(*virtual_inventory_for_swaps, address);
282 let mut virtual_inventory = ctx.accounts.virtual_inventory.load_mut()?;
283 market.leave_virtual_inventory_for_swaps_unchecked(&mut virtual_inventory)?;
284 Ok(())
285 }
286}
287
288impl<'info> internal::Authentication<'info> for LeaveVirtualInventoryForSwaps<'info> {
289 fn authority(&self) -> &Signer<'info> {
290 &self.authority
291 }
292
293 fn store(&self) -> &AccountLoader<'info, Store> {
294 &self.store
295 }
296}
297
298#[derive(Accounts)]
300pub struct CreateVirtualInventoryForPositions<'info> {
301 #[account(mut)]
303 pub authority: Signer<'info>,
304 pub store: AccountLoader<'info, Store>,
306 pub index_token: UncheckedAccount<'info>,
309 #[account(
311 init,
312 payer = authority,
313 space = 8 + VirtualInventory::INIT_SPACE,
314 seeds = [
315 VIRTUAL_INVENTORY_FOR_POSITIONS_SEED,
316 store.key().as_ref(),
317 index_token.key.as_ref(),
318 ],
319 bump,
320 )]
321 pub virtual_inventory: AccountLoader<'info, VirtualInventory>,
322 pub system_program: Program<'info, System>,
324}
325
326impl CreateVirtualInventoryForPositions<'_> {
327 pub(crate) fn invoke_unchecked(ctx: Context<Self>) -> Result<()> {
332 ctx.accounts.virtual_inventory.load_init()?.init(
333 ctx.bumps.virtual_inventory,
334 0,
335 ctx.accounts.store.key(),
336 MARKET_DECIMALS,
337 MARKET_DECIMALS,
338 );
339 Ok(())
340 }
341}
342
343impl<'info> internal::Authentication<'info> for CreateVirtualInventoryForPositions<'info> {
344 fn authority(&self) -> &Signer<'info> {
345 &self.authority
346 }
347
348 fn store(&self) -> &AccountLoader<'info, Store> {
349 &self.store
350 }
351}
352
353#[derive(Accounts)]
357pub struct JoinOrLeaveVirtualInventoryForPositions<'info> {
358 pub authority: Signer<'info>,
360 pub store: AccountLoader<'info, Store>,
362 #[account(
364 mut,
365 seeds = [VIRTUAL_INVENTORY_FOR_POSITIONS_SEED, store.key().as_ref(), market.load()?.meta().index_token_mint.as_ref()],
366 bump = virtual_inventory.load()?.bump,
367 has_one = store,
368 constraint = !virtual_inventory.load()?.is_disabled() @ CoreError::PreconditionsAreNotMet,
369 )]
370 pub virtual_inventory: AccountLoader<'info, VirtualInventory>,
371 #[account(mut, has_one = store)]
373 pub market: AccountLoader<'info, Market>,
374}
375
376impl JoinOrLeaveVirtualInventoryForPositions<'_> {
377 pub(crate) fn invoke_join_unchecked(ctx: Context<Self>) -> Result<()> {
382 let address = ctx.accounts.virtual_inventory.key();
383 let mut virtual_inventory = ctx.accounts.virtual_inventory.load_mut()?;
384 ctx.accounts
385 .market
386 .load_mut()?
387 .join_virtual_inventory_for_positions_unchecked(&address, &mut virtual_inventory)?;
388 Ok(())
389 }
390
391 pub(crate) fn invoke_leave_unchecked(ctx: Context<Self>) -> Result<()> {
396 let address = ctx.accounts.virtual_inventory.key();
397 let mut market = ctx.accounts.market.load_mut()?;
398 let virtual_inventory_for_positions = market
399 .virtual_inventory_for_positions()
400 .ok_or_else(|| error!(CoreError::PreconditionsAreNotMet))?;
401 require_keys_eq!(*virtual_inventory_for_positions, address);
402 let mut virtual_inventory = ctx.accounts.virtual_inventory.load_mut()?;
403 market.leave_virtual_inventory_for_positions_unchecked(&mut virtual_inventory)?;
404 Ok(())
405 }
406}
407
408impl<'info> internal::Authentication<'info> for JoinOrLeaveVirtualInventoryForPositions<'info> {
409 fn authority(&self) -> &Signer<'info> {
410 &self.authority
411 }
412
413 fn store(&self) -> &AccountLoader<'info, Store> {
414 &self.store
415 }
416}