use anchor_lang::prelude::*;
use crate::{
events::EventEmitter,
internal,
ops::market::RemainingAccountsForMarket,
states::{
market::{
revertible::{Revertible, RevertibleMarket},
utils::ClosableMarket,
},
Market, MarketPriceOptions, Oracle, Store, TokenMapHeader,
},
};
#[event_cpi]
#[derive(Accounts)]
pub struct UpdateFeesState<'info> {
#[account(mut)]
pub authority: Signer<'info>,
#[account(mut, has_one = token_map)]
pub store: AccountLoader<'info, Store>,
#[account(has_one = store)]
pub token_map: AccountLoader<'info, TokenMapHeader>,
#[account(mut, has_one = store)]
pub oracle: AccountLoader<'info, Oracle>,
#[account(mut, has_one = store)]
pub market: AccountLoader<'info, Market>,
}
impl<'info> UpdateFeesState<'info> {
pub(crate) fn invoke_unchecked(ctx: Context<'_, '_, 'info, 'info, Self>) -> Result<()> {
ctx.accounts.validate()?;
ctx.accounts
.update(ctx.remaining_accounts, ctx.bumps.event_authority)?;
Ok(())
}
fn validate(&self) -> Result<()> {
self.market
.load()?
.validate_with_options(&self.store.key(), true)?;
Ok(())
}
fn update(
&self,
remaining_accounts: &'info [AccountInfo<'info>],
event_authority_bump: u8,
) -> Result<()> {
let tokens = self
.market
.load()?
.meta()
.ordered_tokens()
.into_iter()
.collect::<Vec<_>>();
let event_emitter = EventEmitter::new(&self.event_authority, event_authority_bump);
let current_market_token = self.market.load()?.meta().market_token_mint;
self.oracle.load_mut()?.with_prices_opts(
&self.store,
&self.token_map,
&tokens,
remaining_accounts,
|oracle, remaining_accounts| {
{
let store = self.store.load()?;
self.market
.load()?
.validate_open_or_nonstale_oracle_with_store(oracle, &store)?;
}
let remaining_accounts = RemainingAccountsForMarket::new(
remaining_accounts,
current_market_token,
None,
)?;
let virtual_inventories = remaining_accounts.load_virtual_inventories()?;
let mut market =
RevertibleMarket::new(&self.market, Some(&virtual_inventories), event_emitter)?;
let prices = oracle.market_prices_with_options(
&market,
MarketPriceOptions {
allow_index_closed: true,
allow_long_closed: false,
allow_short_closed: false,
},
)?;
market.update_fees_state(&prices)?;
market.commit();
virtual_inventories.commit();
Ok(())
},
true,
)?;
Ok(())
}
}
impl<'info> internal::Authentication<'info> for UpdateFeesState<'info> {
fn authority(&self) -> &Signer<'info> {
&self.authority
}
fn store(&self) -> &AccountLoader<'info, Store> {
&self.store
}
}