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, ¶ms, 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, ¶ms, 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, ¶ms)
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, ¶ms, 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, ¶ms)
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, ¶ms, 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, ¶ms)
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, ¶ms, 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, ¶ms, 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, ¶ms, 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");