1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use crate::*;
use anchor_lang::prelude::AccountInfo;
use bytemuck::{cast_slice_mut, from_bytes_mut, try_cast_slice_mut, Pod, Zeroable};
use std::cell::RefMut;

#[derive(Default, Copy, Clone)]
#[repr(C)]
pub struct AccKey {
    pub val: [u8; 32],
}

#[derive(PartialEq, Debug, Copy, Clone)]
#[repr(C)]
pub enum PriceStatus {
    Unknown = 0,
    Trading = 1,
    Halted = 2,
    Auction = 3,
}

impl Default for PriceStatus {
    fn default() -> Self {
        PriceStatus::Trading
    }
}

#[derive(Copy, Clone)]
#[repr(C)]
pub enum CorpAction {
    NoCorpAct,
}

impl Default for CorpAction {
    fn default() -> Self {
        CorpAction::NoCorpAct
    }
}

#[derive(Default, Copy, Clone)]
#[repr(C)]
pub struct PriceInfo {
    pub price: i64,
    pub conf: u64,
    pub status: PriceStatus,
    pub corp_act: CorpAction,
    pub pub_slot: u64,
}
#[derive(Default, Copy, Clone)]
#[repr(C)]
pub struct PriceComp {
    publisher: AccKey,
    agg: PriceInfo,
    latest: PriceInfo,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub enum PriceType {
    Unknown,
    Price,
    TWAP,
    Volatility,
}

impl Into<u8> for PriceStatus {
    fn into(self) -> u8 {
        match self {
            PriceStatus::Unknown => 0,
            PriceStatus::Trading => 1,
            PriceStatus::Halted => 2,
            PriceStatus::Auction => 3,
        }
    }
}

impl Default for PriceType {
    fn default() -> Self {
        PriceType::Price
    }
}

#[derive(Default, Copy, Clone)]
#[repr(C)]
pub struct Ema {
    pub val: i64, // Current value of ema
    numer: i64,   // Numerator state for next update
    denom: i64,   // Denominator state for next update
}
#[derive(Default, Copy, Clone)]
#[repr(C)]
pub struct Price {
    pub magic: u32,            // Pyth magic number
    pub ver: u32,              // Program version
    pub atype: u32,            // Account type
    pub size: u32,             // Price account size
    pub ptype: PriceType,      // Price or calculation type
    pub expo: i32,             // Price exponent
    pub num: u32,              // Number of component prices
    pub num_qt: u32,           // Number of quoters that make up aggregate
    pub last_slot: u64,        // Slot of last valid (not unknown) aggregate price
    pub valid_slot: u64,       // Valid slot-time of agg. price
    pub twap: Ema,             // Time-weighted average price
    pub twac: Ema,             // Time-weighted average confidence interval
    pub drv1: i64,             // Space for future derived values
    pub drv2: i64,             // Space for future derived values
    pub prod: AccKey,          // Product account key
    pub next: AccKey,          // Next Price account in linked list
    pub prev_slot: u64,        // Valid slot of previous update
    pub prev_price: i64,       // Aggregate price of previous update
    pub prev_conf: u64,        // Confidence interval of previous update
    pub drv3: i64,             // Space for future derived values
    pub agg: PriceInfo,        // Aggregate price info
    pub comp: [PriceComp; 32], // Price components one per quoter
}

impl Price {
    #[inline]
    pub fn load<'a>(price_feed: &'a AccountInfo) -> Result<RefMut<'a, Price>, ProgramError> {
        let account_data: RefMut<'a, [u8]>;
        let state: RefMut<'a, Self>;

        account_data = RefMut::map(price_feed.try_borrow_mut_data().unwrap(), |data| *data);

        state = RefMut::map(account_data, |data| {
            from_bytes_mut(cast_slice_mut::<u8, u8>(try_cast_slice_mut(data).unwrap()))
        });
        Ok(state)
    }
}

#[cfg(target_endian = "little")]
unsafe impl Zeroable for Price {}

#[cfg(target_endian = "little")]
unsafe impl Pod for Price {}