gmsol_store/instructions/oracle/
mod.rs

1/// Instructions for custom price feed.
2pub mod custom;
3
4use std::ops::Deref;
5
6use anchor_lang::prelude::*;
7
8use crate::{
9    states::{Chainlink, Oracle, PriceValidator, Store, TokenMapHeader, TokenMapLoader},
10    utils::internal,
11};
12
13pub use self::custom::*;
14
15/// The accounts definition for [`initialize_oracle`](crate::gmsol_store::initialize_oracle).
16///
17/// [*See also the documentation for the instruction.*](crate::gmsol_store::initialize_oracle)
18#[derive(Accounts)]
19pub struct InitializeOracle<'info> {
20    /// The payer.
21    pub payer: Signer<'info>,
22    /// The authority of the oracle.
23    /// CHECK: only used as an identifier.
24    pub authority: UncheckedAccount<'info>,
25    /// The store account that will be the owner of the oracle account.
26    pub store: AccountLoader<'info, Store>,
27    /// The new oracle account.
28    #[account(zero)]
29    pub oracle: AccountLoader<'info, Oracle>,
30    /// The system program.
31    pub system_program: Program<'info, System>,
32}
33
34pub(crate) fn initialize_oracle(ctx: Context<InitializeOracle>) -> Result<()> {
35    ctx.accounts
36        .oracle
37        .load_init()?
38        .init(ctx.accounts.store.key(), ctx.accounts.authority.key());
39    Ok(())
40}
41
42/// The accounts definition for [`clear_all_prices`](crate::gmsol_store::clear_all_prices).
43#[derive(Accounts)]
44pub struct ClearAllPrices<'info> {
45    /// The caller.
46    pub authority: Signer<'info>,
47    /// Store.
48    pub store: AccountLoader<'info, Store>,
49    /// Oracle.
50    #[account(
51        mut,
52        has_one = store,
53        has_one = authority,
54    )]
55    pub oracle: AccountLoader<'info, Oracle>,
56}
57
58/// Clear all prices of the given oracle account.
59/// CHECK: only ORACLE_CONTROLLER is allowed to invoke.
60pub(crate) fn unchecked_clear_all_prices(ctx: Context<ClearAllPrices>) -> Result<()> {
61    ctx.accounts.oracle.load_mut()?.clear_all_prices();
62    Ok(())
63}
64
65impl<'info> internal::Authentication<'info> for ClearAllPrices<'info> {
66    fn authority(&self) -> &Signer<'info> {
67        &self.authority
68    }
69
70    fn store(&self) -> &AccountLoader<'info, Store> {
71        &self.store
72    }
73}
74
75/// The accounts definition for [`set_prices_from_price_feed`](crate::gmsol_store::set_prices_from_price_feed).
76///
77/// Remaining accounts expected by this instruction:
78///
79///   - 0..N. `[]` N feed accounts, where N represents the total number of tokens.
80#[derive(Accounts)]
81pub struct SetPricesFromPriceFeed<'info> {
82    /// The caller.
83    pub authority: Signer<'info>,
84    /// Store.
85    #[account(has_one = token_map)]
86    pub store: AccountLoader<'info, Store>,
87    /// Oracle.
88    #[account(
89        mut,
90        has_one = store,
91        has_one = authority,
92    )]
93    pub oracle: AccountLoader<'info, Oracle>,
94    /// Token map.
95    #[account(has_one = store)]
96    pub token_map: AccountLoader<'info, TokenMapHeader>,
97    /// Chainlink Program.
98    pub chainlink_program: Option<Program<'info, Chainlink>>,
99}
100
101/// Set the oracle prices from price feeds.
102/// CHECK: only ORACLE_CONTROLLER is allowed to invoke.
103pub(crate) fn unchecked_set_prices_from_price_feed<'info>(
104    ctx: Context<'_, '_, 'info, 'info, SetPricesFromPriceFeed<'info>>,
105    tokens: Vec<Pubkey>,
106) -> Result<()> {
107    let validator = PriceValidator::try_from(ctx.accounts.store.load()?.deref())?;
108    let token_map = ctx.accounts.token_map.load_token_map()?;
109    ctx.accounts
110        .oracle
111        .load_mut()?
112        .set_prices_from_remaining_accounts(
113            validator,
114            &token_map,
115            &tokens,
116            ctx.remaining_accounts,
117            ctx.accounts.chainlink_program.as_ref(),
118        )
119}
120
121impl<'info> internal::Authentication<'info> for SetPricesFromPriceFeed<'info> {
122    fn authority(&self) -> &Signer<'info> {
123        &self.authority
124    }
125
126    fn store(&self) -> &AccountLoader<'info, Store> {
127        &self.store
128    }
129}