gmsol_store/
lib.rs

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