gmsol_store/
lib.rs

1//! # The GMX-Solana Store Program
2//!
3//! The Store Program defines several fundamental accounts that form the core of its functionality:
4//!
5//! - [`Store`](states::Store): A central account that serves as a global configuration store and
6//!   permission manager. It acts as the authority ("owner") for other program accounts and manages
7//!   role-based access control. The global [GT](#gt-model) state is also stored in this account.
8//! - [`TokenMap`](states::TokenMap): A mapping of token configurations and price feed configurations
9//!   that defines supported tokens and their associated price oracle feeds.
10//! - [`Market`](states::Market): A market account that stores market-specific configurations and
11//!   maintains the global market state.
12//! - [`Position`](states::Position): Tracks a user's active position in a market.
13//! - Basic Market Action accounts: Accounts that track user actions and positions in markets
14//!   - [`Deposit`](states::Deposit): Tracks a user's pending deposit request into a market.
15//!   - [`Withdrawal`](states::Withdrawal): Tracks a user's pending withdrawal request from a market.
16//!   - [`Shift`](states::Shift): Tracks a user's pending request to shift from one kind of market token to another.
17//!   - [`Order`](states::Order): Tracks a user's pending order request in a market, including swap orders and increase/decrease position orders.
18//! - GLV (GMX Liquidity Vault) Action accounts: Accounts that track user interactions with GLV tokens.
19//!   - [`GlvDeposit`](states::GlvDeposit): Tracks a user's pending deposit of tokens into a GLV pool to mint GLV tokens.
20//!   - [`GlvWithdrawal`](states::GlvWithdrawal): Tracks a user's pending withdrawal of tokens from a GLV pool to burn GLV tokens and withdraw the underlying tokens.
21//!   - [`GlvShift`](states::GlvShift): Tracks a keeper's pending request to rebalance tokens between different market pools within the GLV pool.
22//! - User accounts (see [`UserHeader`](states::UserHeader) for details): Tracks user information including the GT and esGT balances of the user, referral code, and referral relationships.
23//!
24//! The instructions for the store program are categorized into the following sections:
25//!
26//! ## Store
27//!
28//! A [`Store`](states::Store) Account serves as both an authority and a global configuration
29//! storage.
30//!
31//! A store and its associated accounts form a *deployment*. Each deployment operates independently,
32//! allowing multiple instances of the protocol to coexist on-chain (only available when the
33//! `multi-store` feature is enabled).
34//!
35//! #### Instructions for Store Accounts
36//! - [`initialize`](gmsol_store::initialize): Create a new [`Store`](states::Store) account.
37//! - [`transfer_store_authority`]: Transfer the authority of the given store to a new authority.
38//! - [`transfer_receiver`](gmsol_store::transfer_receiver): Set the claimable fee receiver address.
39//! - [`set_token_map`]: Set the token map account to use.
40//!
41//! #### Instructions for Config Management
42//! - [`insert_amount`]: Insert an amount to the global config.
43//! - [`insert_factor`]: Insert a factor to the global config.
44//! - [`insert_address`]: Insert an address to the global config.
45//! - [`insert_order_fee_discount_for_referred_user`]:
46//!   Insert order fee discount for referred user factor to the global config.
47//!
48//! #### Instructions for Feature Management
49//! - [`toggle_feature`]: Enable or disable the given feature.
50//!
51//! ## Role-based Permission Management
52//!
53//! The role-based permission system for each GMSOL deployment is managed through its
54//! [`Store`](states::Store) Account. The permission structure consists of:
55//!
56//! - **Administrator Role**: A single administrator address stored in the `authority` field of the
57//!   [`Store`](states::Store) Account. This address has exclusive rights to modify the permission table
58//!   and use other administrative instructions.
59//!
60//! - **Custom Roles**: A flexible role system stored in the `role` field as a [`RoleStore`](states::RoleStore)
61//!   structure. This allows for granular permission management through custom roles and role assignments.
62//!   Each role can be assigned to multiple addresses.
63//!
64//! #### Instructions for Permission Management
65//! - [`check_admin`](gmsol_store::check_admin): Check whether *the signer* is the admin of the given store.
66//! - [`check_role`](gmsol_store::check_role): Check whether *the signer* has the given role in the given store.
67//! - [`has_admin`](gmsol_store::has_admin): Return whether the given address is the admin of the given store.
68//! - [`has_role`](gmsol_store::has_role): Return whether the given address has the given role in the given store.
69//! - [`enable_role`]: Insert or enable a role for the given store.
70//! - [`disable_role`]: Disable an existing role for the given store.
71//! - [`grant_role`]: Grant a role to the given user in the given store.
72//! - [`revoke_role`]: Revoke a role from the given user in the given store.
73//!
74//! ## Token Config and Oracle Management
75//!
76//! #### Instructions for managing [`TokenConfig`](states::TokenConfig) and token maps.
77//! - [`initialize_token_map`](gmsol_store::initialize_token_map): Initialize a new token map account.
78//!   This is a permissionless instruction.
79//! - [`push_to_token_map`]: Push a new token config for an existing token to the given token map.
80//! - [`push_to_token_map_synthetic`]: Push a new token config for a "synthetic"
81//!   token to the given token map.
82//! - [`toggle_token_config`]: Enable or disable a token config of the given token map.
83//! - [`set_expected_provider`]: Set the expected provider for the given token.
84//! - [`set_feed_config`]: Set the feed config of the given provider for the given token.
85//! - [`is_token_config_enabled`](gmsol_store::is_token_config_enabled): Check if the config for the given token is enabled.
86//! - [`token_expected_provider`](gmsol_store::token_expected_provider): Get the expected provider set for the given token.
87//! - [`token_feed`](gmsol_store::token_feed): Get the feed address of the given provider set for the given token.
88//! - [`token_timestamp_adjustment`](gmsol_store::token_timestamp_adjustment): Get the timestamp adjustment of the given
89//!   provider for the give token.
90//! - [`token_name`](gmsol_store::token_name): Get the name of the given token.
91//! - [`token_decimals`](gmsol_store::token_decimals): Get the token decimals of the given token.
92//! - [`token_precision`](gmsol_store::token_precision): Get the price precision of the given token.
93//!
94//! #### Instructions for [`Oracle`](states::Oracle) accounts
95//! - [`initialize_oracle`](gmsol_store::initialize_oracle): Initialize a new [`Oracle`](states::Oracle) account.
96//! - [`clear_all_prices`]: Clear the prices of the given oracle account.
97//! - [`set_prices_from_price_feed`]: Validate and set prices parsed from the
98//!   provided price feed accounts.
99//! - [`initialize_price_feed`]: Initialize a custom price feed.
100//! - [`update_price_feed_with_chainlink`]: Update a custom Chainlink price feed with Chainlink Data Streams report.
101//!
102//! ## Market Management
103//!
104//! *[See also the module level documentation for Market for details.](states::market)*
105//!
106//! #### Instructions for [`Market`](states::Market) management
107//! - [`initialize_market`]: Initialize a [`Market`](states::Market) account.
108//! - [`toggle_market`]: Enable or disable the given market.
109//! - [`market_transfer_in`]: Transfer tokens into the market and record the amount in its balance.
110//! - [`update_market_config`]: Update an item in the market config.
111//! - [`update_market_config_with_buffer`]: Update the market config with the given
112//!   [`MarketConfigBuffer`](states::market::config::MarketConfigBuffer) account.
113//! - [`get_market_status`](gmsol_store::get_market_status): Calculate the market status with the given prices.
114//! - [`get_market_token_price`](gmsol_store::get_market_token_price): Calculate the market token price the given prices.
115//! - [`toggle_gt_minting`]: Enable or disable GT minting for the given market.
116//!
117//! #### Instructions for [`MarketConfigBuffer`](states::market::config::MarketConfigBuffer) accounts
118//! - [`initialize_market_config_buffer`](gmsol_store::initialize_market_config_buffer): Initialize a market config buffer account.
119//! - [`set_market_config_buffer_authority`](gmsol_store::set_market_config_buffer_authority): Replace the authority of the market
120//!   config buffer account with the new one.
121//! - [`close_market_config_buffer`](gmsol_store::close_market_config_buffer): Close the given market config buffer account.
122//! - [`push_to_market_config_buffer`](gmsol_store::push_to_market_config_buffer): Push config items to the given market config
123//!   buffer account.
124//!
125//! #### Instructions for token accounts
126//! - [`initialize_market_vault`]: Initialize the market vault for the given token.
127//! - [`use_claimable_account`]: Prepare a claimable account to receive tokens during the order execution.
128//! - [`close_empty_claimable_account`]: Close a empty claimble account.
129//! - [`prepare_associated_token_account`](gmsol_store::prepare_associated_token_account): Prepare an ATA.
130//!
131//! ## Exchange
132//! The instructions for providing functionalities as an exchange are as follows:
133//!
134//! #### Instructions for [`Deposit`](states::Deposit)
135//! - [`create_deposit`]: Create a deposit by the owner.
136//! - [`execute_deposit`](gmsol_store::execute_deposit()): Execute a deposit by keepers.
137//! - [`close_deposit`]: Close a deposit, either by the owner or by keepers.
138//!
139//! #### Instructions for [`Withdrawal`](states::Withdrawal)
140//! - [`create_withdrawal`]: Create a withdrawal by the owner.
141//! - [`execute_withdrawal`](gmsol_store::execute_withdrawal()): Execute a withdrawal by keepers.
142//! - [`close_withdrawal`]: Close a withdrawal, either by the owner or by keepers.
143//!
144//! #### Instructions for [`Shift`](states::Shift)
145//! - [`create_shift`]: Create a shift by the owner.
146//! - [`execute_shift`](gmsol_store::execute_shift()): Execute a shift by keepers.
147//! - [`close_shift`]: Close a shift, either by the owner or by keepers.
148//!
149//! #### Instructions for [`Order`](states::Order) and [`Position`](states::Position)
150//! - [`prepare_position`](gmsol_store::prepare_position): Prepare the position account for orders.
151//! - [`prepare_trade_event_buffer`](gmsol_store::prepare_trade_event_buffer): Prepare trade event buffer.
152//! - [`create_order`]: Create an order by the owner.
153//! - [`update_order`](gmsol_store::update_order): Update an order by the owner.
154//! - [`execute_increase_or_swap_order`](gmsol_store::execute_increase_or_swap_order()): Execute an order by keepers.
155//! - [`execute_decrease_order`]: Execute a decrease order by keepers.
156//! - [`close_order`]: Close an order, either by the owner or by keepers.
157//! - [`cancel_order_if_no_position`]: Cancel an order if the position does not exist.
158//! - [`liquidate`]: Perform a liquidation by keepers.
159//! - [`auto_deleverage`]: Perform an ADL by keepers.
160//! - [`update_adl_state`]: Update the ADL state of the market.
161//!
162//! ## GLV (GMX Liquidity Vault) Pools
163//! The instructions for providing functionalities for GLV are as follows:
164//!
165//! #### Instructions for [`Glv`](states::Glv).
166//! - [`initialize_glv`]: Initialize a GLV.
167//! - [`update_glv_market_config`]: Update GLV market config.
168//! - [`toggle_glv_market_flag`]: Toggle flags of GLV market.
169//! - [`update_glv_config`]: Update GLV global config.
170//! - [`insert_glv_market`]: Insert a new market to the GLV.
171//! - [`remove_glv_market`]: Remove a market from the GLV.
172//!
173//! #### Instructions for [`GlvDeposit`](states::GlvDeposit)
174//! - [`create_glv_deposit`]: Create a GLV deposit by the owner.
175//! - [`execute_glv_deposit`]: Execute a GLV deposit by keepers.
176//! - [`close_glv_deposit`]: Close a GLV deposit, either by the owner or by keepers.
177//!
178//! #### Instructions for [`GlvWithdrawal`](states::glv::GlvWithdrawal)
179//! - [`create_glv_withdrawal`]: Create a GLV withdrawal by the owner.
180//! - [`execute_glv_withdrawal`]: Execute a GLV withdrawal by keepers.
181//! - [`close_glv_withdrawal`]: Close a GLV withdrawal, either by the owner or by keepers.
182//!
183//! #### Instructions for [`GlvShift`](states::glv::GlvShift)
184//! - [`create_glv_shift`]: Create a GLV shift by keepers.
185//! - [`execute_glv_shift`]: Execute a GLV shift by keepers.
186//! - [`close_glv_shift`]: Close a shift by keepers.
187//!
188//! ## User Accounts and Referrals
189//! The instructions for user accounts and referrals are as follows:
190//! - [`prepare_user`](gmsol_store::prepare_user): Prepare a user account.
191//! - [`initialize_referral_code`](gmsol_store::initialize_referral_code): Initialize and set a referral code.
192//! - [`set_referrer`](gmsol_store::set_referrer): Set the referrer.
193//! - [`transfer_referral_code`](gmsol_store::transfer_referral_code): Transfer the referral code to others.
194//! - [`cancel_referral_code_transfer`](gmsol_store::cancel_referral_code_transfer): Cancel the referral code transfer.
195//! - [`accept_referral_code`](gmsol_store::accept_referral_code): Complete the referral code transfer.
196//!
197//! ## GT Model
198//!
199//! *[See also the module level documentation for GT for details.](states::gt)*
200//!
201//! The instructions for GT Model are as follows:
202//! - [`initialize_gt`]: Initialize the GT state.
203//! - [`gt_set_order_fee_discount_factors`]: Set order fee discount factors.
204//! - [`gt_set_referral_reward_factors`]: Set referral reward factors.
205//! - [`gt_set_exchange_time_window`]: Set GT exchange time window.
206//! - [`prepare_gt_exchange_vault`](gmsol_store::prepare_gt_exchange_vault): Prepare current GT exchange vault.
207//! - [`confirm_gt_exchange_vault`]: Confirm GT exchange vault.
208//! - [`request_gt_exchange`](gmsol_store::request_gt_exchange): Request a GT exchange.
209//! - [`close_gt_exchange`]: Close a confirmed GT exchange.
210
211/// Instructions.
212pub mod instructions;
213
214/// States.
215pub mod states;
216
217/// Operations.
218pub mod ops;
219
220/// Constants.
221pub mod constants;
222
223/// Utils.
224pub mod utils;
225
226/// Events.
227pub mod events;
228
229use self::{
230    instructions::*,
231    ops::{
232        deposit::CreateDepositParams,
233        glv::{CreateGlvDepositParams, CreateGlvWithdrawalParams},
234        order::{CreateOrderParams, PositionCutKind},
235        shift::CreateShiftParams,
236        withdrawal::CreateWithdrawalParams,
237    },
238    states::{
239        glv::UpdateGlvParams,
240        market::{config::EntryArgs, status::MarketStatus},
241        order::UpdateOrderParams,
242        token_config::UpdateTokenConfigParams,
243        FactorKey, PriceProviderKind,
244    },
245    utils::internal,
246};
247use anchor_lang::prelude::*;
248use gmsol_model::price::Prices;
249
250#[cfg_attr(test, macro_use)]
251extern crate static_assertions;
252
253declare_id!("Gmso1uvJnLbawvw7yezdfCDcPydwW2s2iqG3w6MDucLo");
254
255#[program]
256/// Instructions definitions of the GMSOL Store Program.
257pub mod gmsol_store {
258
259    use super::*;
260
261    // ===========================================
262    //                   Store
263    // ===========================================
264
265    /// Create a new [`Store`](states::Store) account.
266    ///
267    /// # Accounts
268    /// *[See the documentation for the accounts.](Initialize).*
269    ///
270    /// # Arguments
271    /// - `key`: The name of the store, used as a seed to derive the store account's address.
272    ///   The length must not exceed [`MAX_LEN`](states::Store::MAX_LEN).
273    ///
274    /// # Errors
275    /// - The `key` must be empty unless the `multi-store` feature is enabled
276    /// - The [`payer`](Initialize::payer) must be a signer
277    /// - The [`authority`](Initialize::authority) must be as signer if it is provided.
278    /// - The [`receiver`](Initialize::receiver) must be as signer if it is provided.
279    /// - The [`holding`](Initialize::holding) must be as signer if it is provided.
280    /// - The [`store`](Initialize::store) must not be initialized
281    /// - The [`store`](Initialize::store) address must match the PDA derived from
282    ///   the seed of [`Store`](states::Store) and the SHA-256 hash of `key`
283    pub fn initialize(ctx: Context<Initialize>, key: String) -> Result<()> {
284        instructions::initialize(ctx, key)
285    }
286
287    /// Update last restarted slot.
288    ///
289    /// # Accounts
290    /// *[See the documentation for the accounts.](UpdateLastRestartedSlot).*
291    ///
292    /// # Errors
293    /// - The [`authority`](UpdateLastRestartedSlot::authority) must be a signer and the current
294    ///   admin of the store.
295    /// - The [`store`](UpdateLastRestartedSlot::store) must be an initialized store account
296    ///   owned by the store program.
297    #[access_control(internal::Authenticate::only_admin(&ctx))]
298    pub fn update_last_restarted_slot(ctx: Context<UpdateLastRestartedSlot>) -> Result<()> {
299        instructions::update_last_restarted_slot(ctx)
300    }
301
302    /// Request to transfer the authority (admin) of the given store to a new address.
303    /// # Note
304    /// This instruction only sets `next_authority`. Use [`accept_store_authority`] to
305    /// complete the transfer.
306    ///
307    /// # Accounts
308    /// *[See the documentation for the accounts.](TransferStoreAuthority).*
309    ///
310    /// # Errors
311    /// - The [`authority`](TransferStoreAuthority::authority) must be a signer and the current
312    ///   admin of the store.
313    /// - The [`store`](TransferStoreAuthority::store) must be an initialized store account
314    ///   owned by the store program.
315    /// - The [`next_authority`](TransferStoreAuthority::next_authority) cannot be the same as
316    ///   current `next_authority`.
317    #[access_control(internal::Authenticate::only_admin(&ctx))]
318    pub fn transfer_store_authority(ctx: Context<TransferStoreAuthority>) -> Result<()> {
319        instructions::unchecked_transfer_store_authority(ctx)
320    }
321
322    /// Accept the transfer of the authority (admin) of the given store.
323    ///
324    /// # Accounts
325    /// *[See the documentation for the accounts.](AcceptStoreAuthority).*
326    ///
327    /// # Errors
328    /// - The [`next_authority`](AcceptStoreAuthority::next_authority) must be a signer and the current
329    ///   `next_authority` of the store.
330    /// - The [`store`](TransferStoreAuthority::store) must be an initialized store account
331    ///   owned by the store program.
332    pub fn accept_store_authority(ctx: Context<AcceptStoreAuthority>) -> Result<()> {
333        instructions::accept_store_authority(ctx)
334    }
335
336    /// Request to transfer the receiver address to a new one.
337    /// # Note
338    /// This instruction only sets `next_receiver`. Use [`accept_receiver`] to
339    /// complete the transfer.
340    ///
341    /// # Accounts
342    /// *[See the documentation for the accounts.](TransferReceiver).*
343    ///
344    /// # Errors
345    /// - The [`authority`](TransferReceiver::authority) must be a signer and the current receiver
346    ///   of the given store.
347    /// - The [`store`](TransferReceiver::store) must be an initialized store account owned by
348    ///   the store program.
349    /// - The new [`next_receiver`](TransferReceiver::next_receiver) account provided cannot be the same as
350    ///   the current `next_receiver`.
351    pub fn transfer_receiver(ctx: Context<TransferReceiver>) -> Result<()> {
352        instructions::transfer_receiver(ctx)
353    }
354
355    /// Accept the transfer of the receiver address of the given store.
356    ///
357    /// # Accounts
358    /// *[See the documentation for the accounts.](AcceptReceiver).*
359    ///
360    /// # Errors
361    /// - The [`next_receiver`](AcceptReceiver::next_receiver) must be a signer and the current
362    ///   `next_receiver` of the store.
363    /// - The [`store`](AcceptReceiver::store) must be an initialized store account
364    ///   owned by the store program.
365    pub fn accept_receiver(ctx: Context<AcceptReceiver>) -> Result<()> {
366        instructions::accept_receiver(ctx)
367    }
368
369    /// Set the token map address for the store.
370    ///
371    /// This instruction allows a MARKET_KEEPER to update which token map account the store uses.
372    /// The token map account contains token configurations and price feed configurations.
373    ///
374    /// We say the token map is *authorized by the store* if the token map address of the store is
375    /// the same as the address of the token map account.
376    ///
377    /// # Accounts
378    /// *[See the documentation for the accounts.](SetTokenMap).*
379    ///
380    /// # Errors
381    /// - The [`authority`](SetTokenMap::authority) must be a signer and have the MARKET_KEEPER
382    ///   role in the store.
383    /// - The [`store`](SetTokenMap::store) must be an initialized store account owned by the
384    ///   store program.
385    /// - The [`token_map`](SetTokenMap::token_map) must be an initialized token map account
386    ///   and owned by the given store.
387    /// - The new token map address cannot be the same as the current one.
388    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
389    pub fn set_token_map(ctx: Context<SetTokenMap>) -> Result<()> {
390        instructions::unchecked_set_token_map(ctx)
391    }
392
393    // ===========================================
394    //      Role-based Permission Management
395    // ===========================================
396
397    /// Return whether the signer is the admin of the given store.
398    ///
399    /// This instruction verifies if the signer has administrator privileges for the given store
400    /// and returns a boolean result.
401    ///
402    /// # Accounts
403    /// *[See the documentation for the accounts.](CheckRole).*
404    ///
405    /// # Returns
406    /// Returns `true` if the signer is the admin, `false` otherwise.
407    ///
408    /// # Errors
409    /// - The [`authority`](CheckRole::authority) must be a signer.
410    /// - The [`store`](CheckRole::store) must be an initialized store account owned by
411    ///   the store program.
412    pub fn check_admin(ctx: Context<CheckRole>) -> Result<bool> {
413        instructions::check_admin(ctx)
414    }
415
416    /// Check that the authority has the given role in the given store.
417    ///
418    /// This instruction verifies if the authority has the specified role in the given store
419    /// and returns a boolean result.
420    ///
421    /// # Accounts
422    /// *[See the documentation for the accounts.](CheckRole).*
423    ///
424    /// # Arguments
425    /// - `role`: The name of the role to check for the authority.
426    ///
427    /// # Returns
428    /// Returns `true` if the authority has the role, `false` otherwise.
429    ///
430    /// # Errors
431    /// - The [`authority`](CheckRole::authority) must be a signer.
432    /// - The [`store`](CheckRole::store) must be an initialized store account owned by
433    ///   the store program.
434    /// - The `role` must exist and be enabled in the store's role configuration.
435    pub fn check_role(ctx: Context<CheckRole>, role: String) -> Result<bool> {
436        instructions::check_role(ctx, role)
437    }
438
439    /// Return whether the given address is the administrator of the given store.
440    ///
441    /// This instruction checks if the provided address has administrator privileges for the given store
442    /// and returns a boolean result.
443    ///
444    /// # Accounts
445    /// *[See the documentation for the accounts.](HasRole).*
446    ///
447    /// # Arguments
448    /// - `authority`: The address to check for administrator privileges.
449    ///
450    /// # Returns
451    /// Returns `true` if the address is the administrator, `false` otherwise.
452    ///
453    /// # Errors
454    /// - The [`store`](HasRole::store) must be an initialized store account owned by
455    ///   the store program.
456    pub fn has_admin(ctx: Context<HasRole>, authority: Pubkey) -> Result<bool> {
457        instructions::has_admin(ctx, authority)
458    }
459
460    /// Return whether the given address has the given role in the given store.
461    ///
462    /// This instruction checks if the provided address has the specified role in the given store
463    /// and returns a boolean result.
464    ///
465    /// # Accounts
466    /// *[See the documentation for the accounts.](HasRole).*
467    ///
468    /// # Arguments
469    /// - `authority`: The address to check for role membership.
470    /// - `role`: The name of the role to check for the authority.
471    ///
472    /// # Returns
473    /// Returns `true` if the address has the specified role, `false` otherwise.
474    ///
475    /// # Errors
476    /// - The [`store`](HasRole::store) must be an initialized store account owned by
477    ///   the store program.
478    /// - The `role` must exist and be enabled in the store's role configuration.
479    pub fn has_role(ctx: Context<HasRole>, authority: Pubkey, role: String) -> Result<bool> {
480        instructions::has_role(ctx, authority, role)
481    }
482
483    /// Insert or enable a role for the given store.
484    ///
485    /// This instruction adds a new role or enables an existing disabled role in the store's role configuration.
486    ///
487    /// # Accounts
488    /// *[See the documentation for the accounts.](EnableRole).*
489    ///
490    /// # Arguments
491    /// - `role`: The name of the role to be added/enabled. The length cannot exceed
492    ///   [`MAX_ROLE_NAME_LEN`](states::roles::MAX_ROLE_NAME_LEN).
493    ///
494    /// # Errors
495    /// - The [`authority`](EnableRole::authority) must be a signer and be the `ADMIN` of the store.
496    /// - The [`store`](EnableRole::store) must be an initialized store account owned by the store program.
497    /// - The `role` name length must not exceed [`MAX_ROLE_NAME_LEN`](states::roles::MAX_ROLE_NAME_LEN).
498    /// - The `role` must not be already enabled.
499    #[access_control(internal::Authenticate::only_admin(&ctx))]
500    pub fn enable_role(ctx: Context<EnableRole>, role: String) -> Result<()> {
501        instructions::unchecked_enable_role(ctx, role)
502    }
503
504    /// Disable an existing role for the given store.
505    ///
506    /// This instruction disables an existing role in the store's role configuration.
507    ///
508    /// # Accounts
509    /// *[See the documentation for the accounts.](DisableRole).*
510    ///
511    /// # Arguments
512    /// - `role`: The name of the role to be disabled.
513    ///
514    /// # Errors
515    /// - The [`authority`](DisableRole::authority) must be a signer and be the `ADMIN` of the store.
516    /// - The [`store`](DisableRole::store) must be an initialized store account owned by the store program.
517    /// - The `role` must be enabled.
518    #[access_control(internal::Authenticate::only_admin(&ctx))]
519    pub fn disable_role(ctx: Context<DisableRole>, role: String) -> Result<()> {
520        instructions::unchecked_disable_role(ctx, role)
521    }
522
523    /// Grant a role to the given user in the given store.
524    ///
525    /// This instruction grants a role to a user in the store's role configuration. If the user already
526    /// has the role, this instruction has no effect.
527    ///
528    /// # Accounts
529    /// *[See the documentation for the accounts.](GrantRole).*
530    ///
531    /// # Arguments
532    /// - `user`: The address of the user to whom the role should be granted.
533    /// - `role`: The name of the role to be granted. Must be an enabled role in the store.
534    ///
535    /// # Errors
536    /// - The [`authority`](GrantRole::authority) must be a signer and be the `ADMIN` of the store.
537    /// - The [`store`](GrantRole::store) must be an initialized store account owned by the store program.
538    /// - The `role` must exist and be enabled in the store's role table.
539    #[access_control(internal::Authenticate::only_admin(&ctx))]
540    pub fn grant_role(ctx: Context<GrantRole>, user: Pubkey, role: String) -> Result<()> {
541        instructions::unchecked_grant_role(ctx, user, role)
542    }
543
544    /// Revoke a role from the given user in the given store.
545    ///
546    /// This instruction revokes a role from a user in the store's role configuration. If the user does
547    /// not have the role, this instruction has no effect.
548    ///
549    /// # Accounts
550    /// *[See the documentation for the accounts.](RevokeRole).*
551    ///
552    /// # Arguments
553    /// - `user`: The address of the user from whom the role should be revoked.
554    /// - `role`: The name of the role to be revoked.
555    ///
556    /// # Errors
557    /// - The [`authority`](RevokeRole::authority) must be a signer and be the `ADMIN` of the store.
558    /// - The [`store`](RevokeRole::store) must be an initialized store account owned by the store program.
559    /// - The `role` must exist in the store's role table.
560    /// - The `user` must exist in the store's member table.
561    #[access_control(internal::Authenticate::only_admin(&ctx))]
562    pub fn revoke_role(ctx: Context<RevokeRole>, user: Pubkey, role: String) -> Result<()> {
563        instructions::unchecked_revoke_role(ctx, user, role)
564    }
565
566    // ===========================================
567    //              Config Management
568    // ===========================================
569
570    /// Insert an amount value into the store's global configuration.
571    ///
572    /// This instruction allows a CONFIG_KEEPER to set or update an amount value in the store's
573    /// configuration. The key must be one of the predefined amount keys.
574    ///
575    /// # Accounts
576    /// *[See the documentation for the accounts.](InsertConfig).*
577    ///
578    /// # Arguments
579    /// - `key`: The configuration key to update. Must be a valid amount key defined in
580    ///   [`AmountKey`](crate::states::AmountKey).
581    /// - `amount`: The amount value to store for this configuration key.
582    ///
583    /// # Errors
584    /// - The [`authority`](InsertConfig::authority) must be a signer and have the CONFIG_KEEPER role
585    ///   in the store.
586    /// - The provided `key` must be defined in [`AmountKey`](crate::states::AmountKey).
587    /// - The store must be initialized and owned by this program.
588    #[access_control(internal::Authenticate::only_config_keeper(&ctx))]
589    pub fn insert_amount(ctx: Context<InsertConfig>, key: String, amount: u64) -> Result<()> {
590        instructions::unchecked_insert_amount(ctx, &key, amount)
591    }
592
593    /// Insert a factor value into the store's global configuration.
594    /// This instruction allows a CONFIG_KEEPER to set or update a factor value in the store's
595    /// configuration. The key must be one of the predefined factor keys.
596    ///
597    /// # Accounts
598    /// *[See the documentation for the accounts.](InsertConfig).*
599    ///
600    /// # Arguments
601    /// - `key`: The configuration key to update. Must be a valid factor key defined in
602    ///   [`FactorKey`](crate::states::FactorKey).
603    /// - `factor`: The factor value to store for this configuration key.
604    ///
605    /// # Errors
606    /// - The [`authority`](InsertConfig::authority) must be a signer and have the CONFIG_KEEPER role
607    ///   in the store.
608    /// - The provided `key` must be defined in [`FactorKey`](crate::states::FactorKey).
609    /// - The store must be initialized and owned by this program.
610    #[access_control(internal::Authenticate::only_config_keeper(&ctx))]
611    pub fn insert_factor(ctx: Context<InsertConfig>, key: String, factor: u128) -> Result<()> {
612        instructions::unchecked_insert_factor(ctx, &key, factor)
613    }
614
615    /// Insert an address value into the store's global configuration.
616    ///
617    /// This instruction allows a CONFIG_KEEPER to set or update an address value in the store's
618    /// configuration. The key must be one of the predefined address keys.
619    ///
620    /// # Accounts
621    /// *[See the documentation for the accounts.](InsertConfig).*
622    ///
623    /// # Arguments
624    /// - `key`: The configuration key to update. Must be a valid address key defined in
625    ///   [`AddressKey`](crate::states::AddressKey).
626    /// - `address`: The address value to store for this configuration key.
627    ///
628    /// # Errors
629    /// - The [`authority`](InsertConfig::authority) must be a signer and have the CONFIG_KEEPER role
630    ///   in the store.
631    /// - The provided `key` must be defined in [`AddressKey`](crate::states::AddressKey).
632    /// - The store must be initialized and owned by this program.
633    #[access_control(internal::Authenticate::only_config_keeper(&ctx))]
634    pub fn insert_address(ctx: Context<InsertConfig>, key: String, address: Pubkey) -> Result<()> {
635        instructions::unchecked_insert_address(ctx, &key, address)
636    }
637
638    /// Insert order fee discount for referred user factor to the global config.
639    ///
640    /// This instruction allows a MARKET_KEEPER to set or update the GT minting cost referred
641    /// discount factor in the store's configuration. This factor determines the discount
642    /// applied to GT minting costs for referred users.
643    ///
644    /// # Accounts
645    /// *[See the documentation for the accounts.](InsertConfig).*
646    ///
647    /// # Arguments
648    /// - `factor`: The discount factor value to set.
649    ///
650    /// # Errors
651    /// - The [`authority`](InsertConfig::authority) must be a signer and have the
652    ///   MARKET_KEEPER role in the store.
653    /// - The store must be initialized and owned by this program.
654    ///
655    /// # Notes
656    /// - While [`insert_factor`] can also modify this value, it requires CONFIG_KEEPER
657    ///   permissions instead of MARKET_KEEPER permissions required by this instruction.
658    /// - The factor is stored under the [`FactorKey::OrderFeeDiscountForReferredUser`] key.
659    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
660    pub fn insert_order_fee_discount_for_referred_user(
661        ctx: Context<InsertConfig>,
662        factor: u128,
663    ) -> Result<()> {
664        let key = FactorKey::OrderFeeDiscountForReferredUser;
665        instructions::unchecked_insert_factor(ctx, &key.to_string(), factor)
666    }
667
668    // ===========================================
669    //             Feature Management
670    // ===========================================
671
672    /// Enable or disable a feature in this deployment.
673    ///
674    /// This instruction allows a FEATURE_KEEPER to toggle specific features on or off by providing
675    /// a domain and action combination. Features are used to control which functionality is available
676    /// in this deployment.
677    ///
678    /// # Accounts
679    /// *[See the documentation for the accounts.](ToggleFeature).*
680    ///
681    /// # Arguments
682    /// - `domain`: The domain part of the feature flag, must be a valid domain defined in
683    ///   [`DomainDisabledFlag`](crate::states::feature::DomainDisabledFlag).
684    /// - `action`: The action part of the feature flag, must be a valid action defined in
685    ///   [`ActionDisabledFlag`](crate::states::feature::ActionDisabledFlag).
686    /// - `enable`: If true, enables the feature. If false, disables it.
687    ///
688    /// # Errors
689    /// - The [`authority`](ToggleFeature::authority) must be a signer and have the
690    ///   FEATURE_KEEPER role in the store.
691    /// - The `domain` must be a valid domain defined in [`DomainDisabledFlag`](crate::states::feature::DomainDisabledFlag).
692    /// - The `action` must be a valid action defined in [`ActionDisabledFlag`](crate::states::feature::ActionDisabledFlag).
693    ///
694    /// # Warnings
695    /// Although we currently do not provide a feature to disable swaps (only a feature to disable swap orders),
696    /// if we were to introduce such a feature, we must be aware that the following operations could still potentially
697    /// result in swaps:
698    /// - (GLV) Deposits
699    /// - (GLV) Withdrawals
700    /// - Swap Orders
701    /// - Increase Orders
702    /// - Decrease Orders
703    ///
704    /// Therefore, to ensure that this feature effectively prevents swaps from occurring, we need to add
705    /// validation of the swap parameters before executing all of these actions to ensure that swaps do not happen.
706    #[access_control(internal::Authenticate::only_feature_keeper(&ctx))]
707    pub fn toggle_feature(
708        ctx: Context<ToggleFeature>,
709        domain: String,
710        action: String,
711        enable: bool,
712    ) -> Result<()> {
713        let domain = domain
714            .parse()
715            .map_err(|_| error!(CoreError::InvalidArgument))?;
716        let action = action
717            .parse()
718            .map_err(|_| error!(CoreError::InvalidArgument))?;
719        instructions::unchecked_toggle_feature(ctx, domain, action, enable)
720    }
721
722    // ===========================================
723    //           Token Config Management
724    // ===========================================
725
726    /// Initialize a new token map account with its store set to [`store`](InitializeTokenMap::store).
727    ///
728    /// Anyone can initialize a token map account without any permissions, but after initialization, only
729    /// addresses authorized by the store can modify this token map (i.e. have the `MARKET_KEEPER` role).
730    ///
731    /// # Accounts
732    /// *[See the documentation for the accounts.](InitializeTokenMap)*
733    ///
734    /// # Errors
735    /// - The [`payer`](InitializeTokenMap::payer) must be a signer.
736    /// - The [`store`](InitializeTokenMap::store) must be an initialized [`Store`](states::Store)
737    ///   account owned by the store program.
738    /// - The [`token_map`](InitializeTokenMap::token_map) must be an uninitialized account.
739    pub fn initialize_token_map(ctx: Context<InitializeTokenMap>) -> Result<()> {
740        instructions::initialize_token_map(ctx)
741    }
742
743    /// Push a new token config to the given token map.
744    ///
745    /// This instruction is used to add or update the token config for an existing token.
746    /// The token's decimals will be automatically set based on the token mint account.
747    ///
748    /// # Accounts
749    /// [*See the documentation for the accounts*](PushToTokenMap).
750    ///
751    /// # Arguments
752    /// - `name`: The token identifier (e.g. "WSOL", "WBTC")
753    /// - `builder`: Configuration builder containing token parameters
754    /// - `enable`: If true, enables this token config after pushing. If false, disables it.
755    /// - `new`: If true, requires this to be a new token config. An error will be returned if
756    ///   a config already exists for this token. If false, allows updating existing configs.
757    ///
758    /// # Errors
759    /// - The [`authority`](PushToTokenMap::authority) must be a signer with the MARKET_KEEPER role
760    /// - The [`store`](PushToTokenMap::store) must be an initialized [`Store`](states::Store)
761    ///   account owned by the store program.
762    /// - The [`token_map`](PushToTokenMap::token_map) must be initialized and owned by the `store`.
763    /// - The [`token`](PushToTokenMap::token) must be a valid SPL token mint account.
764    /// - If `new` is true, the token must not already have a config in the map.
765    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
766    pub fn push_to_token_map(
767        ctx: Context<PushToTokenMap>,
768        name: String,
769        builder: UpdateTokenConfigParams,
770        enable: bool,
771        new: bool,
772    ) -> Result<()> {
773        instructions::unchecked_push_to_token_map(ctx, &name, builder, enable, new)
774    }
775
776    /// Push a new synthetic token config to the given token map.
777    ///
778    /// This instruction allows adding or updating token configurations for synthetic tokens that don't have
779    /// an actual SPL token mint account. Unlike regular tokens where decimals are read from the mint,
780    /// synthetic tokens specify their decimals directly through the `token_decimals` parameter.
781    ///
782    /// # Accounts
783    /// [*See the documentation for the accounts*](PushToTokenMapSynthetic).
784    ///
785    /// # Arguments
786    /// - `name`: The identifier for the synthetic token (e.g. "BTC")
787    /// - `token`: The public key to use as the synthetic token's address
788    /// - `token_decimals`: Number of decimals for the synthetic token's amounts
789    /// - `builder`: Configuration builder containing token parameters
790    /// - `enable`: If true, enables this token config after pushing. If false, disables it.
791    /// - `new`: If true, requires this to be a new token config. An error will be returned if
792    ///   a config already exists for this token. If false, allows updating the existing config.
793    ///
794    /// # Errors
795    /// - The [`authority`](PushToTokenMapSynthetic::authority) must be a signer with the MARKET_KEEPER role.
796    /// - The [`store`](PushToTokenMapSynthetic::store) must be an initialized [`Store`](states::Store)
797    ///   account owned by the store program.
798    /// - The [`token_map`](PushToTokenMapSynthetic::token_map) must be initialized and owned by the `store`.
799    /// - If updating an existing config, the `token_decimals` must match the original value.
800    /// - If `new` is true, the token must not already have a config in the map.
801    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
802    pub fn push_to_token_map_synthetic(
803        ctx: Context<PushToTokenMapSynthetic>,
804        name: String,
805        token: Pubkey,
806        token_decimals: u8,
807        builder: UpdateTokenConfigParams,
808        enable: bool,
809        new: bool,
810    ) -> Result<()> {
811        instructions::unchecked_push_to_token_map_synthetic(
812            ctx,
813            &name,
814            token,
815            token_decimals,
816            builder,
817            enable,
818            new,
819        )
820    }
821
822    /// Enable or disable the config for the given token.
823    ///
824    /// # Accounts
825    /// [*See the documentation for the accounts*](ToggleTokenConfig).
826    ///
827    /// # Arguments
828    /// - `token`: The token whose config will be updated.
829    /// - `enable`: Enable or disable the config.
830    ///
831    /// # Errors
832    /// - The [`authority`](ToggleTokenConfig::authority) must be a signer
833    ///   and a MARKET_KEEPER in the given store.
834    /// - The [`store`](ToggleTokenConfig::store) must be an initialized [`Store`](states::Store)
835    ///   account owned by the store program .
836    /// - The [`token_map`](ToggleTokenConfig::token_map) must be an initialized token map account
837    ///   owned by the `store`.
838    /// - The given `token` must exist in the token map.
839    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
840    pub fn toggle_token_config(
841        ctx: Context<ToggleTokenConfig>,
842        token: Pubkey,
843        enable: bool,
844    ) -> Result<()> {
845        instructions::unchecked_toggle_token_config(ctx, token, enable)
846    }
847
848    /// Set the expected provider for the given token.
849    ///
850    /// # Accounts
851    /// [*See the documentation for the accounts*](SetExpectedProvider).
852    ///
853    /// # Arguments
854    /// - `token`: The token whose config will be updated.
855    /// - `provider`: The provider index to be set as the expected provider
856    ///   for the token. Must be a valid [`PriceProviderKind`] value.
857    ///
858    /// # Errors
859    /// - The [`authority`](SetExpectedProvider::authority) must be a signer
860    ///   and have the MARKET_KEEPER role in the given store.
861    /// - The [`store`](SetExpectedProvider::store) must be an initialized [`Store`](states::Store)
862    ///   account owned by the store program.
863    /// - The [`token_map`](SetExpectedProvider::token_map) must be an initialized token map account
864    ///   owned by the `store`.
865    /// - The given `token` must exist in the token map.
866    /// - The `provider` index must correspond to a valid [`PriceProviderKind`].
867    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
868    pub fn set_expected_provider(
869        ctx: Context<SetExpectedProvider>,
870        token: Pubkey,
871        provider: u8,
872    ) -> Result<()> {
873        instructions::unchecked_set_expected_provider(
874            ctx,
875            token,
876            PriceProviderKind::try_from(provider)
877                .map_err(|_| CoreError::InvalidProviderKindIndex)?,
878        )
879    }
880
881    /// Set the feed config of the given provider for the given token.
882    ///
883    /// # Accounts
884    /// [*See the documentation for the accounts*](SetFeedConfig).
885    ///
886    /// # Arguments
887    /// - `token`: The token whose config will be updated.
888    /// - `provider`: The index of the provider whose feed config will be updated.
889    ///   Must be a valid [`PriceProviderKind`] value.
890    /// - `feed`: The new feed address.
891    /// - `timestamp_adjustment`: The new timestamp adjustment in seconds.
892    ///
893    /// # Errors
894    /// - The [`authority`](SetFeedConfig::authority) must be a signer
895    ///   and a MARKET_KEEPER in the given store.
896    /// - The [`store`](SetFeedConfig::store) must be an initialized [`Store`](states::Store)
897    ///   account owned by the store program.
898    /// - The [`token_map`](SetFeedConfig::token_map) must be an initialized token map account
899    ///   owned by the `store`.
900    /// - The given `token` must exist in the token map.
901    /// - The `provider` index must correspond to a valid [`PriceProviderKind`].
902    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
903    pub fn set_feed_config(
904        ctx: Context<SetFeedConfig>,
905        token: Pubkey,
906        provider: u8,
907        feed: Pubkey,
908        timestamp_adjustment: u32,
909    ) -> Result<()> {
910        instructions::unchecked_set_feed_config(
911            ctx,
912            token,
913            &PriceProviderKind::try_from(provider)
914                .map_err(|_| CoreError::InvalidProviderKindIndex)?,
915            feed,
916            timestamp_adjustment,
917        )
918    }
919
920    /// Return whether the token config is enabled.
921    ///
922    /// # Accounts
923    /// [*See the documentation for the accounts*](ReadTokenMap).
924    ///
925    /// # Arguments
926    /// - `token`: The address of the token to query for.
927    ///
928    /// # Errors
929    /// - The [`token_map`](ReadTokenMap::token_map) must be an initialized token map account
930    ///   owned by the `store`.
931    /// - The given `token` must exist in the token map.
932    ///
933    /// # Returns
934    /// Returns `true` if the token config is enabled, `false` otherwise.
935    pub fn is_token_config_enabled(ctx: Context<ReadTokenMap>, token: Pubkey) -> Result<bool> {
936        instructions::is_token_config_enabled(ctx, &token)
937    }
938
939    /// Get the expected provider of the given token.
940    ///
941    /// # Accounts
942    /// [*See the documentation for the accounts*](ReadTokenMap).
943    ///
944    /// # Arguments
945    /// - `token`: The address of the token to query for.
946    ///
947    /// # Errors
948    /// - The [`token_map`](ReadTokenMap::token_map) must be an initialized token map account
949    ///   owned by the `store`.
950    /// - The given `token` must exist in the token map.
951    ///
952    /// # Returns
953    /// Returns the expected provider kind as a u8 index. See [`PriceProviderKind`] for valid indices.
954    pub fn token_expected_provider(ctx: Context<ReadTokenMap>, token: Pubkey) -> Result<u8> {
955        instructions::token_expected_provider(ctx, &token).map(|kind| kind as u8)
956    }
957
958    /// Get the configured feed of the given token for the provider.
959    ///
960    /// # Accounts
961    /// [*See the documentation for the accounts*](ReadTokenMap).
962    ///
963    /// # Arguments
964    /// - `token`: The address of the token to query for.
965    /// - `provider`: The index of provider to query for. Must be a valid index defined in
966    ///   [`PriceProviderKind`].
967    ///
968    /// # Errors
969    /// - The [`token_map`](ReadTokenMap::token_map) must be an initialized token map account
970    ///   owned by the `store`.
971    /// - The given `token` must exist in the token map.
972    /// - The `provider` must be a valid index defined in [`PriceProviderKind`], otherwise
973    ///   returns [`CoreError::InvalidProviderKindIndex`].
974    ///
975    /// # Returns
976    /// Returns the configured feed address for the given token and provider.
977    pub fn token_feed(ctx: Context<ReadTokenMap>, token: Pubkey, provider: u8) -> Result<Pubkey> {
978        instructions::token_feed(
979            ctx,
980            &token,
981            &PriceProviderKind::try_from(provider)
982                .map_err(|_| CoreError::InvalidProviderKindIndex)?,
983        )
984    }
985
986    /// Get the configured timestamp adjustment of the given token for the provider.
987    ///
988    /// # Accounts
989    /// [*See the documentation for the accounts*](ReadTokenMap).
990    ///
991    /// # Arguments
992    /// - `token`: The address of the token to query for.
993    /// - `provider`: The index of provider to query for. Must be a valid index defined in
994    ///   [`PriceProviderKind`].
995    ///
996    /// # Errors
997    /// - The [`token_map`](ReadTokenMap::token_map) must be an initialized token map account
998    ///   owned by the `store`.
999    /// - The given `token` must exist in the token map.
1000    /// - The `provider` must be a valid index defined in [`PriceProviderKind`], otherwise
1001    ///   returns [`CoreError::InvalidProviderKindIndex`].
1002    ///
1003    /// # Returns
1004    /// Returns the configured timestamp adjustment for the given token and provider.
1005    pub fn token_timestamp_adjustment(
1006        ctx: Context<ReadTokenMap>,
1007        token: Pubkey,
1008        provider: u8,
1009    ) -> Result<u32> {
1010        instructions::token_timestamp_adjustment(
1011            ctx,
1012            &token,
1013            &PriceProviderKind::try_from(provider)
1014                .map_err(|_| CoreError::InvalidProviderKindIndex)?,
1015        )
1016    }
1017
1018    /// Get the name of the token.
1019    ///
1020    /// # Accounts
1021    /// [*See the documentation for the accounts*](ReadTokenMap).
1022    ///
1023    /// # Arguments
1024    /// - `token`: The address of the token to query for.
1025    ///
1026    /// # Errors
1027    /// - The [`token_map`](ReadTokenMap::token_map) must be an initialized token map account
1028    ///   owned by the store program.
1029    /// - The given `token` must exist in the token map.
1030    ///
1031    /// # Returns
1032    /// Returns the configured name string for the given token.
1033    pub fn token_name(ctx: Context<ReadTokenMap>, token: Pubkey) -> Result<String> {
1034        instructions::token_name(ctx, &token)
1035    }
1036
1037    /// Get the decimals of the token.
1038    ///
1039    /// # Accounts
1040    /// [*See the documentation for the accounts*](ReadTokenMap).
1041    ///
1042    /// # Arguments
1043    /// - `token`: The address of the token to query for.
1044    ///
1045    /// # Errors
1046    /// - The [`token_map`](ReadTokenMap::token_map) must be an initialized token map account
1047    ///   owned by the store program.
1048    /// - The given `token` must exist in the token map.
1049    ///
1050    /// # Returns
1051    /// Returns the configured number of decimals for the given token.
1052    pub fn token_decimals(ctx: Context<ReadTokenMap>, token: Pubkey) -> Result<u8> {
1053        instructions::token_decimals(ctx, &token)
1054    }
1055
1056    /// Get the price precision of the token.
1057    ///
1058    /// # Accounts
1059    /// [*See the documentation for the accounts*](ReadTokenMap).
1060    ///
1061    /// # Arguments
1062    /// - `token`: The address of the token to query for.
1063    ///
1064    /// # Errors
1065    /// - The [`token_map`](ReadTokenMap::token_map) must be an initialized token map account
1066    ///   owned by the store program.
1067    /// - The given `token` must exist in the token map.
1068    ///
1069    /// # Returns
1070    /// Returns the configured price precision for the given token.
1071    pub fn token_precision(ctx: Context<ReadTokenMap>, token: Pubkey) -> Result<u8> {
1072        instructions::token_precision(ctx, &token)
1073    }
1074
1075    // ===========================================
1076    //              Oracle Management
1077    // ===========================================
1078
1079    /// Initialize a new oracle account for the given store.
1080    ///
1081    /// This instruction creates a new oracle account that will be owned by the store. The oracle
1082    /// account is used to store price data for tokens configured in the store's token map.
1083    ///
1084    /// # Accounts
1085    /// *[See the documentation for the accounts.](InitializeOracle)*
1086    ///
1087    /// # Errors
1088    /// - The [`store`](InitializeOracle::store) must be an initialized [`Store`](states::Store)
1089    ///   account owned by the store program.
1090    /// - The [`oracle`](InitializeOracle::oracle) account must be uninitialized.
1091    pub fn initialize_oracle(ctx: Context<InitializeOracle>) -> Result<()> {
1092        instructions::initialize_oracle(ctx)
1093    }
1094
1095    /// Clear all prices from the given oracle.
1096    ///
1097    /// This instruction removes all stored price data from the oracle account and resets it to the
1098    /// cleared state. This can be useful when needing to reset price data or when decommissioning an
1099    /// oracle.
1100    ///
1101    /// # Accounts
1102    /// *[See the documentation for the accounts.](ClearAllPrices)*
1103    ///
1104    /// # Errors
1105    /// - The [`authority`](ClearAllPrices::authority) must be a signer and have the ORACLE_CONTROLLER
1106    ///   role in the given store. It must also be the authority of the oracle.
1107    /// - The [`store`](ClearAllPrices::store) must be an initialized store account owned by the
1108    ///   store program.
1109    /// - The [`oracle`](ClearAllPrices::oracle) must be an initialized oracle account owned by
1110    ///   the given store.
1111    #[access_control(internal::Authenticate::only_oracle_controller(&ctx))]
1112    pub fn clear_all_prices(ctx: Context<ClearAllPrices>) -> Result<()> {
1113        instructions::unchecked_clear_all_prices(ctx)
1114    }
1115
1116    /// Set prices from the provided price feeds.
1117    ///
1118    /// This instruction updates token prices in the oracle account using data from configured price feeds.
1119    /// For each token provided, it reads the current price from the corresponding price feed account and
1120    /// stores it in the oracle.
1121    ///
1122    /// # Accounts
1123    /// *[See the documentation for the accounts.](SetPricesFromPriceFeed)*
1124    ///
1125    /// # Arguments
1126    /// - `tokens`: The list of token mint addresses to update prices for. Each token must be configured
1127    ///   in the token map with a valid price feed.
1128    ///
1129    /// # Errors
1130    /// - The [`authority`](SetPricesFromPriceFeed::authority) must be a signer and have the
1131    ///   ORACLE_CONTROLLER role in the given store. It must also be the authority of the `oracle`.
1132    /// - The [`store`](SetPricesFromPriceFeed::store) must be an initialized store account owned by
1133    ///   the store program.
1134    /// - The [`oracle`](SetPricesFromPriceFeed::oracle) must be an initialized oracle account owned
1135    ///   by the given store. It must not have any prices set and be in the cleared state.
1136    /// - The [`token_map`](SetPricesFromPriceFeed::token_map) must be an initialized token map account
1137    ///   that is owned and authorized by the store.
1138    /// - The number of tokens provided cannot exceed [`MAX_TOKENS`](crate::states::oracle::price_map::PriceMap::MAX_TOKENS).
1139    /// - Each token in `tokens` must be configured and enabled in the token map.
1140    /// - For each token, there must be a valid corresponding price feed account included in the remaining accounts.
1141    #[access_control(internal::Authenticate::only_oracle_controller(&ctx))]
1142    pub fn set_prices_from_price_feed<'info>(
1143        ctx: Context<'_, '_, 'info, 'info, SetPricesFromPriceFeed<'info>>,
1144        tokens: Vec<Pubkey>,
1145    ) -> Result<()> {
1146        instructions::unchecked_set_prices_from_price_feed(ctx, tokens)
1147    }
1148
1149    /// Initialize a custom price feed account.
1150    ///
1151    /// Creates a new price feed account that can be used to provide custom price data for a token.
1152    /// The price feed is owned by the store and can only be updated by ORDER_KEEPERs.
1153    ///
1154    /// # Accounts
1155    /// *[See the documentation for the accounts.](InitializePriceFeed)*
1156    ///
1157    /// # Arguments
1158    /// - `index`: The oracle index this price feed will be associated with.
1159    /// - `provider`: The price provider kind index that will be used for this feed. Must be a valid
1160    ///   index from [`PriceProviderKind`] that supports custom price feeds.
1161    /// - `token`: The mint address of the token this price feed will provide prices for.
1162    /// - `feed_id`: The feed ID defined by the price provider.
1163    ///
1164    /// # Errors
1165    /// - The [`authority`](InitializePriceFeed::authority) must be a signer and have the PRICE_KEEPER
1166    ///   role in the store.
1167    /// - The [`store`](InitializePriceFeed::store) must be an initialized store account owned by
1168    ///   the store program.
1169    /// - The [`price_feed`](InitializePriceFeed::price_feed) must be uninitialized and its address
1170    ///   must match the PDA derived from the `store`, `index`, `feed_id`, and other expected seeds.
1171    /// - The `provider` index must correspond to a valid [`PriceProviderKind`] that supports
1172    ///   custom price feeds.
1173    #[access_control(internal::Authenticate::only_price_keeper(&ctx))]
1174    pub fn initialize_price_feed(
1175        ctx: Context<InitializePriceFeed>,
1176        index: u16,
1177        provider: u8,
1178        token: Pubkey,
1179        feed_id: Pubkey,
1180    ) -> Result<()> {
1181        let provider = PriceProviderKind::try_from(provider)
1182            .map_err(|_| error!(CoreError::InvalidProviderKindIndex))?;
1183        instructions::unchecked_initialize_price_feed(ctx, index, provider, &token, &feed_id)
1184    }
1185
1186    /// Updates the price data in a custom price feed account using a signed price report from
1187    /// Chainlink Data Streams. The price feed must be configured to use the Chainlink Data Streams
1188    /// provider.
1189    ///
1190    /// # Accounts
1191    /// *[See the documentation for the accounts.](UpdatePriceFeedWithChainlink)*
1192    ///
1193    /// # Arguments
1194    /// - `signed_report`: A signed price report from Chainlink Data Streams containing the price data.
1195    ///
1196    /// # Errors
1197    /// - The [`authority`](UpdatePriceFeedWithChainlink::authority) must be a signer and have the
1198    ///   PRICE_KEEPER role in the store.
1199    /// - The [`store`](UpdatePriceFeedWithChainlink::store) must be an initialized store account
1200    /// - The [`verifier_account`](UpdatePriceFeedWithChainlink::verifier_account) must be a valid
1201    ///   Chainlink verifier account.
1202    /// - The [`price_feed`](UpdatePriceFeedWithChainlink::price_feed) must be initialized, owned by
1203    ///   the store, and authorized for the `authority`.
1204    /// - The [`chainlink`](UpdatePriceFeedWithChainlink::chainlink) program ID must be trusted in the
1205    ///   definition of the [`ChainlinkDataStreamsInterface`](gmsol_chainlink_datastreams::interface::ChainlinkDataStreamsInterface).
1206    /// - The price feed must be configured to use [`ChainlinkDataStreams`](PriceProviderKind::ChainlinkDataStreams)
1207    ///   as its provider.
1208    /// - The `signed_report` must be:
1209    ///   - Decodable as a valid Chainlink price report
1210    ///   - Verifiable by the Chainlink Verifier Program
1211    ///   - Contain valid data for creating a [`PriceFeedPrice`](states::oracle::PriceFeedPrice)
1212    /// - The current slot and timestamp must be >= the feed's last update.
1213    /// - The price data timestamp must be >= the feed's last price timestamp
1214    /// - The price data must meet all validity requirements (see the `update` method of [`PriceFeed`](states::oracle::PriceFeed)).
1215    #[access_control(internal::Authenticate::only_price_keeper(&ctx))]
1216    pub fn update_price_feed_with_chainlink(
1217        ctx: Context<UpdatePriceFeedWithChainlink>,
1218        compressed_report: Vec<u8>,
1219    ) -> Result<()> {
1220        instructions::unchecked_update_price_feed_with_chainlink(ctx, compressed_report)
1221    }
1222
1223    // ===========================================
1224    //              Market Management
1225    // ===========================================
1226
1227    /// Initialize a [`Market`](states::Market) account.
1228    ///
1229    /// # Accounts
1230    /// [*See the documentation for the accounts.*](InitializeMarket)
1231    ///
1232    /// # Arguments
1233    /// - `index_token_mint`: The address of the index token.
1234    /// - `name`: The name of the market.
1235    /// - `enable`: Whether to enable the market after initialization.
1236    ///
1237    /// # Errors
1238    /// - The [`authority`](InitializeMarket::authority) must be a signer and have the MARKET_KEEPER role
1239    ///   in the store.
1240    /// - The [`store`](InitializeMarket::store) must be initialized.
1241    /// - The [`market_token_mint`](InitializeMarket::market_token_mint) must be uninitialized
1242    ///   and a PDA derived from the expected seeds.
1243    /// - The [`market`](InitializeMarket::market) must be uninitialized and a PDA derived from
1244    ///   the expected seeds (see the documentation for [`market`](InitializeMarket::market) for details).
1245    /// - The [`token_map`](InitializeMarket::token_map) must be initialized and must be owned and
1246    ///   authorized by the `store`.
1247    /// - The [`long_token_vault`](InitializeMarket::long_token_vault) and
1248    ///   [`short_token_vault`](InitializeMarket::short_token_vault) must be initialized
1249    ///   and valid market vault accounts of the store for their respective tokens.
1250    /// - The long and short token mints must be valid Mint accounts.
1251    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
1252    pub fn initialize_market(
1253        ctx: Context<InitializeMarket>,
1254        index_token_mint: Pubkey,
1255        name: String,
1256        enable: bool,
1257    ) -> Result<()> {
1258        instructions::unchecked_initialize_market(ctx, index_token_mint, &name, enable)
1259    }
1260
1261    /// Enable or disable the given market.
1262    ///
1263    /// This instruction allows a MARKET_KEEPER to toggle whether a market is enabled or disabled.
1264    ///
1265    /// # Accounts
1266    /// [*See the documentation for the accounts.*](ToggleMarket)
1267    ///
1268    /// # Arguments
1269    /// - `enable`: Whether to enable (`true`) or disable (`false`) the market.
1270    ///
1271    /// # Errors
1272    /// - The [`authority`](ToggleMarket::authority) must be a signer and have the MARKET_KEEPER
1273    ///   role in the store.
1274    /// - The [`store`](ToggleMarket::store) must be initialized and owned by this program.
1275    /// - The [`market`](ToggleMarket::market) must be initialized and owned by the store.
1276    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
1277    pub fn toggle_market(ctx: Context<ToggleMarket>, enable: bool) -> Result<()> {
1278        instructions::unchecked_toggle_market(ctx, enable)
1279    }
1280
1281    /// Transfer tokens into the market and record the amounts in its balance.
1282    ///
1283    /// This instruction allows a MARKET_KEEPER to transfer tokens from a source account into one of
1284    /// the market vault accounts, updating the market's internal balance tracking.
1285    ///
1286    /// # Accounts
1287    /// [*See the documentation for the accounts.*](MarketTransferIn)
1288    ///
1289    /// # Arguments
1290    /// - `amount`: The amount of tokens to transfer into the market vault.
1291    ///
1292    /// # Errors
1293    /// - The [`authority`](MarketTransferIn::authority) must be a signer and have the MARKET_KEEPER
1294    ///   role in the store.
1295    /// - The [`store`](MarketTransferIn::store) must be an initialized store account owned by this program.
1296    /// - The [`from_authority`](MarketTransferIn::from_authority) must be a signer and have the
1297    ///   permission to transfer.
1298    /// - The [`market`](MarketTransferIn::market) must be an initialized market account owned by the store.
1299    /// - The [`from`](MarketTransferIn::from) must be an initialized token account and cannot be the
1300    ///   same as the destination vault.
1301    /// - The [`vault`](MarketTransferIn::vault) must be an initialized and valid market vault token
1302    ///   account owned by the store. It must have the same mint as the `from` token account.
1303    /// - The market must be enabled and the token being transferred must be one of the market's
1304    ///   configured pool tokens (long token or short token).
1305    /// - The source token account must have sufficient balance for the transfer amount.
1306    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
1307    pub fn market_transfer_in(ctx: Context<MarketTransferIn>, amount: u64) -> Result<()> {
1308        instructions::unchecked_market_transfer_in(ctx, amount)
1309    }
1310
1311    /// Update an item in the market config.
1312    ///
1313    /// This instruction allows a MARKET_KEEPER to update a single configuration value in the market's
1314    /// configuration. The key must be one of the predefined market config keys.
1315    ///
1316    /// # Accounts
1317    /// [*See the documentation for the accounts.*](UpdateMarketConfig)
1318    ///
1319    /// # Arguments
1320    /// - `key`: The configuration key to update. Must be a valid key defined in
1321    ///   [`MarketConfigKey`](states::market::config::MarketConfigKey).
1322    /// - `value`: The new value to set for this configuration key.
1323    ///
1324    /// # Errors
1325    /// - The [`authority`](UpdateMarketConfig::authority) must be a signer and have the MARKET_KEEPER
1326    ///   role in the store.
1327    /// - The [`store`](UpdateMarketConfig::store) must be an initialized store account owned by this program.
1328    /// - The [`market`](UpdateMarketConfig::market) must be an initialized market account owned by the store.
1329    /// - The provided `key` must be defined in [`MarketConfigKey`](states::market::config::MarketConfigKey).
1330    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
1331    pub fn update_market_config(
1332        ctx: Context<UpdateMarketConfig>,
1333        key: String,
1334        value: u128,
1335    ) -> Result<()> {
1336        instructions::unchecked_update_market_config(ctx, &key, value)
1337    }
1338
1339    /// Update a flag in the market config.
1340    ///
1341    /// This instruction allows a MARKET_KEEPER to update a single flag in the market's
1342    /// configuration. The key must be one of the predefined market config flags.
1343    ///
1344    /// # Accounts
1345    /// [*See the documentation for the accounts.*](UpdateMarketConfig)
1346    ///
1347    /// # Arguments
1348    /// - `key`: The flag to update. Must be a valid key defined in
1349    ///   [`MarketConfigFlag`](states::market::config::MarketConfigFlag).
1350    /// - `value`: The new boolean value to set for this flag.
1351    ///
1352    /// # Errors
1353    /// - The [`authority`](UpdateMarketConfig::authority) must be a signer and have the MARKET_KEEPER
1354    ///   role in the store.
1355    /// - The [`store`](UpdateMarketConfig::store) must be an initialized store account owned by this program.
1356    /// - The [`market`](UpdateMarketConfig::market) must be an initialized market account owned by the store.
1357    /// - The provided `key` must be defined in [`MarketConfigFlag`](states::market::config::MarketConfigFlag).
1358    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
1359    pub fn update_market_config_flag(
1360        ctx: Context<UpdateMarketConfig>,
1361        key: String,
1362        value: bool,
1363    ) -> Result<()> {
1364        instructions::unchecked_update_market_config_flag(ctx, &key, value)
1365    }
1366
1367    /// Update the market configuration using a pre-populated
1368    /// [`MarketConfigBuffer`](crate::states::market::config::MarketConfigBuffer) account.
1369    ///
1370    /// This instruction allows a MARKET_KEEPER to update multiple market configuration values at once
1371    /// by applying the changes stored in a buffer account. The buffer must contain valid configuration
1372    /// keys and values.
1373    ///
1374    /// # Accounts
1375    /// [*See the documentation for the accounts.*](UpdateMarketConfigWithBuffer)
1376    ///
1377    /// # Errors
1378    /// - The [`authority`](UpdateMarketConfigWithBuffer::authority) must be a signer and have the
1379    ///   MARKET_KEEPER role in the store.
1380    /// - The [`store`](UpdateMarketConfigWithBuffer::store) must be an initialized store account
1381    ///   owned by this program.
1382    /// - The [`market`](UpdateMarketConfigWithBuffer::market) must be an initialized market account
1383    ///   owned by the store.
1384    /// - The [`buffer`](UpdateMarketConfigWithBuffer::buffer) must be:
1385    ///   - An initialized market config buffer account
1386    ///   - Owned by both the store and the authority
1387    ///   - Not expired
1388    /// - All configuration keys in the buffer must be valid keys defined in
1389    ///   [`MarketConfigKey`](states::market::config::MarketConfigKey).
1390    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
1391    pub fn update_market_config_with_buffer(
1392        ctx: Context<UpdateMarketConfigWithBuffer>,
1393    ) -> Result<()> {
1394        instructions::unchecked_update_market_config_with_buffer(ctx)
1395    }
1396
1397    /// Calculate the current market status.
1398    ///
1399    /// This instruction calculates and returns the current status of a market, including metrics like
1400    /// pool value, PnL, and other key indicators. The calculation can be configured to maximize or
1401    /// minimize certain values based on the provided flags.
1402    ///
1403    /// # Accounts
1404    /// [*See the documentation for the accounts.*](ReadMarket)
1405    ///
1406    /// # Arguments
1407    /// - `prices`: The current unit prices of tokens in the market, used for calculations.
1408    /// - `maximize_pnl`: If true, uses the maximum possible PnL values in calculations.
1409    ///   If false, uses minimum PnL values.
1410    /// - `maximize_pool_value`: If true, uses the maximum possible pool value in calculations.
1411    ///   If false, uses minimum pool value.
1412    ///
1413    /// # Errors
1414    /// - The [`market`](ReadMarket::market) account must be properly initialized.
1415    /// - The provided prices must be non-zero.
1416    /// - Any calculation errors.
1417    pub fn get_market_status(
1418        ctx: Context<ReadMarket>,
1419        prices: Prices<u128>,
1420        maximize_pnl: bool,
1421        maximize_pool_value: bool,
1422    ) -> Result<MarketStatus> {
1423        instructions::get_market_status(ctx, &prices, maximize_pnl, maximize_pool_value)
1424    }
1425
1426    /// Get the current market token price based on the provided token prices and PnL factor.
1427    ///
1428    /// This instruction calculates and returns the current price of the market token, taking into
1429    /// account the provided token prices and PnL factor. The calculation can be configured to
1430    /// maximize certain values based on the provided flag.
1431    ///
1432    /// # Accounts
1433    /// [*See the documentation for the accounts.*](ReadMarketWithToken)
1434    ///
1435    /// # Arguments
1436    /// - `prices`: The current unit prices of tokens in the market, used for calculations.
1437    /// - `pnl_factor`: The PnL factor key to use for price calculations, must be a valid
1438    ///   [`PnlFactorKind`](gmsol_model::PnlFactorKind).
1439    /// - `maximize`: If true, uses the maximum possible values in calculations.
1440    ///   If false, uses minimum values.
1441    ///
1442    /// # Errors
1443    /// - The [`market`](ReadMarketWithToken::market) must be an initialized market account.
1444    /// - The provided prices must be non-zero.
1445    /// - The `pnl_factor` must be a valid [`PnlFactorKind`](gmsol_model::PnlFactorKind).
1446    /// - Any calculation errors.
1447    pub fn get_market_token_price(
1448        ctx: Context<ReadMarketWithToken>,
1449        prices: Prices<u128>,
1450        pnl_factor: String,
1451        maximize: bool,
1452    ) -> Result<u128> {
1453        instructions::get_market_token_price(
1454            ctx,
1455            &prices,
1456            pnl_factor
1457                .parse()
1458                .map_err(|_| error!(CoreError::InvalidArgument))?,
1459            maximize,
1460        )
1461    }
1462
1463    /// Initialize a market config buffer account.
1464    ///
1465    /// This instruction creates a new market config buffer account that can be used to stage market
1466    /// configuration changes before applying them. The buffer has an expiration time after which
1467    /// it cannot be used.
1468    ///
1469    /// # Accounts
1470    /// [*See the documentation for the accounts.*](InitializeMarketConfigBuffer)
1471    ///
1472    /// # Arguments
1473    /// - `expire_after_secs`: The number of seconds after which this buffer account will expire.
1474    ///   Once expired, the buffer can no longer be used and must be closed.
1475    ///
1476    /// # Errors
1477    /// - The [`authority`](InitializeMarketConfigBuffer::authority) must be a signer and will be
1478    ///   set as the owner of the buffer account.
1479    /// - The [`store`](InitializeMarketConfigBuffer::store) must be an initialized store account
1480    ///   owned by the program.
1481    /// - The [`buffer`](InitializeMarketConfigBuffer::buffer) must be an uninitialized account
1482    ///   that will store the market configuration data.
1483    /// - The expiration time must be greater than zero.
1484    pub fn initialize_market_config_buffer(
1485        ctx: Context<InitializeMarketConfigBuffer>,
1486        expire_after_secs: u32,
1487    ) -> Result<()> {
1488        instructions::initialize_market_config_buffer(ctx, expire_after_secs)
1489    }
1490
1491    /// Transfer ownership of a market config buffer account to a new authority.
1492    ///
1493    /// This instruction allows the current authority to transfer ownership of the buffer
1494    /// account to a new authority. After the transfer, only the new authority will be able
1495    /// to modify or close the buffer.
1496    ///
1497    /// # Accounts
1498    /// [*See the documentation for the accounts.*](SetMarketConfigBufferAuthority)
1499    ///
1500    /// # Arguments
1501    /// - `new_authority`: The public key of the new authority that will own the buffer account.
1502    ///
1503    /// # Errors
1504    /// - The [`authority`](SetMarketConfigBufferAuthority::authority) must be a signer
1505    ///   and the current owner of the `buffer` account.
1506    /// - The [`buffer`](SetMarketConfigBufferAuthority::buffer) must be an initialized
1507    ///   market config buffer account.
1508    /// - The `new_authority` cannot be the same as the current authority.
1509    pub fn set_market_config_buffer_authority(
1510        ctx: Context<SetMarketConfigBufferAuthority>,
1511        new_authority: Pubkey,
1512    ) -> Result<()> {
1513        instructions::set_market_config_buffer_authority(ctx, new_authority)
1514    }
1515
1516    /// Close the given market config buffer account and reclaim its rent.
1517    ///
1518    /// This instruction allows the authority to close their market config buffer account
1519    /// and reclaim the rent.
1520    ///
1521    /// # Accounts
1522    /// [*See the documentation for the accounts.*](CloseMarketConfigBuffer)
1523    ///
1524    /// # Errors
1525    /// - The [`authority`](CloseMarketConfigBuffer::authority) must be a signer
1526    ///   and the owner of the `buffer` account.
1527    /// - The [`buffer`](CloseMarketConfigBuffer::buffer) must be an initialized
1528    ///   market config buffer account.
1529    pub fn close_market_config_buffer(ctx: Context<CloseMarketConfigBuffer>) -> Result<()> {
1530        instructions::close_market_config_buffer(ctx)
1531    }
1532
1533    /// Push config items to the given market config buffer account.
1534    ///
1535    /// This instruction allows the authority to add new configuration items to their market
1536    /// config buffer account. The buffer will be reallocated to accommodate the new items,
1537    /// with the authority paying for any additional rent.
1538    ///
1539    /// # Accounts
1540    /// [*See the documentation for the accounts.*](PushToMarketConfigBuffer)
1541    ///
1542    /// # Arguments
1543    /// - `new_configs`: The list of new config items to append to the buffer. Each item
1544    ///   consists of a string key and a factor value.
1545    ///
1546    /// # Errors
1547    /// - The [`authority`](PushToMarketConfigBuffer::authority) must be a signer
1548    ///   and the owner of the `buffer` account.
1549    /// - The [`buffer`](PushToMarketConfigBuffer::buffer) must be an initialized
1550    ///   market config buffer account.
1551    /// - The authority must have enough SOL to pay for any additional rent needed.
1552    /// - The keys in `new_configs` must be valid [`MarketConfigKey`](states::market::config::MarketConfigKey).
1553    pub fn push_to_market_config_buffer(
1554        ctx: Context<PushToMarketConfigBuffer>,
1555        new_configs: Vec<EntryArgs>,
1556    ) -> Result<()> {
1557        instructions::push_to_market_config_buffer(ctx, new_configs)
1558    }
1559
1560    /// Enable or disable GT minting for the given market.
1561    ///
1562    /// This instruction allows a MARKET_KEEPER to control whether GT minting is enabled for the
1563    /// given market. When disabled, users cannot mint new GT tokens through this market.
1564    ///
1565    /// # Accounts
1566    /// [*See the documentation for the accounts.*](ToggleGTMinting)
1567    ///
1568    /// # Arguments
1569    /// - `enable`: Whether to enable (`true`) or disable (`false`) GT minting for the given market.
1570    ///
1571    /// # Errors
1572    /// - The [`authority`](ToggleGTMinting::authority) must be a signer and be a MARKET_KEEPER
1573    ///   in the store.
1574    /// - The [`store`](ToggleGTMinting::store) must be an initialized store account.
1575    /// - The [`market`](ToggleGTMinting::market) must be an initialized market account and owned
1576    ///   by the store.
1577    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
1578    pub fn toggle_gt_minting(ctx: Context<ToggleGTMinting>, enable: bool) -> Result<()> {
1579        instructions::unchecked_toggle_gt_minting(ctx, enable)
1580    }
1581
1582    /// Claim fees from the given market.
1583    ///
1584    /// # Accounts
1585    /// [*See the documentation for the accounts.*](ClaimFeesFromMarket)
1586    ///
1587    /// # Return
1588    /// - Returns the claimed amount in base units of the token.
1589    ///
1590    /// # Errors
1591    /// - The [`authority`](ClaimFeesFromMarket::authority) must be a signer and be the designated
1592    ///   fee receiver in the given store.
1593    /// - The [`store`](ClaimFeesFromMarket::store) must be an initialized [`Store`](crate::states::Store)
1594    ///   account owned by this program.
1595    /// - The [`market`](ClaimFeesFromMarket::market) must be an initialized [`Market`](crate::states::Market)
1596    ///   account owned by this program and associated with the given store.
1597    /// - The token being claimed must be one of the market's configured collateral tokens.
1598    /// - All provided token accounts must match their expected addresses.
1599    /// - The market must maintain valid balance requirements after the claim.
1600    pub fn claim_fees_from_market(ctx: Context<ClaimFeesFromMarket>) -> Result<u64> {
1601        let claimed = instructions::claim_fees_from_market(ctx)?;
1602        Ok(claimed)
1603    }
1604
1605    /// Initialize a new market vault for a specific token.
1606    ///
1607    /// This instruction creates a new vault account that will be used to store tokens for a market.
1608    /// The vault is a PDA (Program Derived Address) account that can only be controlled by this program.
1609    ///
1610    /// # Accounts
1611    /// [*See the documentation for the accounts.*](InitializeMarketVault)
1612    ///
1613    /// # Errors
1614    /// - The [`authority`](InitializeMarketVault::authority) must be a signer and have MARKET_KEEPER
1615    ///   permissions in the store.
1616    /// - The [`store`](InitializeMarketVault::store) must be an initialized store account.
1617    /// - The [`vault`](InitializeMarketVault::vault) must be an uninitialized account and its address
1618    ///   must match the PDA derived from the expected seeds.
1619    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
1620    pub fn initialize_market_vault(ctx: Context<InitializeMarketVault>) -> Result<()> {
1621        instructions::unchecked_initialize_market_vault(ctx)
1622    }
1623
1624    /// Prepare a claimable account to receive tokens during order execution.
1625    ///
1626    /// This instruction serves two purposes:
1627    /// 1. For uninitialized accounts: Creates and prepares the account to receive tokens
1628    /// 2. For initialized accounts: Unlocks the funds for the owner to claim
1629    ///
1630    /// # Accounts
1631    /// [*See the documentation for the accounts.*](UseClaimableAccount)
1632    ///
1633    /// # Arguments
1634    /// - `timestamp`: The timestamp for which the claimable account was created.
1635    /// - `amount`: The token amount to approve for delegation.
1636    ///
1637    /// # Errors
1638    /// - The [`authority`](UseClaimableAccount::authority) must be a signer and have ORDER_KEEPER
1639    ///   permissions in the store.
1640    /// - The [`store`](UseClaimableAccount::store) must be an initialized store account.
1641    /// - The [`account`](UseClaimableAccount::account) must be a PDA derived from
1642    ///   the time window of the `timestamp` and other expected seeds. It can be uninitialized.
1643    /// - If the `account` is initialized, it must be owned by the store.
1644    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
1645    pub fn use_claimable_account(
1646        ctx: Context<UseClaimableAccount>,
1647        timestamp: i64,
1648        amount: u64,
1649    ) -> Result<()> {
1650        instructions::unchecked_use_claimable_account(ctx, timestamp, amount)
1651    }
1652
1653    /// Close an empty claimable account.
1654    ///
1655    /// # Accounts
1656    /// [*See the documentation for the accounts.*](CloseEmptyClaimableAccount)
1657    ///
1658    /// # Arguments
1659    /// - `timestamp`: The timestamp for which the claimable account was created.
1660    ///
1661    /// # Errors
1662    /// - The [`authority`](CloseEmptyClaimableAccount::authority) must be a signer and have ORDER_KEEPER
1663    ///   permissions in the store.
1664    /// - The [`store`](CloseEmptyClaimableAccount::store) must be initialized.
1665    /// - The [`account`](CloseEmptyClaimableAccount::account) must be a PDA derived from
1666    ///   the claimable timestamp and other expected seeds.
1667    /// - The [`account`](CloseEmptyClaimableAccount::account) must be initialized and owned by the store.
1668    /// - The balance of the [`account`](CloseEmptyClaimableAccount::account) must be zero.
1669    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
1670    pub fn close_empty_claimable_account(
1671        ctx: Context<CloseEmptyClaimableAccount>,
1672        timestamp: i64,
1673    ) -> Result<()> {
1674        instructions::unchecked_close_empty_claimable_account(ctx, timestamp)
1675    }
1676
1677    /// Prepare an associated token account.
1678    ///
1679    /// # Accounts
1680    /// *[See the documentation for the accounts.](PrepareAssociatedTokenAccount)*
1681    ///
1682    /// # Errors
1683    /// - The [`payer`](PrepareAssociatedTokenAccount::payer) must be a signer.
1684    /// - The [`mint`](PrepareAssociatedTokenAccount::mint) must be a [`Mint`](anchor_spl::token_interface::Mint)
1685    ///   account that is owned by the given token program.
1686    /// - The [`account`](PrepareAssociatedTokenAccount::account) must be an associated token account
1687    ///   with:
1688    ///   - mint = [`mint`](PrepareAssociatedTokenAccount::mint)
1689    ///   - owner = [`owner`](PrepareAssociatedTokenAccount::owner)
1690    ///   - It can be uninitialized.
1691    pub fn prepare_associated_token_account(
1692        ctx: Context<PrepareAssociatedTokenAccount>,
1693    ) -> Result<()> {
1694        instructions::prepare_associated_token_account(ctx)
1695    }
1696
1697    // ===========================================
1698    //                  Deposit
1699    // ===========================================
1700
1701    /// Create a deposit by the owner.
1702    ///
1703    /// # Accounts
1704    /// *[See the documentation for the accounts.](CreateDeposit)*
1705    ///
1706    /// # Arguments
1707    /// - `nonce`: Nonce bytes used to derive the deposit account address.
1708    /// - `params`: Parameters specifying the deposit details.
1709    ///
1710    /// # Errors
1711    /// This instruction will fail if:
1712    /// - The [`owner`](CreateDeposit::owner) is not a signer or has insufficient balance
1713    ///   for the execution fee and rent.
1714    /// - The [`store`](CreateDeposit::store) is not properly initialized.
1715    /// - The [`market`](CreateDeposit::market) is not initialized, not owned by the store,
1716    ///   or is disabled.
1717    /// - The [`deposit`](CreateDeposit::deposit) account is already initialized or is not
1718    ///   a valid PDA derived from the provided nonce and other expected seeds.
1719    /// - The [`market_token`](CreateDeposit::market_token) is not the market token of `market`.
1720    /// - Any required escrow account is not properly initialized or owned by the `deposit`.
1721    /// - Any source account has insufficient balance, does not match the initial tokens, or the
1722    ///   `owner` does not have the permission to transfer the tokens.
1723    /// - The remaining accounts do not form valid swap paths or reference disabled markets.
1724    pub fn create_deposit<'info>(
1725        mut ctx: Context<'_, '_, 'info, 'info, CreateDeposit<'info>>,
1726        nonce: [u8; 32],
1727        params: CreateDepositParams,
1728    ) -> Result<()> {
1729        internal::Create::create(&mut ctx, &nonce, &params)
1730    }
1731
1732    /// Close a deposit, either by the owner or by keepers.
1733    ///
1734    /// # Accounts
1735    /// *[See the documentation for the accounts.](CloseDeposit)*
1736    ///
1737    /// # Arguments
1738    /// - `reason`: The reason for closing the deposit.
1739    ///
1740    /// # Errors
1741    /// This instruction will fail if:
1742    /// - The [`executor`](CloseDeposit::executor) is not a signer or is neither the deposit
1743    ///   owner nor an ORDER_KEEPER in the store.
1744    /// - The [`store`](CloseDeposit::store) is not properly initialized.
1745    /// - The [`owner`](CloseDeposit::owner) does not match the deposit's owner.
1746    /// - The provided token mint accounts do not match those recorded in the `deposit`.
1747    /// - The [`deposit`](CloseDeposit::deposit) is not initialized, not owned by the store,
1748    ///   or not owned by the specified owner.
1749    /// - Any escrow account is not owned by the `deposit` or does not match the `deposit` records.
1750    /// - Any associated token account address is invalid.
1751    /// - The deposit is not in a cancelled or completed state when closed by a non-owner.
1752    pub fn close_deposit<'info>(
1753        ctx: Context<'_, '_, 'info, 'info, CloseDeposit<'info>>,
1754        reason: String,
1755    ) -> Result<()> {
1756        internal::Close::close(&ctx, &reason)
1757    }
1758
1759    /// Execute a deposit by keepers.
1760    ///
1761    /// # Accounts
1762    /// *[See the documentation for the accounts.](ExecuteDeposit)*
1763    ///
1764    /// # Arguments
1765    /// - `execution_fee`: The execution fee claimed to be used by the keeper.
1766    /// - `throw_on_execution_error`: If true, throws an error if execution fails. If false,
1767    ///   the deposit will be cancelled instead.
1768    ///
1769    /// # Errors
1770    /// This instruction will fail if:
1771    /// - The [`authority`](ExecuteDeposit::authority) is not a signer or is not an ORDER_KEEPER
1772    ///   in the store.
1773    /// - The [`store`](ExecuteDeposit::store) is not properly initialized.
1774    /// - The [`token_map`](ExecuteDeposit::token_map) is not initialized or not authorized by
1775    ///   the store.
1776    /// - The [`oracle`](ExecuteDeposit::oracle) is not initialized, cleared and owned by the
1777    ///   store.
1778    /// - The [`market`](ExecuteDeposit::market) is not initialized, is disabled, not owned by
1779    ///   the store, or does not match the market recorded in the `deposit`.
1780    /// - The [`deposit`](ExecuteDeposit::deposit) is not initialized, not owned by the store,
1781    ///   or not in the pending state.
1782    /// - Any token mint accounts do not match those recorded in the `deposit`.
1783    /// - Any escrow accounts are not properly owned or not recorded in the `deposit`.
1784    /// - Any vault accounts are not valid market vaults or do not correspond to the initial tokens.
1785    /// - Any feed accounts in the remaining accounts are invalid or do not match the swap parameters.
1786    /// - Any market accounts in the remaining accounts are disabled, not owned by the store,
1787    ///   or do not match the swap parameters.
1788    /// - Any oracle prices from the feed accounts are incomplete or invalid.
1789    /// - The execution fails and `throw_on_execution_error` is set to `true`.
1790    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
1791    pub fn execute_deposit<'info>(
1792        ctx: Context<'_, '_, 'info, 'info, ExecuteDeposit<'info>>,
1793        execution_fee: u64,
1794        throw_on_execution_error: bool,
1795    ) -> Result<()> {
1796        instructions::unchecked_execute_deposit(ctx, execution_fee, throw_on_execution_error)
1797    }
1798
1799    // ===========================================
1800    //                 Withdrawal
1801    // ===========================================
1802
1803    /// Create a withdrawal by the owner.
1804    ///
1805    /// # Accounts
1806    /// *[See the documentation for the accounts.](CreateWithdrawal)*
1807    ///
1808    /// # Arguments
1809    /// - `nonce`: Nonce bytes used to derive the address for the withdrawal.
1810    /// - `params`: Withdrawal Parameters containing the withdrawal configuration.
1811    ///
1812    /// # Errors
1813    /// This instruction will fail if:
1814    /// - The [`owner`](CreateWithdrawal::owner) is not a signer or has insufficient balance
1815    ///   for the execution fee and rent.
1816    /// - The [`store`](CreateWithdrawal::store) is not properly initialized.
1817    /// - The [`market`](CreateWithdrawal::market) is not initialized, is disabled, or not owned
1818    ///   by the store.
1819    /// - The [`withdrawal`](CreateWithdrawal::withdrawal) is already initialized or is not a valid
1820    ///   PDA derived from the provided `nonce` and expected seeds.
1821    /// - The [`market_token`](CreateWithdrawal::market_token) does not match the market token
1822    ///   of the specified market.
1823    /// - Any required escrow accounts are not properly initialized or not owned by the `withdrawal`.
1824    /// - The source market token account has insufficient balance, or the `owner` does not have the
1825    ///   permission to transfer the tokens.
1826    /// - Any market accounts in the remaining accounts are disabled, not owned by the store,
1827    ///   or do not form valid swap paths.
1828    pub fn create_withdrawal<'info>(
1829        mut ctx: Context<'_, '_, 'info, 'info, CreateWithdrawal<'info>>,
1830        nonce: [u8; 32],
1831        params: CreateWithdrawalParams,
1832    ) -> Result<()> {
1833        internal::Create::create(&mut ctx, &nonce, &params)
1834    }
1835
1836    /// Close a withdrawal, either by the owner or by keepers.
1837    ///
1838    /// # Accounts
1839    /// *[See the documentation for the accounts.](CloseWithdrawal)*
1840    ///
1841    /// # Arguments
1842    /// - `reason`: The reason for closing the withdrawal.
1843    ///
1844    /// # Errors
1845    /// This instruction will fail if:
1846    /// - The [`executor`](CloseWithdrawal::executor) is not a signer or is neither the withdrawal
1847    ///   owner nor an ORDER_KEEPER in the store.
1848    /// - The [`store`](CloseWithdrawal::store) is not properly initialized.
1849    /// - The [`owner`](CloseWithdrawal::owner) does not match the withdrawal owner.
1850    /// - The token mint accounts do not match those recorded in the `withdrawal`.
1851    /// - The [`withdrawal`](CloseWithdrawal::withdrawal) is not initialized, not owned by the store,
1852    ///   or not owned by the specified `owner`.
1853    /// - Any required escrow accounts are not properly initialized or not owned by the `withdrawal`.
1854    /// - Any associated token accounts have invalid addresses.
1855    /// - The withdrawal is not in a cancelled or completed state when the executor is not the owner
1856    pub fn close_withdrawal<'info>(
1857        ctx: Context<'_, '_, 'info, 'info, CloseWithdrawal<'info>>,
1858        reason: String,
1859    ) -> Result<()> {
1860        internal::Close::close(&ctx, &reason)
1861    }
1862
1863    /// Execute a withdrawal by keepers.
1864    ///
1865    /// # Accounts
1866    /// *[See the documentation for the accounts.](ExecuteWithdrawal)*
1867    ///
1868    /// # Arguments
1869    /// - `execution_fee`: The execution fee to be paid to the keeper for executing the withdrawal.
1870    /// - `throw_on_execution_error`: If true, throws an error if execution fails. If false, the
1871    ///   withdrawal will be cancelled instead.
1872    ///
1873    /// # Errors
1874    /// This instruction will fail if:
1875    /// - The [`authority`](ExecuteWithdrawal::authority) is not a signer or is not an ORDER_KEEPER
1876    ///   in the store.
1877    /// - The [`store`](ExecuteWithdrawal::store) is not properly initialized.
1878    /// - The [`token_map`](ExecuteWithdrawal::token_map) is not initialized or not authorized by
1879    ///   the store.
1880    /// - The [`oracle`](ExecuteWithdrawal::oracle) is not initialized, cleared and owned by the
1881    ///   store.
1882    /// - The [`market`](ExecuteWithdrawal::market) is not initialized, is disabled, not owned by
1883    ///   the store, or does not match the market recorded in the `withdrawal`.
1884    /// - The [`withdrawal`](ExecuteWithdrawal::withdrawal) is not initialized, not owned by the
1885    ///   store, or not in the pending state.
1886    /// - Any token mint accounts do not match those recorded in the `withdrawal`.
1887    /// - Any escrow accounts are not properly initialized or not owned by the `withdrawal`.
1888    /// - Any vault accounts are not valid market vaults or do not correspond to the final tokens.
1889    /// - Any feed accounts in the remaining accounts are invalid or do not match the swap parameters.
1890    /// - Any market accounts in the remaining accounts are disabled, not owned by the store, or do
1891    ///   not match the swap parameters.
1892    /// - Any oracle prices from the feed accounts are incomplete or invalid.
1893    /// - The execution fails and `throw_on_execution_error` is set to true.
1894    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
1895    pub fn execute_withdrawal<'info>(
1896        ctx: Context<'_, '_, 'info, 'info, ExecuteWithdrawal<'info>>,
1897        execution_fee: u64,
1898        throw_on_execution_error: bool,
1899    ) -> Result<()> {
1900        instructions::unchecked_execute_withdrawal(ctx, execution_fee, throw_on_execution_error)
1901    }
1902
1903    // ===========================================
1904    //             Order and Position
1905    // ===========================================
1906
1907    /// Prepare the position account for orders.
1908    ///
1909    /// # Accounts
1910    /// *[See the documentation for the accounts.](PreparePosition)*
1911    ///
1912    /// # Arguments
1913    /// - `params`: Order Parameters.
1914    ///
1915    /// # Errors
1916    /// This instruction will fail if:
1917    /// - The [`owner`](PreparePosition::owner) is not a signer or has insufficient balance for the
1918    ///   rent.
1919    /// - The [`store`](PreparePosition::store) is not properly initialized.
1920    /// - The [`market`](PreparePosition::market) is not initialized, is disabled, or not owned by
1921    ///   the `store`.
1922    /// - The [`position`](PreparePosition::position) address is not a valid PDA derived from the
1923    ///   `owner` and expected seeds.
1924    /// - The position account is neither uninitialized nor validly initialized with `store` as the
1925    ///   store and `owner` as the owner.
1926    pub fn prepare_position(
1927        ctx: Context<PreparePosition>,
1928        params: CreateOrderParams,
1929    ) -> Result<()> {
1930        instructions::prepare_position(ctx, &params)
1931    }
1932
1933    /// Create an order by the owner.
1934    ///
1935    /// # Accounts
1936    /// *[See the documentation for the accounts.](CreateOrder)*
1937    ///
1938    /// # Arguments
1939    /// - `nonce`: Nonce bytes used to derive the address for the order.
1940    /// - `params`: Order Parameters specifying the market, order kind, and other details.
1941    ///
1942    /// # Errors
1943    /// This instruction will fail if:
1944    /// - The [`owner`](CreateOrder::owner) is not a signer or has insufficient balance for the
1945    ///   execution fee and rent.
1946    /// - The [`store`](CreateOrder::store) is not properly initialized.
1947    /// - The [`market`](CreateOrder::market) is not initialized, is disabled, or not owned by
1948    ///   the `store`.
1949    /// - The [`user`](CreateOrder::user) is not initialized or does not correspond to the owner.
1950    ///   The address must be a valid PDA derived from the `owner` and expected seeds.
1951    /// - The [`order`](CreateOrder::order) is not uninitialized or the address is not a valid
1952    ///   PDA derived from the `owner`, `nonce` and expected seeds.
1953    /// - For increase/decrease orders:
1954    ///   - The [`position`](CreateOrder::position) is missing, not validly initialized, or not
1955    ///     owned by both the `owner` and `store`.
1956    ///   - The [`long_token`](CreateOrder::long_token) or [`short_token`](CreateOrder::short_token)
1957    ///     are missing, or do not match the those defined in the [`market`](CreateOrder::market).
1958    ///   - The [`long_token_escrow`](CreateOrder::long_token_escrow) or
1959    ///     [`short_token_escrow`](CreateOrder::short_token_escrow) are missing, not valid
1960    ///     escrow accounts for `long_token` or `short_token` respectively, or not owned by the `order`.
1961    /// - For increase/swap orders:
1962    ///   - The [`initial_collateral_token`](CreateOrder::initial_collateral_token) is missing
1963    ///     or invalid.
1964    ///   - The [`initial_collateral_token_escrow`](CreateOrder::initial_collateral_token_escrow)
1965    ///     is missing, not a valid escrow account for `initial_collateral_token`, or not owned by
1966    ///     the `order`.
1967    ///   - The [`initial_collateral_token_source`](CreateOrder::initial_collateral_token_source)
1968    ///     is missing or not a valid source account with `owner` as the authority.
1969    /// - For decrease/swap orders:
1970    ///   - The [`final_output_token`](CreateOrder::final_output_token) is invalid.
1971    ///   - The [`final_output_token_escrow`](CreateOrder::final_output_token_escrow) is missing,
1972    ///     not a valid escrow account for `final_output_token`, or not owned by the `order`.
1973    /// - The feature for creating this kind of order is not enabled.
1974    /// - The remaining market accounts do not match the swap parameters, not all enabled or owned
1975    ///   by the `store`.
1976    pub fn create_order<'info>(
1977        mut ctx: Context<'_, '_, 'info, 'info, CreateOrder<'info>>,
1978        nonce: [u8; 32],
1979        params: CreateOrderParams,
1980    ) -> Result<()> {
1981        internal::Create::create(&mut ctx, &nonce, &params)
1982    }
1983
1984    /// Close an order, either by the owner or by keepers.
1985    ///
1986    /// # Accounts
1987    /// *[See the documentation for the accounts.](CloseOrder)*
1988    ///
1989    /// # Arguments
1990    /// - `reason`: The reason for the close.
1991    ///
1992    /// # Errors
1993    /// - The [`executor`](CloseOrder::executor) must be a signer and either the owner
1994    ///   of the `order` or a ORDER_KEEPER in the store.
1995    /// - The [`store`](CloseOrder::store) must be initialized.
1996    /// - The [`owner`](CloseOrder::owner) must be the owner of the `order`.
1997    /// - The [`user`](CloseOrder::user) must be initialized and correspond to the `owner`.
1998    /// - The [`referrer_user`](CloseOrder::referrer_user) must be present if the `owner` has a
1999    ///   referrer, and it must be initialized and correspond to the referrer of the `owner`.
2000    /// - The [`order`](CloseOrder::order) must be initialized and owned by the `store` and the
2001    ///   `owner`.
2002    /// - The tokens must be those recorded in the `order`.
2003    /// - The escrow accounts must be owned and recorded in the `order`.
2004    /// - The addresses of the ATAs must be valid.
2005    /// - The `order` must be cancelled or completed if the `executor` is not the owner.
2006    /// - The feature must be enabled for closing the given kind of `order`.
2007    pub fn close_order<'info>(
2008        ctx: Context<'_, '_, 'info, 'info, CloseOrder<'info>>,
2009        reason: String,
2010    ) -> Result<()> {
2011        internal::Close::close(&ctx, &reason)
2012    }
2013
2014    /// Cancel order if the corresponding position does not exist.
2015    ///
2016    /// # Accounts
2017    /// *[See the documentation for the accounts.](CancelOrderIfNoPosition)*
2018    ///
2019    /// # Errors
2020    /// - The [`authority`](CancelOrderIfNoPosition::authority) must be a signed ORDER_KEEPER
2021    ///   in the store.
2022    /// - The [`store`](CancelOrderIfNoPosition::authority) must be initialized.
2023    /// - The [`order`](CancelOrderIfNoPosition::order) must be initialized and owned by the
2024    ///   `store`. It must be in the pending state.
2025    /// - The [`position`](CancelOrderIfNoPosition::position) must be recorded in the order.
2026    ///   It must be owned by the system program (i.e., considered to be missing).
2027    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
2028    pub fn cancel_order_if_no_position(ctx: Context<CancelOrderIfNoPosition>) -> Result<()> {
2029        instructions::unchecked_cancel_order_if_no_position(ctx)
2030    }
2031
2032    /// Prepare a trade event buffer.
2033    ///
2034    /// # Accounts
2035    /// *[See the documentation for the accounts.](PrepareTradeEventBuffer)*
2036    ///
2037    /// # Arguments
2038    /// - `index`: The index of the trade event buffer to prepare.
2039    ///
2040    /// # Errors
2041    /// - The [`authority`](PrepareTradeEventBuffer::authority) must be a signer.
2042    /// - The [`store`](PrepareTradeEventBuffer::store) must be initialized.
2043    /// - The [`event`](PrepareTradeEventBuffer::event) must be either:
2044    ///   - Uninitialized, or
2045    ///   - Already initialized with the `authority` as the authority and the `store` as
2046    ///     the store
2047    // Note: There is a false positive lint for the doc link of `event`.
2048    #[allow(rustdoc::broken_intra_doc_links)]
2049    pub fn prepare_trade_event_buffer(
2050        ctx: Context<PrepareTradeEventBuffer>,
2051        index: u16,
2052    ) -> Result<()> {
2053        instructions::prepare_trade_event_buffer(ctx, index)
2054    }
2055
2056    /// Update an order by the owner.
2057    ///
2058    /// # Accounts
2059    /// *[See the documentation for the accounts.](UpdateOrder)*
2060    ///
2061    /// # Arguments
2062    /// - `params`: Update Order Parameters.
2063    ///
2064    /// # Errors
2065    /// - The [`owner`](UpdateOrder::owner) must be a signer and the owner of the `order`.
2066    /// - The [`store`](UpdateOrder::store) must be initialized.
2067    /// - The [`market`](UpdateOrder::market) must be initialized, enabled and owned by the `store`.
2068    /// - The [`order`](UpdateOrder::order) must be:
2069    ///   - Initialized and owned by both the `store` and the `owner`
2070    ///   - Associated with the provided `market`
2071    ///   - In a pending state
2072    ///   - The order type must support updates
2073    /// - The feature must be enabled in the `store` for updating the given kind of `order`.
2074    /// - The updated parameters must be valid for the order type.
2075    pub fn update_order(ctx: Context<UpdateOrder>, params: UpdateOrderParams) -> Result<()> {
2076        instructions::update_order(ctx, &params)
2077    }
2078
2079    /// Execute an increase/swap order by keepers.
2080    ///
2081    /// # Accounts
2082    /// *[See the documentation for the accounts.](ExecuteIncreaseOrSwapOrder)*
2083    ///
2084    /// # Arguments
2085    /// - `recent_timestamp`: A recent timestamp used for deriving the claimable accounts.
2086    /// - `execution_fee`: The execution fee claimed to be used the keeper.
2087    /// - `throw_on_execution_error`: If true, throws an error if order execution fails. If false,
2088    ///   silently cancels the order on execution failure.
2089    ///
2090    /// # Errors
2091    /// - The [`authority`](ExecuteIncreaseOrSwapOrder::authority) must be a signer and have the
2092    ///   ORDER_KEEPER role in the `store`.
2093    /// - The [`store`](ExecuteIncreaseOrSwapOrder::store) must be initialized.
2094    /// - The [`token_map`](ExecuteIncreaseOrSwapOrder::token_map) must be initialized and authorized
2095    ///   by the `store`.
2096    /// - The [`oracle`](ExecuteIncreaseOrSwapOrder::oracle) must be initialized, cleared and owned
2097    ///   by the `store`.
2098    /// - The [`market`](ExecuteIncreaseOrSwapOrder::market) must be initialized, enabled and owned
2099    ///   by the `store`. It must also be associated with the `order`.
2100    /// - The [`owner`](ExecuteIncreaseOrSwapOrder::owner) must be the owner of the `order`.
2101    /// - The [`user`](ExecuteIncreaseOrSwapOrder::user) must be initialized and associated with
2102    ///   the `owner`.
2103    /// - The [`order`](ExecuteIncreaseOrSwapOrder::order) must be:
2104    ///   - Initialized and owned by both the `store` and `owner`
2105    ///   - Associated with the provided `market`
2106    ///   - In a pending state
2107    /// - For increase orders:
2108    ///   - The [`initial_collateral_token`](ExecuteIncreaseOrSwapOrder::initial_collateral_token)
2109    ///     must be valid.
2110    ///   - The [`position`](ExecuteIncreaseOrSwapOrder::position) must exist and be owned by the
2111    ///     `owner` and `store`. It must match the `order`.
2112    ///   - The [`event`](ExecuteIncreaseOrSwapOrder::event) must be a valid trade event buffer owned
2113    ///     by both the `store` and `authority`.
2114    ///   - The [`long_token`](ExecuteIncreaseOrSwapOrder::long_token) and [`short_token`](ExecuteIncreaseOrSwapOrder::short_token)
2115    ///     must match those defined in the `market`.
2116    ///   - The corresponding token escrow and vault accounts must be valid, recorded in the `order`
2117    ///     and owned by the `order`.
2118    /// - For swap orders:
2119    ///   - The [`initial_collateral_token`](ExecuteIncreaseOrSwapOrder::initial_collateral_token)
2120    ///     must be valid.
2121    ///   - The [`final_output_token`](ExecuteIncreaseOrSwapOrder::final_output_token) must be valid.
2122    ///   - The corresponding escrow and vault accounts must be valid, recorded in the `order` and
2123    ///     owned by the `order`.
2124    /// - The remaining accounts must be valid. See the documentation for the accounts for more
2125    ///   details.
2126    /// - The feature for executing this order type must be enabled in the `store`.
2127    /// - If `throw_on_execution_error` is true, any execution failure will throw an error
2128    // Note: There is a false positive lint for the doc link of `event`.
2129    #[allow(rustdoc::broken_intra_doc_links)]
2130    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
2131    pub fn execute_increase_or_swap_order<'info>(
2132        ctx: Context<'_, '_, 'info, 'info, ExecuteIncreaseOrSwapOrder<'info>>,
2133        recent_timestamp: i64,
2134        execution_fee: u64,
2135        throw_on_execution_error: bool,
2136    ) -> Result<()> {
2137        instructions::unchecked_execute_increase_or_swap_order(
2138            ctx,
2139            recent_timestamp,
2140            execution_fee,
2141            throw_on_execution_error,
2142        )
2143    }
2144
2145    /// Execute a decrease order by keepers.
2146    ///
2147    /// # Accounts
2148    /// *[See the documentation for the accounts.](ExecuteDecreaseOrder)*
2149    ///
2150    /// # Arguments
2151    /// - `recent_timestamp`: A timestamp that must be within a recent time window.
2152    /// - `execution_fee`: The execution fee claimed to be used by the keeper.
2153    /// - `throw_on_execution_error`: If true, throws an error if order execution fails. If false,
2154    ///   silently cancels the order on execution failure.
2155    ///
2156    /// # Errors
2157    /// - The [`authority`](ExecuteDecreaseOrder::authority) must be a signer with the ORDER_KEEPER
2158    ///   role in the `store`.
2159    /// - The [`store`](ExecuteDecreaseOrder::store) must be initialized.
2160    /// - The [`token_map`](ExecuteDecreaseOrder::token_map) must be initialized and authorized
2161    ///   by the `store`.
2162    /// - The [`oracle`](ExecuteDecreaseOrder::oracle) must be initialized, cleared and owned
2163    ///   by the `store`.
2164    /// - The [`market`](ExecuteDecreaseOrder::market) must be initialized, enabled and owned
2165    ///   by the `store`.
2166    /// - The [`owner`](ExecuteDecreaseOrder::owner) must be the owner of the `order`.
2167    /// - The [`user`](ExecuteDecreaseOrder::user) must be initialized and associated with
2168    ///   the `owner`.
2169    /// - The [`order`](ExecuteDecreaseOrder::order) must be:
2170    ///   - Initialized and owned by both the `store` and `owner`
2171    ///   - Associated with the provided `market`
2172    ///   - In the pending state
2173    /// - The [`position`](ExecuteDecreaseOrder::position) must exist and be validly owned
2174    ///   by the `owner` and `store`. It must match the `order`.
2175    /// - The [`event`](ExecuteDecreaseOrder::event) must be a valid trade event buffer
2176    ///   owned by both the `store` and `authority`.
2177    /// - The tokens must match those recorded in the `order`.
2178    /// - All escrow accounts must be valid, recorded in the `order` and owned by the `order`.
2179    /// - All vault accounts must be valid market vault accounts and owned by the `store`.
2180    /// - All claimable token accounts must be valid and properly delegated to their owners.
2181    /// - The remaining accounts must be valid. See the documentation for the accounts for more
2182    ///   details.
2183    /// - The feature for executing decrease orders must be enabled in the `store`.
2184    /// - If `throw_on_execution_error` is true, any execution failure will throw an error.
2185    // Note: There is a false positive lint for the doc link of `event`.
2186    #[allow(rustdoc::broken_intra_doc_links)]
2187    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
2188    pub fn execute_decrease_order<'info>(
2189        ctx: Context<'_, '_, 'info, 'info, ExecuteDecreaseOrder<'info>>,
2190        recent_timestamp: i64,
2191        execution_fee: u64,
2192        throw_on_execution_error: bool,
2193    ) -> Result<()> {
2194        instructions::unchecked_execute_decrease_order(
2195            ctx,
2196            recent_timestamp,
2197            execution_fee,
2198            throw_on_execution_error,
2199        )
2200    }
2201
2202    /// Perform a liquidation by keepers.
2203    ///
2204    /// # Accounts
2205    /// *[See the documentation for the accounts.](PositionCut)*
2206    ///
2207    /// # Arguments
2208    /// - `nonce`: The nonce used to derive the `order` PDA address.
2209    /// - `recent_timestamp`: A recent timestamp that must be within the valid time window.
2210    /// - `execution_fee`: The execution fee claimed to be used by the keeper.
2211    ///
2212    /// # Errors
2213    /// - The [`authority`](PositionCut::authority) must be a signer with the ORDER_KEEPER
2214    ///   role in the `store`.
2215    /// - The [`owner`](PositionCut::owner) must be the owner of the position being liquidated.
2216    /// - The [`user`](PositionCut::user) must be an initialized user account corresponding to the
2217    ///   `owner`.
2218    /// - The [`store`](PositionCut::store) must be initialized.
2219    /// - The [`token_map`](PositionCut::token_map) must be initialized and authorized by the
2220    ///   `store`.
2221    /// - The [`oracle`](PositionCut::oracle) must be initialized, cleared and owned by the `store`.
2222    /// - The [`market`](PositionCut::market) must be:
2223    ///   - Initialized and enabled
2224    ///   - Owned by the `store`
2225    ///   - Associated with the position being liquidated
2226    /// - The [`order`](PositionCut::order) must be:
2227    ///   - Uninitialized
2228    ///   - Have an address matching the PDA derived from the `store`, `owner`, provided
2229    ///     `nonce` and other expected seeds
2230    /// - The [`position`](PositionCut::position) must be:
2231    ///   - Validly initialized
2232    ///   - Owned by both the `owner` and `store`
2233    ///   - In a liquidatable state
2234    /// - The [`event`](PositionCut::event) must be a valid trade event buffer owned by both the
2235    ///   `store` and `authority`.
2236    /// - The [`long_token`](PositionCut::long_token) and [`short_token`](PositionCut::short_token)
2237    ///   must match those defined in the `market`.
2238    /// - Token escrow accounts must be:
2239    ///   - Valid for their respective tokens
2240    ///   - Owned by the `order`
2241    /// - Market vault accounts must be:
2242    ///   - Valid market vault accounts for their respective tokens
2243    ///   - Owned by the `store`
2244    /// - Claimable token accounts must be:
2245    ///   - Valid for their respective tokens
2246    ///   - Owned by the `store`
2247    ///   - Properly delegated to their owners
2248    /// - Price feed accounts must be:
2249    ///   - Valid and complete
2250    ///   - Provided in order matching the market's sorted token list
2251    /// - The liquidation feature must be enabled in the `store`.
2252    /// - Oracle prices must be valid and complete.
2253    // Note: There is a false positive lint for the doc link of `event`.
2254    #[allow(rustdoc::broken_intra_doc_links)]
2255    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
2256    pub fn liquidate<'info>(
2257        ctx: Context<'_, '_, 'info, 'info, PositionCut<'info>>,
2258        nonce: [u8; 32],
2259        recent_timestamp: i64,
2260        execution_fee: u64,
2261    ) -> Result<()> {
2262        instructions::unchecked_process_position_cut(
2263            ctx,
2264            &nonce,
2265            recent_timestamp,
2266            PositionCutKind::Liquidate,
2267            execution_fee,
2268            true,
2269        )
2270    }
2271
2272    /// Update the ADL (Auto-Deleveraging) state for the market.
2273    ///
2274    /// # Accounts
2275    /// *[See the documentation for the accounts.](UpdateAdlState)*
2276    ///
2277    /// # Arguments
2278    /// - `is_long`: Whether to update the ADL state for the long (`true`) or short (`false`) side
2279    ///   of the market.
2280    ///
2281    /// # Errors
2282    /// - The [`authority`](UpdateAdlState::authority) must be a signer and have the ORDER_KEEPER
2283    ///   role in the store.
2284    /// - The [`store`](UpdateAdlState::store) must be an initialized [`Store`](states::Store)
2285    ///   account owned by the store program.
2286    /// - The [`oracle`](UpdateAdlState::oracle) must be an initialized [`Oracle`](states::Oracle)
2287    ///   account that is owned by the store.
2288    /// - The [`market`](UpdateAdlState::market) must be enabled and owned by the store.
2289    /// - Price feed accounts must be valid and provided in the market's sorted token list order.
2290    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
2291    pub fn update_adl_state<'info>(
2292        ctx: Context<'_, '_, 'info, 'info, UpdateAdlState<'info>>,
2293        is_long: bool,
2294    ) -> Result<()> {
2295        instructions::unchecked_update_adl_state(ctx, is_long)
2296    }
2297
2298    /// Perform an ADL (Auto-Deleveraging) by keepers.
2299    ///
2300    /// # Accounts
2301    /// *[See the documentation for the accounts.](PositionCut)*
2302    ///
2303    /// # Arguments
2304    /// - `nonce`: The nonce used to derive the `order` PDA address.
2305    /// - `recent_timestamp`: A recent blockchain timestamp for validation.
2306    /// - `execution_fee`: The execution fee claimed to be used by the keeper.
2307    ///
2308    /// # Errors
2309    /// - The [`authority`](PositionCut::authority) must be a signer with the ORDER_KEEPER role.
2310    /// - The [`owner`](PositionCut::owner) must be the position owner.
2311    /// - The [`user`](PositionCut::user) must be initialized and corresponding to the `owner`.
2312    /// - The [`store`](PositionCut::store) must be initialized.
2313    /// - The [`token_map`](PositionCut::token_map) must be initialized and authorized by the store.
2314    /// - The [`oracle`](PositionCut::oracle) must be initialized, cleared and store-owned.
2315    /// - The [`market`](PositionCut::market) must be initialized, enabled, store-owned and match
2316    ///   the position's market. The market must be in ADL state.
2317    /// - The [`order`](PositionCut::order) must be uninitialized with address matching PDA from
2318    ///   the `store`, `owner`, `nonce` and other expected seeds.
2319    /// - The [`position`](PositionCut::position) must be initialized, owned by the `owner` and
2320    ///   `store` and eligible for ADL.
2321    /// - The [`event`](PositionCut::event) must be a valid trade event buffer owned by the `store`
2322    ///   and `authority`.
2323    /// - The [`long_token`](PositionCut::long_token) and [`short_token`](PositionCut::short_token)
2324    ///   must match those defined in the `market`.
2325    /// - The [`long_token_escrow`](PositionCut::long_token_escrow) and
2326    ///   [`short_token_escrow`](PositionCut::short_token_escrow) must be valid order-owned escrow
2327    ///   accounts for their respective tokens.
2328    /// - The [`long_token_vault`](PositionCut::long_token_vault) and
2329    ///   [`short_token_vault`](PositionCut::short_token_vault) must be valid store-owned market
2330    ///   vault accounts for their tokens.
2331    /// - The [`claimable_long_token_account_for_user`](PositionCut::claimable_long_token_account_for_user)
2332    ///   must be a store-owned, owner-delegated claimable account for long token.
2333    /// - The [`claimable_short_token_account_for_user`](PositionCut::claimable_short_token_account_for_user)
2334    ///   must be a store-owned, owner-delegated claimable account for short token.
2335    /// - The [`claimable_pnl_token_account_for_holding`](PositionCut::claimable_pnl_token_account_for_holding)
2336    ///   must be a store-owned, holding-delegated claimable account for PnL token.
2337    /// - Price feed accounts must be valid and provided in the market's sorted token list order.
2338    /// - The ADL feature must be enabled in the `store`.
2339    /// - Oracle prices must be valid and complete.
2340    /// - Execution must complete successfully.
2341    // Note: There is a false positive lint for the doc link of `event`.
2342    #[allow(rustdoc::broken_intra_doc_links)]
2343    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
2344    pub fn auto_deleverage<'info>(
2345        ctx: Context<'_, '_, 'info, 'info, PositionCut<'info>>,
2346        nonce: [u8; 32],
2347        recent_timestamp: i64,
2348        size_delta_in_usd: u128,
2349        execution_fee: u64,
2350    ) -> Result<()> {
2351        instructions::unchecked_process_position_cut(
2352            ctx,
2353            &nonce,
2354            recent_timestamp,
2355            PositionCutKind::AutoDeleverage(size_delta_in_usd),
2356            execution_fee,
2357            true,
2358        )
2359    }
2360
2361    // ===========================================
2362    //                  Shift
2363    // ===========================================
2364
2365    /// Create a shift by the owner.
2366    ///
2367    /// # Accounts
2368    /// *[See the documentation for the accounts.](CreateShift)*
2369    ///
2370    /// # Arguments
2371    /// - `nonce`: The nonce used to derive the shift's PDA address.
2372    /// - `params`: The parameters for creating the shift.
2373    ///
2374    /// # Errors
2375    /// - The [`owner`](CreateShift::owner) must be a signer and have sufficient balance for the
2376    ///   execution fee and rent.
2377    /// - The [`store`](CreateShift::store) must be initialized.
2378    /// - The [`from_market`](CreateShift::from_market) must be initialized, enabled
2379    ///   and store-owned.
2380    /// - The [`to_market`](CreateShift::to_market) must be initialized, enabled
2381    ///   and store-owned.
2382    /// - The [`from_market`](CreateShift::from_market) must be shiftable to the
2383    ///   [`to_market`](CreateShift::to_market).
2384    /// - The [`shift`](CreateShift::shift) must be uninitialized. Its address must
2385    ///   match the PDA derived from the expected seeds.
2386    /// - The [`from_market_token`](CreateShift::from_market_token) must be the market
2387    ///   token of the [`from_market`](CreateShift::from_market).
2388    /// - The [`to_market_token`](CreateShift::to_market_token) must be the market
2389    ///   token of the [`to_market`](CreateShift::to_market).
2390    /// - The [`from_market_token_escrow`](CreateShift::from_market_token_escrow) must
2391    ///   be a valid shift-owned escrow account for the
2392    ///   [`from_market_token`](CreateShift::from_market_token).
2393    /// - The [`to_market_token_escrow`](CreateShift::to_market_token_escrow) must be
2394    ///   a valid shift-owned escrow account for the
2395    ///   [`to_market_token`](CreateShift::to_market_token).
2396    /// - The [`from_market_token_source`](CreateShift::from_market_token_source) must
2397    ///   be a token account for [`from_market_token`](CreateShift::from_market_token)
2398    ///   with `owner` as authority.
2399    /// - The [`to_market_token_ata`](CreateShift::to_market_token_ata) must be a valid
2400    ///   associated token account for [`to_market_token`](CreateShift::to_market_token)
2401    ///   owned by `owner`.
2402    pub fn create_shift<'info>(
2403        mut ctx: Context<'_, '_, 'info, 'info, CreateShift<'info>>,
2404        nonce: [u8; 32],
2405        params: CreateShiftParams,
2406    ) -> Result<()> {
2407        internal::Create::create(&mut ctx, &nonce, &params)
2408    }
2409
2410    /// Execute a shift by keepers.
2411    ///
2412    /// # Accounts
2413    /// *[See the documentation for the accounts.](ExecuteShift)*
2414    ///
2415    /// # Arguments
2416    /// - `execution_lamports`: The execution fee in lamports claimed to be used by the keeper.
2417    /// - `throw_on_execution_error`: Whether to throw an error if the execution fails.
2418    ///
2419    /// # Errors
2420    /// - The [`authority`](ExecuteShift::authority) must be a signer and have the ORDER_KEEPER role
2421    ///   in the store.
2422    /// - The [`store`](ExecuteShift::store) must be initialized.
2423    /// - The [`token_map`](ExecuteShift::token_map) must be initialized and authorized by the store.
2424    /// - The [`oracle`](ExecuteShift::oracle) must be initialized, cleared and store-owned.
2425    /// - The [`from_market`](ExecuteShift::from_market) must be initialized, enabled and store-owned.
2426    ///   It must be the from market of the [`shift`](ExecuteShift::shift).
2427    /// - The [`to_market`](ExecuteShift::to_market) must be initialized, enabled and store-owned.
2428    ///   It must be the to market of the [`shift`](ExecuteShift::shift).
2429    /// - The [`from_market`](ExecuteShift::from_market) must be shiftable to the
2430    ///   [`to_market`](ExecuteShift::to_market).
2431    /// - The [`shift`](ExecuteShift::shift) must be initialized, store-owned and in the pending state.
2432    /// - The [`from_market_token`](ExecuteShift::from_market_token) must be the market token of the
2433    ///   [`from_market`](ExecuteShift::from_market).
2434    /// - The [`to_market_token`](ExecuteShift::to_market_token) must be the market token of the
2435    ///   [`to_market`](ExecuteShift::to_market).
2436    /// - The [`from_market_token_escrow`](ExecuteShift::from_market_token_escrow) must be a valid
2437    ///   shift-owned escrow account for the [`from_market_token`](ExecuteShift::from_market_token)
2438    ///   and recorded in the [`shift`](ExecuteShift::shift).
2439    /// - The [`to_market_token_escrow`](ExecuteShift::to_market_token_escrow) must be a valid
2440    ///   shift-owned escrow account for the [`to_market_token`](ExecuteShift::to_market_token)
2441    ///   and recorded in the [`shift`](ExecuteShift::shift).
2442    /// - The [`from_market_token_vault`](ExecuteShift::from_market_token_vault) must be the market
2443    ///   vault for the [`from_market_token`](ExecuteShift::from_market_token) and store-owned.
2444    /// - The feed accounts must be valid and provided in the same order as the unique sorted list
2445    ///   of tokens in the `from_market` and `to_market`.
2446    /// - The oracle prices from the feed accounts must be complete and valid.
2447    /// - If `throw_on_execution_error` is `true`, returns an error if execution fails.
2448    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
2449    pub fn execute_shift<'info>(
2450        ctx: Context<'_, '_, 'info, 'info, ExecuteShift<'info>>,
2451        execution_lamports: u64,
2452        throw_on_execution_error: bool,
2453    ) -> Result<()> {
2454        instructions::unchecked_execute_shift(ctx, execution_lamports, throw_on_execution_error)
2455    }
2456
2457    /// Close a shift, either by the owner or by keepers.
2458    ///
2459    /// # Accounts
2460    /// *[See the documentation for the accounts.](CloseShift)*
2461    ///
2462    /// # Arguments
2463    /// - `reason`: The reason for closing the shift.
2464    ///
2465    /// # Errors
2466    /// - The [`executor`](CloseShift::executor) must be a signer, and either the owner or have
2467    ///   the ORDER_KEEPER role.
2468    /// - The [`store`](CloseShift::store) must be initialized.
2469    /// - The [`owner`](CloseShift::owner) must be the owner of the shift.
2470    /// - The [`shift`](CloseShift::shift) must be initialized and owned by both the `store` and
2471    ///   `owner`.
2472    /// - The [`from_market_token`](CloseShift::from_market_token) and
2473    ///   [`to_market_token`](CloseShift::to_market_token) must be valid and match those recorded
2474    ///   in the [`shift`](CloseShift::shift).
2475    /// - The [`from_market_token_escrow`](CloseShift::from_market_token_escrow) and
2476    ///   [`to_market_token_escrow`](CloseShift::to_market_token_escrow) must be valid escrow
2477    ///   accounts owned by the `shift` and match those recorded in the [`shift`](CloseShift::shift).
2478    /// - The address of the [`from_market_token_ata`](CloseShift::from_market_token_ata) must match
2479    ///   the derived associated token account address for the `from_market_token` and `owner`.
2480    /// - The address of the [`to_market_token_ata`](CloseShift::to_market_token_ata) must match
2481    ///   the derived associated token account address for the `to_market_token` and `owner`.
2482    /// - If the `executor` is not the `owner`, the `shift` must be in either cancelled or completed
2483    ///   state.
2484    pub fn close_shift<'info>(
2485        ctx: Context<'_, '_, 'info, 'info, CloseShift<'info>>,
2486        reason: String,
2487    ) -> Result<()> {
2488        internal::Close::close(&ctx, &reason)
2489    }
2490
2491    // ===========================================
2492    //                The GT Model
2493    // ===========================================
2494
2495    /// Initialize GT Mint.
2496    ///
2497    /// # Accounts
2498    /// *[See the documentation for the accounts.](InitializeGt)*
2499    ///
2500    /// # Arguments
2501    /// - `decimals`: The number of decimal places for the GT token.
2502    /// - `initial_minting_cost`: The initial cost for minting GT.
2503    /// - `grow_factor`: The multiplier that increases minting cost for each step.
2504    /// - `grow_step`: The step size (in GT amount) for minting cost increase.
2505    /// - `ranks`: Array of GT token thresholds that define user rank boundaries.
2506    ///
2507    /// # Errors
2508    /// - The [`authority`](InitializeGt::authority) must be a signer and have the MARKET_KEEPER role in the `store`.
2509    /// - The [`store`](InitializeGt::store) must be properly initialized.
2510    /// - The GT state must not already be initialized.
2511    /// - The arguments must be valid. See `init` method of [`GtState`](states::gt::GtState) for detailed validation logic.
2512    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
2513    pub fn initialize_gt(
2514        ctx: Context<InitializeGt>,
2515        decimals: u8,
2516        initial_minting_cost: u128,
2517        grow_factor: u128,
2518        grow_step: u64,
2519        ranks: Vec<u64>,
2520    ) -> Result<()> {
2521        instructions::unchecked_initialize_gt(
2522            ctx,
2523            decimals,
2524            initial_minting_cost,
2525            grow_factor,
2526            grow_step,
2527            &ranks,
2528        )
2529    }
2530
2531    /// Set order fee discount factors.
2532    ///
2533    /// # Accounts
2534    /// *[See the documentation for the accounts.](ConfigurateGt)*
2535    ///
2536    /// # Arguments
2537    /// - `factors`: The order fee discount factors for each user rank.
2538    ///
2539    /// # Errors
2540    /// - The [`authority`](ConfigurateGt::authority) must be a signer and have the MARKET_KEEPER role in the `store`.
2541    /// - The [`store`](ConfigurateGt::store) must be initialized.
2542    /// - The GT state of the `store` must be initialized.
2543    /// - The number of `factors` must match the number of ranks defined in GT state.
2544    /// - Each factor must be less than or equal to [`MARKET_USD_UNIT`](crate::constants::MARKET_USD_UNIT)(i.e., 100%).
2545    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
2546    pub fn gt_set_order_fee_discount_factors(
2547        ctx: Context<ConfigurateGt>,
2548        factors: Vec<u128>,
2549    ) -> Result<()> {
2550        instructions::unchecked_gt_set_order_fee_discount_factors(ctx, &factors)
2551    }
2552
2553    /// Set referral reward factors.
2554    ///
2555    /// # Accounts
2556    /// *[See the documentation for the accounts.](ConfigurateGt)*
2557    ///
2558    /// # Arguments
2559    /// - `factors`: The referral reward factors for each user rank.
2560    ///
2561    /// # Errors
2562    /// - The [`authority`](ConfigurateGt::authority) must be a signer and a
2563    ///   GT_CONTROLLER in the store.
2564    /// - The [`store`](ConfigurateGt::store) must be initialized.
2565    /// - The GT state of the `store` must be initialized.
2566    /// - The number of `factors` must match the number of ranks defined in GT state.
2567    /// - Each factor must be less than or equal to [`MARKET_USD_UNIT`](crate::constants::MARKET_USD_UNIT)(i.e., 100%).
2568    #[access_control(internal::Authenticate::only_gt_controller(&ctx))]
2569    pub fn gt_set_referral_reward_factors(
2570        ctx: Context<ConfigurateGt>,
2571        factors: Vec<u128>,
2572    ) -> Result<()> {
2573        instructions::unchecked_gt_set_referral_reward_factors(ctx, &factors)
2574    }
2575
2576    /// Set GT exchange time window (in seconds).
2577    ///
2578    /// # Accounts
2579    /// *[See the documentation for the accounts.](ConfigurateGt)*
2580    ///
2581    /// # Arguments
2582    /// - `window`: The time window in seconds for one GT exchange period.
2583    ///
2584    /// # Errors
2585    /// - The [`authority`](ConfigurateGt::authority) must be a signer and have the GT_CONTROLLER role in the `store`.
2586    /// - The [`store`](ConfigurateGt::store) must be properly initialized.
2587    /// - The GT state of the `store` must be initialized.
2588    /// - The `window` must be greater than 0 seconds to ensure a valid exchange period.
2589    #[access_control(internal::Authenticate::only_gt_controller(&ctx))]
2590    pub fn gt_set_exchange_time_window(ctx: Context<ConfigurateGt>, window: u32) -> Result<()> {
2591        cfg_if::cfg_if! {
2592            if #[cfg(feature = "test-only")] {
2593                instructions::unchecked_gt_set_exchange_time_window(ctx, window)
2594            } else {
2595                msg!("Trying to set the GT exchange time window to {}, but this is a test-only instruction", window);
2596                Err(CoreError::Unimplemented.into())
2597            }
2598        }
2599    }
2600
2601    /// Prepare a GT exchange vault.
2602    ///
2603    /// # Accounts
2604    /// *[See the documentation for the accounts.](PrepareGtExchangeVault)*
2605    ///
2606    /// # Arguments
2607    /// - `time_window_index`: The index of the current time window.
2608    /// - `time_window`: The current GT exchange time window in seconds.
2609    ///
2610    /// # Errors
2611    /// - The [`payer`](PrepareGtExchangeVault::payer) must be a signer.
2612    /// - The [`store`](PrepareGtExchangeVault::store) must be properly initialized.
2613    /// - The GT state of the `store` must be initialized.
2614    /// - The [`vault`](PrepareGtExchangeVault::vault) must be either:
2615    ///   - Uninitialized, or
2616    ///   - Properly initialized, owned by the `store`, and have matching `time_window_index`
2617    ///     and `time_window` values
2618    /// - The provided `time_window_index` must match the current time window index.
2619    pub fn prepare_gt_exchange_vault(
2620        ctx: Context<PrepareGtExchangeVault>,
2621        time_window_index: i64,
2622    ) -> Result<()> {
2623        instructions::prepare_gt_exchange_vault(ctx, time_window_index)
2624    }
2625
2626    /// Confirm GT exchange vault.
2627    ///
2628    /// # Accounts
2629    /// *[See the documentation for the accounts.](ConfirmGtExchangeVault)*
2630    ///
2631    /// # Errors
2632    /// - The [`authority`](ConfirmGtExchangeVault::authority) must be a signer and have the GT_CONTROLLER role in the `store`.
2633    /// - The [`store`](ConfirmGtExchangeVault::store) must be properly initialized.
2634    /// - The GT state of the `store` must be initialized.
2635    /// - The [`vault`](ConfirmGtExchangeVault::vault) must be validly initialized and owned by
2636    ///   the `store`.
2637    /// - The `vault` must be in a confirmable state (deposit window has passed but not yet confirmed).
2638    #[access_control(internal::Authenticate::only_gt_controller(&ctx))]
2639    pub fn confirm_gt_exchange_vault(ctx: Context<ConfirmGtExchangeVault>) -> Result<()> {
2640        instructions::unchecked_confirm_gt_exchange_vault(ctx)
2641    }
2642
2643    /// Request a GT exchange.
2644    ///
2645    /// # Accounts
2646    /// *[See the documentation for the accounts.](RequestGtExchange)*
2647    ///
2648    /// # Arguments
2649    /// - `amount`: The amount of GT to exchange for rewards.
2650    ///
2651    /// # Errors
2652    /// - The [`owner`](RequestGtExchange::owner) must be a signer.
2653    /// - The [`store`](RequestGtExchange::store) must be properly initialized with an initialized GT state.
2654    /// - The [`user`](RequestGtExchange::user) must be properly initialized and correspond to the `owner`.
2655    /// - The [`vault`](RequestGtExchange::vault) must be properly initialized, owned by the `store`,
2656    ///   and currently accepting deposits (not yet confirmed).
2657    /// - The [`exchange`](RequestGtExchange::exchange) must be either:
2658    ///   - Uninitialized, or
2659    ///   - Properly initialized and owned by both the `owner` and `vault`
2660    /// - The `amount` must be:
2661    ///   - Greater than 0
2662    ///   - Not exceed the owner's available (excluding reserved) GT balance in their user account
2663    pub fn request_gt_exchange(ctx: Context<RequestGtExchange>, amount: u64) -> Result<()> {
2664        instructions::request_gt_exchange(ctx, amount)
2665    }
2666
2667    /// Close a confirmed GT exchange.
2668    ///
2669    /// # Accounts
2670    /// *[See the documentation for the accounts.](CloseGtExchange)*
2671    ///
2672    /// # Errors
2673    /// - The [`authority`](CloseGtExchange::authority) must be a signer and have the GT_CONTROLLER role in the `store`.
2674    /// - The [`store`](CloseGtExchange::store) must be properly initialized with an initialized GT state.
2675    /// - The [`vault`](CloseGtExchange::vault) must be properly initialized, owned by the `store`,
2676    ///   and confirmed.
2677    /// - The [`exchange`](CloseGtExchange::exchange) must be properly initialized and owned by both
2678    ///   the `owner` and `vault`.
2679    #[access_control(internal::Authenticate::only_gt_controller(&ctx))]
2680    pub fn close_gt_exchange(ctx: Context<CloseGtExchange>) -> Result<()> {
2681        instructions::unchecked_close_gt_exchange(ctx)
2682    }
2683
2684    // ===========================================
2685    //              User & Referral
2686    // ===========================================
2687
2688    /// Initialize or validate a User Account.
2689    ///
2690    /// # Accounts
2691    /// *[See the documentation for the accounts.](PrepareUser)*
2692    ///
2693    /// # Errors
2694    /// - The [`owner`](PrepareUser::owner) must be a signer.
2695    /// - The [`store`](PrepareUser::store) must be properly initialized.
2696    /// - The [`user`](PrepareUser::user) must be either:
2697    ///   - Uninitialized (for new account creation)
2698    ///   - Or validly initialized and correspond to the `owner`
2699    pub fn prepare_user(ctx: Context<PrepareUser>) -> Result<()> {
2700        instructions::prepare_user(ctx)
2701    }
2702
2703    /// Initialize referral code.
2704    ///
2705    /// # Accounts
2706    /// *[See the documentation for the accounts.](InitializeReferralCode)*
2707    ///
2708    /// # Arguments
2709    /// - `code`: The referral code to initialize and associate with the user.
2710    ///
2711    /// # Errors
2712    /// - The [`owner`](InitializeReferralCode::owner) must be a signer.
2713    /// - The [`store`](InitializeReferralCode::store) must be properly initialized.
2714    /// - The [`referral_code`](InitializeReferralCode::referral_code) account must be uninitialized.
2715    /// - The [`user`](InitializeReferralCode::user) account must be:
2716    ///   - Properly initialized
2717    ///   - Correspond to the `owner`
2718    ///   - Not already have an associated referral code
2719    /// - The provided `code` must not already be in use by another user.
2720    pub fn initialize_referral_code(
2721        ctx: Context<InitializeReferralCode>,
2722        code: [u8; 8],
2723    ) -> Result<()> {
2724        instructions::initialize_referral_code(ctx, code)
2725    }
2726
2727    /// Set referrer.
2728    ///
2729    /// # Accounts
2730    /// *[See the documentation for the accounts.](SetReferrer)*
2731    ///
2732    /// # Arguments
2733    /// - `code`: The referral code of the referrer.
2734    ///
2735    /// # Errors
2736    /// - The [`owner`](SetReferrer::owner) must be a signer.
2737    /// - The [`store`](SetReferrer::store) must be properly initialized.
2738    /// - The [`user`](SetReferrer::user) must be:
2739    ///   - Properly initialized
2740    ///   - Correspond to the `owner`
2741    ///   - Must not already have a referrer set
2742    /// - The [`referral_code`](SetReferrer::referral_code) must be:
2743    ///   - Properly initialized
2744    ///   - Owned by the `store`
2745    ///   - Match the provided `code`
2746    ///   - Correspond to the `referrer_user`
2747    /// - The [`referrer_user`](SetReferrer::referrer_user) must be:
2748    ///   - Properly initialized
2749    ///   - Different from the `user`
2750    ///   - Not have the `user` as their referrer (no circular references)
2751    pub fn set_referrer(ctx: Context<SetReferrer>, code: [u8; 8]) -> Result<()> {
2752        instructions::set_referrer(ctx, code)
2753    }
2754
2755    /// Transfer referral code.
2756    ///
2757    /// # Accounts
2758    /// *[See the documentation for the accounts.](TransferReferralCode)*
2759    ///
2760    /// # Errors
2761    /// - The [`owner`](TransferReferralCode::owner) must be a signer.
2762    /// - The [`store`](TransferReferralCode::store) must be properly initialized.
2763    /// - The [`user`](TransferReferralCode::user) account must be:
2764    ///   - Properly initialized
2765    ///   - Correspond to the `owner`
2766    ///   - Different from the [`receiver_user`](TransferReferralCode::receiver_user)
2767    /// - The [`referral_code`](TransferReferralCode::referral_code) account must be:
2768    ///   - Properly initialized
2769    ///   - Owned by the `store`
2770    ///   - Correspond to the `owner`
2771    /// - The [`receiver_user`](TransferReferralCode::receiver_user) account must be:
2772    ///   - Properly initialized
2773    ///   - Not have an associated referral code
2774    pub fn transfer_referral_code(ctx: Context<TransferReferralCode>) -> Result<()> {
2775        instructions::transfer_referral_code(ctx)
2776    }
2777
2778    /// Cancel referral code transfer.
2779    ///
2780    /// # Accounts
2781    /// *[See the documentation for the accounts.](CancelReferralCodeTransfer)*
2782    ///
2783    /// # Errors
2784    /// - The [`owner`](CancelReferralCodeTransfer::owner) must be a signer.
2785    /// - The [`store`](CancelReferralCodeTransfer::store) must be properly initialized.
2786    /// - The [`user`](CancelReferralCodeTransfer::user) account must be:
2787    ///   - Properly initialized
2788    ///   - Correspond to the `owner`
2789    /// - The [`referral_code`](CancelReferralCodeTransfer::referral_code) account must be:
2790    ///   - Properly initialized
2791    ///   - Owned by the `store`
2792    ///   - Correspond to the `owner`
2793    ///   - The next owner must not have been the `owner`
2794    pub fn cancel_referral_code_transfer(ctx: Context<CancelReferralCodeTransfer>) -> Result<()> {
2795        instructions::cancel_referral_code_transfer(ctx)
2796    }
2797
2798    /// Accept referral code.
2799    ///
2800    /// # Accounts
2801    /// *[See the documentation for the accounts.](AcceptReferralCode)*
2802    ///
2803    /// # Errors
2804    /// - The [`next_owner`](AcceptReferralCode::next_owner) must be a signer.
2805    /// - The [`store`](AcceptReferralCode::store) must be properly initialized.
2806    /// - The [`user`](AcceptReferralCode::user) account must be:
2807    ///   - Properly initialized
2808    ///   - Different from the [`receiver_user`](AcceptReferralCode::receiver_user)
2809    /// - The [`referral_code`](AcceptReferralCode::referral_code) account must be:
2810    ///   - Properly initialized
2811    ///   - Owned by the `store`
2812    ///   - Correspond to the owner of the `user`
2813    ///   - Have the next owner be the `next_owner`
2814    /// - The [`receiver_user`](AcceptReferralCode::receiver_user) account must be:
2815    ///   - Properly initialized
2816    ///   - Not have an associated referral code
2817    ///   - Correspond to the `next_owner`
2818    pub fn accept_referral_code(ctx: Context<AcceptReferralCode>) -> Result<()> {
2819        instructions::accept_referral_code(ctx)
2820    }
2821
2822    // ===========================================
2823    //                GLV Operations
2824    // ===========================================
2825
2826    /// Initialize a GLV token and the corresponding GLV account.
2827    ///
2828    /// # Accounts
2829    /// *[See the documentation for the accounts.](InitializeGlv)*
2830    ///
2831    /// # Arguments
2832    /// - `index`: The index of the GLV. Used to derive the GLV token address.
2833    /// - `length`: The number of markets to include in the GLV.
2834    ///
2835    /// # Errors
2836    /// - The [`authority`](InitializeGlv::authority) must be a signer and have
2837    ///   MARKET_KEEPER role in the store.
2838    /// - The [`store`](InitializeGlv::store) must be properly initialized.
2839    /// - The [`glv_token`](InitializeGlv::glv_token) must be:
2840    ///   - Uninitialized
2841    ///   - Address must be PDA derived from [`GLV_TOKEN_SEED`](crate::states::Glv::GLV_TOKEN_SEED),
2842    ///     [`store`] and `index`
2843    /// - The [`glv`](InitializeGlv::glv) must be:
2844    ///   - Uninitialized
2845    ///   - Address must be PDA derived from the SEED of [`Glv`](states::Glv) and the address of the
2846    ///     [`glv_token`](InitializeGlv::glv_token)
2847    /// - The remaining required accounts are documented in [`InitializeGlv`].
2848    /// - The `length` must be:
2849    ///   - Greater than 0
2850    ///   - Less than or equal to [`Glv::MAX_ALLOWED_NUMBER_OF_MARKETS`](crate::states::Glv::MAX_ALLOWED_NUMBER_OF_MARKETS)
2851    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
2852    pub fn initialize_glv<'info>(
2853        ctx: Context<'_, '_, 'info, 'info, InitializeGlv<'info>>,
2854        index: u16,
2855        length: u16,
2856    ) -> Result<()> {
2857        instructions::unchecked_initialize_glv(ctx, index, length as usize)
2858    }
2859
2860    /// Update the config of a market in the given GLV.
2861    ///
2862    /// # Accounts
2863    /// *[See the documentation for the accounts.](UpdateGlvMarketConfig)*
2864    ///
2865    /// # Arguments
2866    /// - `max_amount`: The maximum amount of the market token that can be stored in the GLV.
2867    /// - `max_value`: The maximum value of the market token that can be stored in the GLV.
2868    ///
2869    /// # Errors
2870    /// - The [`authority`](UpdateGlvMarketConfig::authority) must be:
2871    ///   - A signer
2872    ///   - Have MARKET_KEEPER role in the `store`
2873    /// - The [`store`](UpdateGlvMarketConfig::store) must be properly initialized.
2874    /// - The [`glv`](UpdateGlvMarketConfig::glv) must be:
2875    ///   - Properly initialized
2876    ///   - Owned by the `store`
2877    ///   - Have the market token in its list of market tokens
2878    /// - The [`market_token`](UpdateGlvMarketConfig::market_token) must be:
2879    ///   - Properly initialized
2880    ///   - Owned by the `store`
2881    /// - At least one of `max_amount` or `max_value` must be provided
2882    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
2883    pub fn update_glv_market_config(
2884        ctx: Context<UpdateGlvMarketConfig>,
2885        max_amount: Option<u64>,
2886        max_value: Option<u128>,
2887    ) -> Result<()> {
2888        instructions::unchecked_update_glv_market_config(ctx, max_amount, max_value)
2889    }
2890
2891    /// Toggle the given flag of a market in the given GLV.
2892    ///
2893    /// # Accounts
2894    /// *[See the documentation for the accounts.](UpdateGlvMarketConfig)*
2895    ///
2896    /// # Arguments
2897    /// - `flag`: The flag to toggle.
2898    /// - `enable`: The value to toggle to.
2899    ///
2900    /// # Errors
2901    /// - The [`authority`](UpdateGlvMarketConfig::authority) must be:
2902    ///   - A signer
2903    ///   - Have MARKET_KEEPER role in the `store`
2904    /// - The [`store`](UpdateGlvMarketConfig::store) must be properly initialized.
2905    /// - The [`glv`](UpdateGlvMarketConfig::glv) must be:
2906    ///   - Properly initialized
2907    ///   - Owned by the `store`
2908    ///   - Have the market token in its list of market tokens
2909    /// - The [`market_token`](UpdateGlvMarketConfig::market_token) must be:
2910    ///   - Properly initialized
2911    ///   - Owned by the `store`
2912    /// - `flag` must be defined in [`GlvMarketFlag`](crate::states::glv::GlvMarketFlag).
2913    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
2914    pub fn toggle_glv_market_flag(
2915        ctx: Context<UpdateGlvMarketConfig>,
2916        flag: String,
2917        enable: bool,
2918    ) -> Result<()> {
2919        instructions::unchecked_toggle_glv_market_flag(ctx, &flag, enable)
2920    }
2921
2922    /// Update GLV config.
2923    ///
2924    /// # Accounts
2925    /// *[See the documentation for the accounts.](UpdateGlvConfig)*
2926    ///
2927    /// # Arguments
2928    /// - `params`: The update of the config.
2929    ///
2930    /// # Errors
2931    /// - The [`authority`](UpdateGlvConfig::authority) must be:
2932    ///   - A signer
2933    ///   - Have MARKET_KEEPER role in the `store`
2934    /// - The [`store`](UpdateGlvConfig::store) must be properly initialized.
2935    /// - The [`glv`](UpdateGlvConfig::glv) must be:
2936    ///   - Properly initialized
2937    ///   - Owned by the `store`
2938    /// - The `params` must not non-empty.
2939    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
2940    pub fn update_glv_config(ctx: Context<UpdateGlvConfig>, params: UpdateGlvParams) -> Result<()> {
2941        instructions::unchecked_update_glv(ctx, &params)
2942    }
2943
2944    /// Insert a new market to the GLV.
2945    ///
2946    /// # Accounts
2947    /// *[See the documentation for the accounts.](InsertGlvMarket)*
2948    ///
2949    /// # Errors
2950    /// - The [`authority`](InsertGlvMarket::authority) must be:
2951    ///   - A signer
2952    ///   - Have MARKET_KEEPER role in the `store`
2953    /// - The [`store`](InsertGlvMarket::store) must be properly initialized.
2954    /// - The [`glv`](InsertGlvMarket::glv) must be:
2955    ///   - Properly initialized
2956    ///   - Owned by the `store`
2957    /// - The [`market_token`](InsertGlvMarket::market_token) must be:
2958    ///   - A initialized SPL Token / Token-2022 mint
2959    ///   - Have `store` as its mint authority
2960    ///   - Not already contains in the given GLV
2961    /// - The [`market`](InsertGlvMarket::market) must be:
2962    ///   - A initialized market account owned by the `store`
2963    ///   - Must have `market_token` as its market token
2964    ///   - Must have the same long token and short token as the GLV
2965    ///   - Must be enabled
2966    /// - The [`vault`](InsertGlvMarket::vault) must be either:
2967    ///   - The ATA of `market_token` owned by `glv`, or
2968    ///   - Unintialized ATA account of `market_token` owned by `glv`
2969    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
2970    pub fn insert_glv_market(ctx: Context<InsertGlvMarket>) -> Result<()> {
2971        instructions::unchecked_insert_glv_market(ctx)
2972    }
2973
2974    /// Remove a market from the GLV.
2975    ///
2976    /// # Accounts
2977    /// *[See the documentation for the accounts.](RemoveGlvMarket)*
2978    ///
2979    /// # Errors
2980    /// - The [`authority`](RemoveGlvMarket::authority) must:
2981    ///   - Be a signer
2982    ///   - Have MARKET_KEEPER role in the `store`
2983    /// - The [`store`](RemoveGlvMarket::store) must be properly initialized.
2984    /// - The [`glv`](RemoveGlvMarket::glv) must be:
2985    ///   - Properly initialized
2986    ///   - Owned by the `store`
2987    /// - The [`market_token`](RemoveGlvMarket::market_token) must be:
2988    ///   - A initialized SPL Token mint
2989    ///   - Having `store` as its mint authority
2990    ///   - Contained in the given GLV
2991    ///   - Having deposit disabled in the GLV
2992    /// - The [`vault`](RemoveGlvMarket::vault) must be:
2993    ///   - The ATA of `market_token` owned by `glv`
2994    ///   - Having no remaining balance
2995    #[access_control(internal::Authenticate::only_market_keeper(&ctx))]
2996    pub fn remove_glv_market(ctx: Context<RemoveGlvMarket>) -> Result<()> {
2997        instructions::unchecked_remove_glv_market(ctx)
2998    }
2999
3000    /// Create GLV deposit.
3001    ///
3002    /// # Accounts
3003    /// *[See the documentation for the accounts.](CreateGlvDeposit)*
3004    ///
3005    /// # Arguments
3006    /// - `nonce`: A 32-byte used to derive the address of the GLV deposit.
3007    /// - `params`: The parameters for creating the GLV deposit.
3008    ///
3009    /// # Errors
3010    /// - The [`owner`](CreateGlvDeposit::owner) must be a signer and have sufficient balance
3011    ///   for the execution fee and rent.
3012    /// - The [`store`](CreateGlvDeposit::store) must be properly initialized.
3013    /// - The [`market`](CreateGlvDeposit::market) must be:
3014    ///   - Properly initialized
3015    ///   - Owned by the `store`
3016    ///   - Listed in the [`glv`](CreateGlvDeposit::glv)
3017    /// - The [`glv`](CreateGlvDeposit::glv) must be:
3018    ///   - Properly initialized
3019    ///   - Owned by the `store`
3020    /// - The [`glv_deposit`](CreateGlvDeposit::glv_deposit) must be:
3021    ///   - Uninitialized
3022    ///   - Address must be PDA derived from the SEED of [`GlvDeposit`](states::GlvDeposit),
3023    ///     [`store`](CreateGlvDeposit::store), [`owner`](CreateGlvDeposit::owner) and `nonce`
3024    /// - The [`glv_token`](CreateGlvDeposit::glv_token) must be:
3025    ///   - Properly initialized
3026    ///   - Correspond to the provided [`glv`](CreateGlvDeposit::glv)
3027    /// - The [`market_token`](CreateGlvDeposit::market_token) must be:
3028    ///   - Properly initialized
3029    ///   - Correspond to the provided [`market`](CreateGlvDeposit::market)
3030    /// - Token mint account requirements:
3031    ///   - [`initial_long_token`](CreateGlvDeposit::initial_long_token) must be provided if initial long amount > 0
3032    ///   - [`initial_short_token`](CreateGlvDeposit::initial_short_token) must be provided if initial short amount > 0
3033    /// - Escrow account requirements:
3034    ///   - [`glv_token_escrow`](CreateGlvDeposit::glv_token_escrow) must be:
3035    ///     - Owned by the [`glv_deposit`](CreateGlvDeposit::glv_deposit)
3036    ///   - Other escrow accounts must be:
3037    ///     - Provided for any non-zero initial token amounts
3038    ///     - Owned by the [`glv_deposit`](CreateGlvDeposit::glv_deposit)
3039    /// - Source token account requirements:
3040    ///   - Must be provided for any non-zero initial token amounts
3041    ///   - Must have sufficient balance
3042    ///   - Must have the `owner` as its authority
3043    /// - All token programs must match their corresponding token accounts
3044    pub fn create_glv_deposit<'info>(
3045        mut ctx: Context<'_, '_, 'info, 'info, CreateGlvDeposit<'info>>,
3046        nonce: [u8; 32],
3047        params: CreateGlvDepositParams,
3048    ) -> Result<()> {
3049        internal::Create::create(&mut ctx, &nonce, &params)
3050    }
3051
3052    /// Close GLV deposit.
3053    ///
3054    /// # Accounts
3055    /// *[See the documentation for the accounts.](CloseGlvDeposit)*
3056    ///
3057    /// # Arguments
3058    /// - `reason`: The reason for closing the GLV deposit.
3059    ///
3060    /// # Errors
3061    /// - The [`executor`](CloseGlvDeposit::executor) must be a signer, and must be
3062    ///   either the owner of the GLV deposit or a `ORDER_KEEPER` in the store
3063    /// - The [`store`](CloseGlvDeposit::store) must be properly initialized
3064    /// - The [`owner`](CloseGlvDeposit::owner) must be the owner of the GLV deposit
3065    /// - The [`glv_deposit`](CloseGlvDeposit::glv_deposit) must be:
3066    ///   - Properly initialized
3067    ///   - Owned by the `owner` and `store`
3068    ///   - In cancelled or executed state if the `executor` is not the `owner`
3069    /// - Token mint account requirements:
3070    ///   - All tokens must be valid and recorded in the [`glv_deposit`](CloseGlvDeposit::glv_deposit)
3071    ///   - [`initial_long_token`](CloseGlvDeposit::initial_long_token) must be provided if initial long amount > 0
3072    ///   - [`initial_short_token`](CloseGlvDeposit::initial_short_token) must be provided if initial short amount > 0
3073    /// - Escrow account requirements:
3074    ///   - Must correspond to their respective tokens
3075    ///   - Must be owned by the [`glv_deposit`](CloseGlvDeposit::glv_deposit)
3076    ///   - Must be recorded in the [`glv_deposit`](CloseGlvDeposit::glv_deposit)
3077    /// - The addresses of the ATAs must be valid associated token addresses derived from the respective tokens and `owner`
3078    /// - All token programs must match their corresponding token accounts
3079    pub fn close_glv_deposit<'info>(
3080        ctx: Context<'_, '_, 'info, 'info, CloseGlvDeposit<'info>>,
3081        reason: String,
3082    ) -> Result<()> {
3083        internal::Close::close(&ctx, &reason)
3084    }
3085
3086    /// Execute GLV deposit.
3087    ///
3088    /// # Accounts
3089    /// *[See the documentation for the accounts.](ExecuteGlvDeposit)*
3090    ///
3091    /// # Arguments
3092    /// - `execution_lamports`: The execution fee claimed to be used by the keeper.
3093    /// - `throw_on_execution_error`: Whether to throw an error if the execution fails.
3094    ///
3095    /// # Errors
3096    /// - The [`authority`](ExecuteGlvDeposit::authority) must be a signer and have `ORDER_KEEPER` role in the `store`
3097    /// - The [`store`](ExecuteGlvDeposit::store) must be properly initialized
3098    /// - The [`token_map`](ExecuteGlvDeposit::token_map) must be:
3099    ///   - Properly initialized
3100    ///   - Authorized by the `store`
3101    /// - The [`oracle`](ExecuteGlvDeposit::oracle) must be:
3102    ///   - Cleared
3103    ///   - Owned by the `store`
3104    /// - The [`glv`](ExecuteGlvDeposit::glv) must be:
3105    ///   - Properly initialized
3106    ///   - Owned by the `store`
3107    ///   - Match the expected GLV of the deposit
3108    /// - The [`market`](ExecuteGlvDeposit::market) must be:
3109    ///   - Properly initialized
3110    ///   - Owned by the `store`
3111    ///   - Match the expected market of the deposit
3112    ///   - Must be enabled and listed in the [`glv`](ExecuteGlvDeposit::glv)
3113    /// - The [`glv_deposit`](ExecuteGlvDeposit::glv_deposit) must be:
3114    ///   - Properly initialized
3115    ///   - Owned by the `store`
3116    ///   - In pending state
3117    /// - Token requirements:
3118    ///   - All tokens must be valid and recorded in the [`glv_deposit`](ExecuteGlvDeposit::glv_deposit)
3119    ///   - [`glv_token`](ExecuteGlvDeposit::glv_token) must be the GLV token of the [`glv`](ExecuteGlvDeposit::glv)
3120    ///   - [`market_token`](ExecuteGlvDeposit::market_token) must be the market token of the [`market`](ExecuteGlvDeposit::market)
3121    /// - Vault requirements:
3122    ///   - [`initial_long_token_vault`](ExecuteGlvDeposit::initial_long_token_vault) must be:
3123    ///     - The market vault for the initial long token
3124    ///     - Owned by the `store`
3125    ///   - [`initial_short_token_vault`](ExecuteGlvDeposit::initial_short_token_vault) must be:
3126    ///     - The market vault for the initial short token
3127    ///     - Owned by the `store`
3128    ///   - [`market_token_vault`](ExecuteGlvDeposit::market_token_vault) must be:
3129    ///     - The market token vault in the [`glv`](ExecuteGlvDeposit::glv)
3130    ///     - Owned by the [`glv`](ExecuteGlvDeposit::glv)
3131    /// - Escrow requirements:
3132    ///   - Must correspond to their respective tokens
3133    ///   - Must be owned by the [`glv_deposit`](ExecuteGlvDeposit::glv_deposit)
3134    ///   - Must be recorded in the [`glv_deposit`](ExecuteGlvDeposit::glv_deposit)
3135    /// - All token programs must match their corresponding token accounts
3136    /// - All remaining accounts must be valid per [`ExecuteGlvDeposit`] documentation
3137    /// - Returns error if execution fails and `throw_on_execution_error` is `true`
3138    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
3139    pub fn execute_glv_deposit<'info>(
3140        ctx: Context<'_, '_, 'info, 'info, ExecuteGlvDeposit<'info>>,
3141        execution_lamports: u64,
3142        throw_on_execution_error: bool,
3143    ) -> Result<()> {
3144        instructions::unchecked_execute_glv_deposit(
3145            ctx,
3146            execution_lamports,
3147            throw_on_execution_error,
3148        )
3149    }
3150
3151    /// Create GLV withdrawal.
3152    ///
3153    /// # Accounts
3154    /// *[See the documentation for the accounts.](CreateGlvWithdrawal)*
3155    ///
3156    /// # Arguments
3157    /// - `nonce`: A 32-byte used to derive the address of the GLV withdrawal.
3158    /// - `params`: The parameters for creating the GLV withdrawal.
3159    ///
3160    /// # Errors
3161    /// - The [`owner`](CreateGlvWithdrawal::owner) must be a signer and have sufficient balance
3162    ///   for the execution fee and rent.
3163    /// - The [`store`](CreateGlvWithdrawal::store) must be properly initialized.
3164    /// - The [`market`](CreateGlvWithdrawal::market) must be:
3165    ///   - Properly initialized
3166    ///   - Enabled
3167    ///   - Owned by the `store`
3168    ///   - One of the markets in the [`glv`](CreateGlvWithdrawal::glv)
3169    /// - The [`glv`](CreateGlvWithdrawal::glv) must be:
3170    ///   - Properly initialized
3171    ///   - Owned by the `store`
3172    /// - The [`glv_withdrawal`](CreateGlvWithdrawal::glv_withdrawal) must be:
3173    ///   - Uninitialized
3174    ///   - A PDA derived from:
3175    ///     - the SEED of [`GlvWithdrawal`](states::GlvWithdrawal)
3176    ///     - [`store`](CreateGlvWithdrawal::store)
3177    ///     - [`owner`](CreateGlvWithdrawal::owner)
3178    ///     - `nonce`
3179    /// - Token requirements:
3180    ///   - [`glv_token`](CreateGlvWithdrawal::glv_token) must be:
3181    ///     - Properly initialized
3182    ///     - The GLV token of the [`glv`](CreateGlvWithdrawal::glv)
3183    ///   - [`market_token`](CreateGlvWithdrawal::market_token) must be:
3184    ///     - Properly initialized
3185    ///     - The market token of the [`market`](CreateGlvWithdrawal::market)
3186    ///   - All other tokens must be properly initialized
3187    /// - Source requirements:
3188    ///   - [`glv_token_source`](CreateGlvWithdrawal::glv_token_source) must be:
3189    ///     - Properly initialized
3190    ///     - A GLV token account
3191    ///     - Have sufficient balance
3192    ///     - Have the `owner` as its authority
3193    /// - Escrow requirements:
3194    ///   - Must correspond to their respective tokens
3195    ///   - Must be owned by the [`glv_withdrawal`](CreateGlvWithdrawal::glv_withdrawal)
3196    /// - All token programs must match their corresponding token accounts
3197    pub fn create_glv_withdrawal<'info>(
3198        mut ctx: Context<'_, '_, 'info, 'info, CreateGlvWithdrawal<'info>>,
3199        nonce: [u8; 32],
3200        params: CreateGlvWithdrawalParams,
3201    ) -> Result<()> {
3202        internal::Create::create(&mut ctx, &nonce, &params)
3203    }
3204
3205    /// Close GLV withdrawal.
3206    ///
3207    /// # Accounts
3208    /// *[See the documentation for the accounts.](CloseGlvWithdrawal)*
3209    ///
3210    /// # Arguments
3211    /// - `reason`: The reason for closing the GLV withdrawal.
3212    ///
3213    /// # Errors
3214    /// - The [`executor`](CloseGlvWithdrawal::executor) must be:
3215    ///   - A signer
3216    ///   - Either:
3217    ///     - The owner of the [`glv_withdrawal`](CloseGlvWithdrawal::glv_withdrawal)
3218    ///     - A `ORDER_KEEPER` in the `store`
3219    /// - The [`store`](CloseGlvWithdrawal::store) must be properly initialized
3220    /// - The [`owner`](CloseGlvWithdrawal::owner) must be the owner of the [`glv_withdrawal`](CloseGlvWithdrawal::glv_withdrawal)
3221    /// - The [`glv_withdrawal`](CloseGlvWithdrawal::glv_withdrawal) must be:
3222    ///   - Properly initialized
3223    ///   - Owned by the `owner`
3224    ///   - Owned by the `store`
3225    /// - Token requirements:
3226    ///   - All tokens must be valid and recorded in the [`glv_withdrawal`](CloseGlvWithdrawal::glv_withdrawal)
3227    /// - Escrow requirements:
3228    ///   - Must correspond to their respective tokens
3229    ///   - Must be owned by the [`glv_withdrawal`](CloseGlvWithdrawal::glv_withdrawal)
3230    ///   - Must be recorded in the [`glv_withdrawal`](CloseGlvWithdrawal::glv_withdrawal)
3231    /// - The addresses of the ATAs must be valid associated token addresses derived from the respective tokens and `owner`
3232    /// - All token programs must match their corresponding token accounts
3233    /// - If the `executor` is not the `owner`, the [`glv_withdrawal`](CloseGlvWithdrawal::glv_withdrawal) must be either cancelled or executed.
3234    pub fn close_glv_withdrawal<'info>(
3235        ctx: Context<'_, '_, 'info, 'info, CloseGlvWithdrawal<'info>>,
3236        reason: String,
3237    ) -> Result<()> {
3238        internal::Close::close(&ctx, &reason)
3239    }
3240
3241    /// Execute GLV withdrawal.
3242    ///
3243    /// # Accounts
3244    /// *[See the documentation for the accounts.](ExecuteGlvWithdrawal)*
3245    ///
3246    /// # Arguments
3247    /// - `execution_lamports`: The execution fee claimed to be used by the keeper.
3248    /// - `throw_on_execution_error`: Whether to throw an error if the execution fails.
3249    ///
3250    /// # Errors
3251    /// - The [`authority`](ExecuteGlvWithdrawal::authority) must be:
3252    ///   - A signer
3253    ///   - A `ORDER_KEEPER` in the `store`
3254    /// - The [`store`](ExecuteGlvWithdrawal::store) must be properly initialized
3255    /// - The [`token_map`](ExecuteGlvWithdrawal::token_map) must be:
3256    ///   - Properly initialized
3257    ///   - Authorized by the `store`
3258    /// - The [`oracle`](ExecuteGlvWithdrawal::oracle) must be:
3259    ///   - Cleared
3260    ///   - Owned by the `store`
3261    /// - The [`glv`](ExecuteGlvWithdrawal::glv) must be:
3262    ///   - Properly initialized
3263    ///   - Owned by the `store`
3264    ///   - The expected GLV of the withdrawal
3265    /// - The [`market`](ExecuteGlvWithdrawal::market) must be:
3266    ///   - Properly initialized
3267    ///   - Owned by the `store`
3268    ///   - The expected market of the withdrawal
3269    ///   - Must be enabled and listed in the [`glv`](ExecuteGlvWithdrawal::glv)
3270    /// - The [`glv_withdrawal`](ExecuteGlvWithdrawal::glv_withdrawal) must be:
3271    ///   - Properly initialized
3272    ///   - Owned by the `store`
3273    ///   - In pending state
3274    /// - Token requirements:
3275    ///   - All tokens must be valid and recorded in the withdrawal
3276    ///   - [`glv_token`](ExecuteGlvWithdrawal::glv_token) must be the GLV token of the GLV
3277    ///   - [`market_token`](ExecuteGlvWithdrawal::market_token) must be the market token of the market
3278    /// - Escrow requirements:
3279    ///   - Escrow accounts must correspond to their tokens
3280    ///   - Escrow accounts must be owned by the [`glv_withdrawal`](ExecuteGlvWithdrawal::glv_withdrawal)
3281    ///   - Escrow accounts must be recorded in the [`glv_withdrawal`](ExecuteGlvWithdrawal::glv_withdrawal)
3282    /// - Vault requirements:
3283    ///   - [`market_token_withdrawal_vault`](ExecuteGlvWithdrawal::market_token_withdrawal_vault) must be the market vault for market token, owned by the `store`
3284    ///   - [`final_long_token_vault`](ExecuteGlvWithdrawal::final_long_token_vault) must be the market vault for final long token, owned by the `store`
3285    ///   - [`final_short_token_vault`](ExecuteGlvWithdrawal::final_short_token_vault) must be the market vault for final short token, owned by the `store`
3286    ///   - [`market_token_vault`](ExecuteGlvWithdrawal::market_token_vault) must be the GLV's market token vault, owned by the [`glv`](ExecuteGlvWithdrawal::glv)
3287    /// - All token programs must match their corresponding token accounts
3288    /// - All remaining accounts must be valid per [`ExecuteGlvWithdrawal`] documentation
3289    /// - Returns error if execution fails and `throw_on_execution_error` is `true`
3290    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
3291    pub fn execute_glv_withdrawal<'info>(
3292        ctx: Context<'_, '_, 'info, 'info, ExecuteGlvWithdrawal<'info>>,
3293        execution_lamports: u64,
3294        throw_on_execution_error: bool,
3295    ) -> Result<()> {
3296        instructions::unchecked_execute_glv_withdrawal(
3297            ctx,
3298            execution_lamports,
3299            throw_on_execution_error,
3300        )
3301    }
3302
3303    /// Create GLV shift.
3304    ///
3305    /// # Accounts
3306    /// *[See the documentation for the accounts.](CreateGlvShift)*
3307    ///
3308    /// # Arguments
3309    /// - `nonce`: A 32-byte used to derive the address of the GLV shift.
3310    /// - `params`: The parameters for creating the GLV shift.
3311    ///
3312    /// # Errors
3313    /// - The [`authority`](CreateGlvShift::authority) must be:
3314    ///   - A signer
3315    ///   - A `ORDER_KEEPER` in the `store`
3316    /// - The [`store`](CreateGlvShift::store) must be properly initialized
3317    /// - The [`glv`](CreateGlvShift::glv) must be:
3318    ///   - Properly initialized
3319    ///   - Owned by the `store`
3320    /// - Market requirements:
3321    ///   - [`from_market`](CreateGlvShift::from_market) must be:
3322    ///     - Enabled
3323    ///     - Owned by the `store`
3324    ///     - One of the markets in the [`glv`](CreateGlvShift::glv)
3325    ///   - [`to_market`](CreateGlvShift::to_market) must be:
3326    ///     - Enabled
3327    ///     - Owned by the `store`
3328    ///     - One of the markets in the [`glv`](CreateGlvShift::glv)
3329    ///     - Different from `from_market`
3330    /// - The [`glv_shift`](CreateGlvShift::glv_shift) must be:
3331    ///   - Uninitialized
3332    ///   - PDA derived from the SEED of [`GlvShift`](states::GlvShift), `store`, `glv`, and `nonce`
3333    /// - Token requirements:
3334    ///   - [`from_market_token`](CreateGlvShift::from_market_token) must be:
3335    ///     - Properly initialized
3336    ///     - The market token of `from_market`
3337    ///   - [`to_market_token`](CreateGlvShift::to_market_token) must be:
3338    ///     - Properly initialized
3339    ///     - The market token of `to_market`
3340    /// - Vault requirements:
3341    ///   - [`from_market_token_vault`](CreateGlvShift::from_market_token_vault) must be:
3342    ///     - The market token vault for `from_market_token` in the [`glv`](CreateGlvShift::glv)
3343    ///     - Owned by the [`glv`](CreateGlvShift::glv)
3344    ///   - [`to_market_token_vault`](CreateGlvShift::to_market_token_vault) must be:
3345    ///     - The market token vault for `to_market_token` in the [`glv`](CreateGlvShift::glv)
3346    ///     - Owned by the [`glv`](CreateGlvShift::glv)
3347    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
3348    pub fn create_glv_shift<'info>(
3349        mut ctx: Context<'_, '_, 'info, 'info, CreateGlvShift<'info>>,
3350        nonce: [u8; 32],
3351        params: CreateShiftParams,
3352    ) -> Result<()> {
3353        internal::Create::create(&mut ctx, &nonce, &params)
3354    }
3355
3356    /// Close a GLV shift.
3357    ///
3358    /// # Accounts
3359    /// *[See the documentation for the accounts.](CloseGlvShift)*
3360    ///
3361    /// # Arguments
3362    /// - `reason`: The reason for closing the GLV shift.
3363    ///
3364    /// # Errors
3365    /// - The [`authority`](CloseGlvShift::authority) must be:
3366    ///   - A signer
3367    ///   - A `ORDER_KEEPER` in the `store`
3368    /// - The [`funder`](CloseGlvShift::funder) must be the funder of the [`glv`](CloseGlvShift::glv).
3369    /// - The [`store`](CloseGlvShift::store) must be properly initialized.
3370    /// - The [`glv`](CloseGlvShift::glv) must be:
3371    ///   - Properly initialized
3372    ///   - Owned by the `store`
3373    ///   - The expected GLV of the GLV shift
3374    /// - The [`glv_shift`](CloseGlvShift::glv_shift) must be:
3375    ///   - Properly initialized
3376    ///   - Owned by the `store`
3377    /// - Token requirements:
3378    ///   - [`from_market_token`](CloseGlvShift::from_market_token) must be:
3379    ///     - Recorded in the GLV shift
3380    ///   - [`to_market_token`](CloseGlvShift::to_market_token) must be:
3381    ///     - Recorded in the GLV shift
3382    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
3383    pub fn close_glv_shift<'info>(
3384        ctx: Context<'_, '_, 'info, 'info, CloseGlvShift<'info>>,
3385        reason: String,
3386    ) -> Result<()> {
3387        internal::Close::close(&ctx, &reason)
3388    }
3389
3390    /// Execute GLV shift.
3391    ///
3392    /// # Accounts
3393    /// *[See the documentation for the accounts.](ExecuteGlvShift)*
3394    ///
3395    /// # Arguments
3396    /// - `execution_lamports`: The execution fee claimed to be used by the keeper.
3397    /// - `throw_on_execution_error`: Whether to throw an error if execution fails.
3398    ///
3399    /// # Errors
3400    /// - The [`authority`](ExecuteGlvShift::authority) must be:
3401    ///   - A signer
3402    ///   - A `ORDER_KEEPER` in the `store`
3403    /// - The [`store`](ExecuteGlvShift::store) must be properly initialized
3404    /// - The [`token_map`](ExecuteGlvShift::token_map) must be:
3405    ///   - Properly initialized
3406    ///   - Authorized by the `store`
3407    /// - The [`oracle`](ExecuteGlvShift::oracle) must be:
3408    ///   - Cleared
3409    ///   - Owned by the `store`
3410    /// - The [`glv`](ExecuteGlvShift::glv) must be:
3411    ///   - Properly initialized
3412    ///   - Owned by the `store`
3413    ///   - The expected GLV of the GLV shift
3414    /// - The [`from_market`](ExecuteGlvShift::from_market) must be:
3415    ///   - Enabled
3416    ///   - Owned by the `store`
3417    ///   - One of the markets in the [`glv`](ExecuteGlvShift::glv)
3418    /// - The [`to_market`](ExecuteGlvShift::to_market) must be:
3419    ///   - Enabled
3420    ///   - Owned by the `store`
3421    ///   - One of the markets in the [`glv`](ExecuteGlvShift::glv)
3422    /// - The [`glv_shift`](ExecuteGlvShift::glv_shift) must be:
3423    ///   - Properly initialized
3424    ///   - Owned by the `store`
3425    /// - Token requirements:
3426    ///   - [`from_market_token`](ExecuteGlvShift::from_market_token) must be:
3427    ///     - The market token of `from_market`
3428    ///     - Recorded in the GLV shift
3429    ///   - [`to_market_token`](ExecuteGlvShift::to_market_token) must be:
3430    ///     - The market token of `to_market`
3431    ///     - Recorded in the GLV shift
3432    /// - Vault requirements:
3433    ///   - [`from_market_token_glv_vault`](ExecuteGlvShift::from_market_token_glv_vault) must be:
3434    ///     - The escrow account for `from_market_token` in the GLV
3435    ///     - Owned by the [`glv`](ExecuteGlvShift::glv)
3436    ///   - [`to_market_token_glv_vault`](ExecuteGlvShift::to_market_token_glv_vault) must be:
3437    ///     - The escrow account for `to_market_token` in the GLV
3438    ///     - Owned by the [`glv`](ExecuteGlvShift::glv)
3439    ///   - [`from_market_token_vault`](ExecuteGlvShift::from_market_token_vault) must be:
3440    ///     - The market vault for `from_market_token`
3441    ///     - Owned by the `store`
3442    /// - Token programs must match the tokens and token accounts
3443    /// - The remaining accounts must be valid (see [`ExecuteGlvShift`] docs)
3444    /// - Returns error if execution fails and `throw_on_execution_error` is `true`
3445    #[access_control(internal::Authenticate::only_order_keeper(&ctx))]
3446    pub fn execute_glv_shift<'info>(
3447        ctx: Context<'_, '_, 'info, 'info, ExecuteGlvShift<'info>>,
3448        execution_lamports: u64,
3449        throw_on_execution_error: bool,
3450    ) -> Result<()> {
3451        instructions::unchecked_execute_glv_shift(ctx, execution_lamports, throw_on_execution_error)
3452    }
3453
3454    #[access_control(internal::Authenticate::only_migration_keeper(&ctx))]
3455    pub fn migrate_referral_code<'info>(
3456        ctx: Context<'_, '_, 'info, 'info, MigrateReferralCode<'info>>,
3457    ) -> Result<()> {
3458        cfg_if::cfg_if! {
3459            if #[cfg(feature = "migration")] {
3460                instructions::unchecked_migrate_referral_code(ctx)
3461            } else {
3462                err!(CoreError::Unimplemented)
3463            }
3464        }
3465    }
3466}
3467
3468/// Result type with [`CoreError`] as error type.
3469pub type CoreResult<T> = std::result::Result<T, CoreError>;
3470
3471#[error_code]
3472pub enum CoreError {
3473    // ===========================================
3474    //                Common Errors
3475    // ===========================================
3476    /// Non-defualt store is not allowed.
3477    #[msg("non-default store is not allowed")]
3478    NonDefaultStore,
3479    /// Internal error.
3480    #[msg("internal error")]
3481    Internal,
3482    /// Unimplemented.
3483    Unimplemented,
3484    /// Not an Admin.
3485    #[msg("not an admin")]
3486    NotAnAdmin,
3487    /// Permission denied.
3488    #[msg("permission denied")]
3489    PermissionDenied,
3490    /// Feature disabled.
3491    #[msg("feature disabled")]
3492    FeatureDisabled,
3493    /// Model Error.
3494    #[msg("model")]
3495    Model,
3496    /// Invalid Argument.
3497    #[msg("invalid argument")]
3498    InvalidArgument,
3499    /// Preconditions are not met.
3500    #[msg("preconditions are not met")]
3501    PreconditionsAreNotMet,
3502    /// Not found.
3503    #[msg("not found")]
3504    NotFound,
3505    /// Exceed max length limit.
3506    #[msg("exceed max length limit")]
3507    ExceedMaxLengthLimit,
3508    /// Not enough space.
3509    #[msg("not enough space")]
3510    NotEnoughSpace,
3511    /// Token amount overflow.
3512    #[msg("token amount overflow")]
3513    TokenAmountOverflow,
3514    /// Value overflow.
3515    #[msg("value overflow")]
3516    ValueOverflow,
3517    /// Unknown Action State.
3518    #[msg("unknown action state")]
3519    UnknownActionState,
3520    /// Load account error.
3521    #[msg("load zero-copy account error")]
3522    LoadAccountError,
3523    /// Token account is not provided.
3524    #[msg("required token account is not provided")]
3525    TokenAccountNotProvided,
3526    /// Token mint is not provided.
3527    #[msg("required token mint is not provided")]
3528    TokenMintNotProvided,
3529    /// Token decimals mismatched.
3530    #[msg("token decimals mismatched")]
3531    TokenDecimalsMismatched,
3532    /// Market account is not provided.
3533    #[msg("market account is not provided")]
3534    MarketAccountIsNotProvided,
3535    /// Store Mismatched.
3536    #[msg("store mismatched")]
3537    StoreMismatched,
3538    /// Owner mismatched.
3539    #[msg("owner mismatched")]
3540    OwnerMismatched,
3541    /// Receiver mismatched.
3542    #[msg("receiver mismatched")]
3543    ReceiverMismatched,
3544    /// Rent Receiver mismatched.
3545    #[msg("rent receiver mismatched")]
3546    RentReceiverMismatched,
3547    /// Market mismatched.
3548    #[msg("market mismatched")]
3549    MarketMismatched,
3550    /// Market token mint mismatched.
3551    #[msg("market token mint mismatched")]
3552    MarketTokenMintMismatched,
3553    /// Mint account not provided.
3554    #[msg("mint account not provided")]
3555    MintAccountNotProvided,
3556    /// Market token account mismatched.
3557    #[msg("market token account mismatched")]
3558    MarketTokenAccountMismatched,
3559    /// Token mint mismatched.
3560    #[msg("token mint mismatched")]
3561    TokenMintMismatched,
3562    /// Token account mismatched.
3563    #[msg("token account mismatched")]
3564    TokenAccountMismatched,
3565    /// Not an ATA for the given token.
3566    #[msg("not an ATA for the given token")]
3567    NotAnATA,
3568    /// Not enough token amounts.
3569    #[msg("not enough token amount")]
3570    NotEnoughTokenAmount,
3571    /// Token amount exceeds limit.
3572    #[msg("token amount exceeds limit")]
3573    TokenAmountExceedsLimit,
3574    /// Unknown token.
3575    #[msg("unknown token")]
3576    UnknownToken,
3577    /// Not enough execution fee.
3578    #[msg("not enough execution fee")]
3579    NotEnoughExecutionFee,
3580    /// Invalid Swap Path length.
3581    #[msg("invalid swap path length")]
3582    InvalidSwapPathLength,
3583    /// Not enough swap markets in the path.
3584    #[msg("not enough swap markets in the path")]
3585    NotEnoughSwapMarkets,
3586    /// Invalid Swap Path.
3587    #[msg("invalid swap path")]
3588    InvalidSwapPath,
3589    /// Insufficient output amounts.
3590    #[msg("insufficient output amounts")]
3591    InsufficientOutputAmount,
3592    /// Store Outdated.
3593    #[msg("store outdated")]
3594    StoreOutdated,
3595    // ===========================================
3596    //                 Store Errors
3597    // ===========================================
3598    /// Invalid Store Config Key.
3599    #[msg("invalid store config key")]
3600    InvalidStoreConfigKey,
3601    // ===========================================
3602    //                Oracle Errors
3603    // ===========================================
3604    /// Invalid Provider Kind Index.
3605    #[msg("invalid provider kind index")]
3606    InvalidProviderKindIndex,
3607    /// Chainlink Program is required.
3608    #[msg("chainlink program is required")]
3609    ChainlinkProgramIsRequired,
3610    /// Not supported price provider for custom price feed.
3611    #[msg("this price provider is not supported to be used with custom price feed")]
3612    NotSupportedCustomPriceProvider,
3613    /// Not enough token feeds.
3614    #[msg("not enough token feeds")]
3615    NotEnoughTokenFeeds,
3616    /// Oracle timestamps are larger than required.
3617    #[msg("oracle timestamps are larger than required")]
3618    OracleTimestampsAreLargerThanRequired,
3619    /// Oracle timestamps are smaller than required.
3620    #[msg("oracle timestamps are smaller than required")]
3621    OracleTimestampsAreSmallerThanRequired,
3622    /// Invalid Oracle timestamps range.
3623    #[msg("invalid oracle timestamps range")]
3624    InvalidOracleTimestampsRange,
3625    /// Max oracle timestamps range exceeded.
3626    #[msg("max oracle timestamps range exceeded")]
3627    MaxOracleTimestampsRangeExceeded,
3628    /// Oracle not updated.
3629    #[msg("oracle not updated")]
3630    OracleNotUpdated,
3631    /// Max price age exceeded.
3632    #[msg("max price age exceeded")]
3633    MaxPriceAgeExceeded,
3634    /// Max prcie's timestamp exceeded.
3635    MaxPriceTimestampExceeded,
3636    /// Negative price.
3637    #[msg("negative price is not supported")]
3638    NegativePriceIsNotSupported,
3639    /// Invalid Oracle slot.
3640    #[msg("invalid oracle slot")]
3641    InvalidOracleSlot,
3642    /// Missing oracle price.
3643    #[msg("missing oracle price")]
3644    MissingOraclePrice,
3645    /// Invalid Price feed price.
3646    #[msg("invalid price feed price")]
3647    InvalidPriceFeedPrice,
3648    /// Price Overflow.
3649    #[msg("price overflow")]
3650    PriceOverflow,
3651    /// Invalid price feed account.
3652    #[msg("invalid price feed account")]
3653    InvalidPriceFeedAccount,
3654    /// Price feed is not updated.
3655    #[msg("price feed is not updated")]
3656    PriceFeedNotUpdated,
3657    /// Prices are already set.
3658    #[msg("prices are already set")]
3659    PricesAreAlreadySet,
3660    /// Price is already set.
3661    #[msg("price is already set")]
3662    PriceIsAlreadySet,
3663    /// Token config is diabled.
3664    #[msg("token config is disabled")]
3665    TokenConfigDisabled,
3666    /// Synthetic token price is not allowed.
3667    #[msg("synthetic token price is not allowed")]
3668    SyntheticTokenPriceIsNotAllowed,
3669    /// Invalid Price Report.
3670    #[msg("invalid price report")]
3671    InvalidPriceReport,
3672    /// Market not opened.
3673    #[msg("market is not open")]
3674    MarketNotOpen,
3675    // ===========================================
3676    //                Deposit Errors
3677    // ===========================================
3678    /// Empty Deposit.
3679    #[msg("empty deposit")]
3680    EmptyDeposit,
3681    /// Invalid owner for the first deposit.
3682    #[msg("invalid owner for the first deposit")]
3683    InvalidReceiverForFirstDeposit,
3684    /// Not enough market token amount for the first deposit.
3685    #[msg("not enough market token amount for the first deposit")]
3686    NotEnoughMarketTokenAmountForFirstDeposit,
3687    /// Not enough GLV token amount for the first deposit.
3688    #[msg("not enough GLV token amount for the first deposit")]
3689    NotEnoughGlvTokenAmountForFirstDeposit,
3690    // ===========================================
3691    //               Withdrawal Errors
3692    // ===========================================
3693    /// Empty Withdrawal.
3694    #[msg("emtpy withdrawal")]
3695    EmptyWithdrawal,
3696    // ===========================================
3697    //                 Order Errors
3698    // ===========================================
3699    /// Empty Order.
3700    #[msg("emtpy order")]
3701    EmptyOrder,
3702    /// Invalid min output amount for limit swap.
3703    #[msg("invalid min output amount for limit swap order")]
3704    InvalidMinOutputAmount,
3705    /// Invalid trigger price.
3706    #[msg("invalid trigger price")]
3707    InvalidTriggerPrice,
3708    /// Invalid position.
3709    #[msg("invalid position")]
3710    InvalidPosition,
3711    /// Invalid position kind.
3712    #[msg("invalid position kind")]
3713    InvalidPositionKind,
3714    /// Position mismatched.
3715    #[msg("position mismatched")]
3716    PositionMismatched,
3717    /// Position is not required.
3718    #[msg("position is not required")]
3719    PositionItNotRequired,
3720    /// Position is required.
3721    #[msg("position is required")]
3722    PositionIsRequired,
3723    /// Order kind is not allowed.
3724    #[msg("the order kind is not allowed by this instruction")]
3725    OrderKindNotAllowed,
3726    /// Unknown Order Kind.
3727    #[msg("unknown order kind")]
3728    UnknownOrderKind,
3729    /// Unknown Order Side.
3730    #[msg("unknown order side")]
3731    UnknownOrderSide,
3732    /// Unknown Decrease Position Swap Type.
3733    #[msg("unknown decrease position swap type")]
3734    UnknownDecreasePositionSwapType,
3735    /// Missing initial collateral token.
3736    #[msg("missing initial collateral token")]
3737    MissingInitialCollateralToken,
3738    /// Missing final output token.
3739    #[msg("missing final output token")]
3740    MissingFinalOutputToken,
3741    /// Missing pool tokens.
3742    #[msg("missing pool tokens")]
3743    MissingPoolTokens,
3744    /// Invalid Trade ID.
3745    #[msg("invalid trade ID")]
3746    InvalidTradeID,
3747    /// Invalid Trade delta size.
3748    #[msg("invalid trade delta size")]
3749    InvalidTradeDeltaSize,
3750    /// Invalid Trade delta tokens.
3751    #[msg("invalid trade delta tokens")]
3752    InvalidTradeDeltaTokens,
3753    /// Invalid Borrowing Factor.
3754    #[msg("invalid borrowing factor")]
3755    InvalidBorrowingFactor,
3756    /// Invalid funding factors.
3757    #[msg("invalid funding factors")]
3758    InvalidFundingFactors,
3759    /// No delegated authority is set.
3760    #[msg("no delegated authority is set")]
3761    NoDelegatedAuthorityIsSet,
3762    /// Claimable collateral for holding cannot be in output tokens.
3763    #[msg("claimable collateral for holding cannot be in output tokens")]
3764    ClaimableCollateralForHoldingCannotBeInOutputTokens,
3765    /// ADL is not enabled.
3766    #[msg("ADL is not enabled")]
3767    AdlNotEnabled,
3768    /// ADL is not required.
3769    #[msg("ADL is not required")]
3770    AdlNotRequired,
3771    /// Invalid ADL.
3772    #[msg("invalid ADL")]
3773    InvalidAdl,
3774    /// The output token and the secondary output token are the same,
3775    /// but the token amounts are not merged togather.
3776    #[msg("same output tokens not merged")]
3777    SameOutputTokensNotMerged,
3778    /// Event buffer is not provided.
3779    #[msg("event buffer is not provided")]
3780    EventBufferNotProvided,
3781    // ===========================================
3782    //                 Shift Errors
3783    // ===========================================
3784    /// Empty Shift.
3785    #[msg("emtpy shift")]
3786    EmptyShift,
3787    /// Invalid Shift Markets
3788    #[msg("invalid shift markets")]
3789    InvalidShiftMarkets,
3790    // ===========================================
3791    //        GT and User Accounts Errors
3792    // ===========================================
3793    /// GT State has been initialized.
3794    #[msg("GT State has been initialized")]
3795    GTStateHasBeenInitialized,
3796    /// Invalid GT config.
3797    #[msg("invalid GT config")]
3798    InvalidGTConfig,
3799    /// Invalid GT discount.
3800    #[msg("invalid GT discount")]
3801    InvalidGTDiscount,
3802    /// User account has been initialized.
3803    #[msg("user account has been initialized")]
3804    UserAccountHasBeenInitialized,
3805    // ===========================================
3806    //               Referral Errors
3807    // ===========================================
3808    /// Referral Code has been set.
3809    #[msg("referral code has been set")]
3810    ReferralCodeHasBeenSet,
3811    /// Referrer has been set.
3812    #[msg("referrer has been set")]
3813    ReferrerHasBeenSet,
3814    /// Invalid User Account.
3815    #[msg("invalid user account")]
3816    InvalidUserAccount,
3817    /// Referral Code Mismatched.
3818    #[msg("referral code mismatched")]
3819    ReferralCodeMismatched,
3820    /// Self-referral is not allowed.
3821    #[msg("self-referral is not allowed")]
3822    SelfReferral,
3823    /// Mutual-referral is not allowed.
3824    #[msg("mutual-referral is not allowed")]
3825    MutualReferral,
3826    // ===========================================
3827    //                Market Errors
3828    // ===========================================
3829    /// Invalid market config key.
3830    #[msg("invalid market config key")]
3831    InvalidMarketConfigKey,
3832    /// Invalid collateral token.
3833    #[msg("invalid collateral token")]
3834    InvalidCollateralToken,
3835    /// Disabled market.
3836    #[msg("disabled market")]
3837    DisabledMarket,
3838    // ===========================================
3839    //                  GLV Errors
3840    // ===========================================
3841    /// Failed to calculate GLV value for market.
3842    #[msg("failed to calculate GLV value for this market")]
3843    FailedToCalculateGlvValueForMarket,
3844    /// Failed to calculate GLV amount to mint.
3845    #[msg("failed to calculate GLV amount to mint")]
3846    FailedToCalculateGlvAmountToMint,
3847    /// Failed to calculate market token amount to burn.
3848    FailedTOCalculateMarketTokenAmountToBurn,
3849    /// Exceed max market token balance amount of GLV.
3850    #[msg("GLV max market token balance amount exceeded")]
3851    ExceedMaxGlvMarketTokenBalanceAmount,
3852    /// Exceed max market token balance value of GLV.
3853    #[msg("GLV max market token balance value exceeded")]
3854    ExceedMaxGlvMarketTokenBalanceValue,
3855    /// Empty GLV withdrawal.
3856    #[msg("Empty GLV withdrawal")]
3857    EmptyGlvWithdrawal,
3858    /// Negative Market Pool Value.
3859    #[msg("GLV: negative market pool value")]
3860    GlvNegativeMarketPoolValue,
3861    /// Deposit is not allowed with the given market.
3862    #[msg("GLV: deposit is not allowed with the given market")]
3863    GlvDepositIsNotAllowed,
3864    /// Shift interval not yet passed.
3865    #[msg("GLV: shift interval not yet passed")]
3866    GlvShiftIntervalNotYetPassed,
3867    /// Shift max price impact exceeded.
3868    #[msg("GLV: shift max price impact exceeded")]
3869    GlvShiftMaxPriceImpactExceeded,
3870    /// Shift value too small.
3871    #[msg("GLV: shift value is not large enough")]
3872    GlvShiftValueNotLargeEnough,
3873    // ===========================================
3874    //                Other Errors
3875    // ===========================================
3876    /// The decimals of token is immutable.
3877    #[msg("The decimals of token is immutable")]
3878    TokenDecimalsChanged,
3879    /// Price is stale.
3880    #[msg("Price is stale")]
3881    PriceIsStale,
3882}