oil-api 0.7.8

API for interacting with the OIL protocol on Solana
Documentation
use serde::{Deserialize, Serialize};
use steel::*;

use crate::state::oil_oracle_pda;

use super::OilAccount;

/// OIL price oracle (Valiant-backed; updated by centralized authority).
/// Price is stored as FOGO lamports per 1 OIL: fee_lamports = claimable_atomic * price * 35 / (100 * ONE_OIL).
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
pub struct OilPriceOracle {
    /// Price: FOGO lamports per 1 OIL (expo applied separately for scaling; here expo is 0 for this interpretation).
    pub price: u64,
    /// Exponent for price (e.g. -9 if price is in FOGO units with 9 decimals). Currently use price as lamports per 1 OIL, expo = 0.
    pub expo: i32,
    #[allow(dead_code)]
    /// Padding for alignment (repr(C) after i32).
    pub _pad: i32,
    /// Confidence interval (optional; for future use).
    pub conf: u64,
    /// EMA price (optional; for future use).
    pub ema: u64,
    /// Unix timestamp when price was last updated.
    pub publish_time: i64,
    /// Authority allowed to call SetOilOraclePrice.
    pub oracle_authority: Pubkey,
}

impl OilPriceOracle {
    pub const LEN: usize = 8 + 8 + 4 + 4 + 8 + 8 + 8 + 32; // 8 discriminator? no - we use Pod. So 8+4+4+8+8+8+32 = 72

    pub fn pda() -> (Pubkey, u8) {
        oil_oracle_pda()
    }

    /// Set price data (called by SetOilOraclePrice).
    pub fn set(&mut self, price: u64, expo: i32, conf: u64, ema: u64, publish_time: i64) {
        self.price = price;
        self.expo = expo;
        self.conf = conf;
        self.ema = ema;
        self.publish_time = publish_time;
    }

    /// Required fee in lamports for a given claimable amount (atomic OIL).
    /// fee = claimable_atomic * price * 35 / (100 * ONE_OIL). Uses expo if needed; with expo=0, price is lamports per 1 OIL.
    pub fn required_fee_lamports(&self, claimable_atomic: u64) -> u64 {
        if self.price == 0 {
            return 0;
        }
        // required = claimable_atomic * price * 35 / (100 * ONE_OIL)
        let one_oil = crate::consts::ONE_OIL as u128;
        let num = (claimable_atomic as u128)
            .saturating_mul(self.price as u128)
            .saturating_mul(35);
        let den = 100u128.saturating_mul(one_oil);
        (num / den) as u64
    }
}

account!(OilAccount, OilPriceOracle);