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