streak-api 0.1.7

API for interacting with the STREAK directional markets protocol on Solana
Documentation
//! Price-chain settlement helper for `AdminInstantSettlement`.
//!
//! Reads the open reference from `Treasury::last_close_*`, reads the Pyth close price,
//! resolves UP/DOWN, emits `PeriodSettled`, and writes the close price back to Treasury.
//! All market pool math and USDC distribution happen off-chain.

use steel::*;

use crate::consts::PYTH_BTC_USD_FEED_ID;
use crate::error::StreakError;
use crate::event::PeriodSettled;
use crate::pyth::{load_fresh_price, outcome_from_open_close, Price};
use crate::state::Treasury;

pub struct SettlementResult {
    pub outcome: u8,
    pub close_px: Price,
    pub open_px: Price,
}

/// Read open from Treasury, read close from Pyth, return outcome + both prices.
/// Returns `Err(GenesisNotSet)` if the price chain has not been seeded.
pub fn resolve_settlement(
    treasury: &Treasury,
    pyth_price_feed_info: &AccountInfo<'_>,
    unix_timestamp: i64,
) -> Result<SettlementResult, ProgramError> {
    if treasury.last_close_price == 0 {
        return Err(StreakError::GenesisNotSet.into());
    }

    let open_px = Price {
        price: treasury.last_close_price,
        conf: 0,
        expo: treasury.last_close_expo,
        publish_time: treasury.last_close_publish_time,
    };

    let close_px = load_fresh_price(pyth_price_feed_info, &PYTH_BTC_USD_FEED_ID, unix_timestamp)?;
    let outcome = outcome_from_open_close(open_px, close_px)?;

    Ok(SettlementResult { outcome, close_px, open_px })
}

/// Write close price back to Treasury and emit the `PeriodSettled` event.
pub fn commit_settlement(
    treasury: &mut Treasury,
    result: SettlementResult,
    series_id: u16,
    period: u64,
) {
    PeriodSettled {
        series_id,
        outcome: result.outcome,
        _pad: [0; 5],
        period,
        close_price: result.close_px.price,
        close_expo: result.close_px.expo,
        _pad2: [0; 4],
        close_publish_time: result.close_px.publish_time,
        open_price: result.open_px.price,
        open_expo: result.open_px.expo,
        _pad3: [0; 4],
    }
    .log();

    treasury.last_close_price = result.close_px.price;
    treasury.last_close_expo = result.close_px.expo;
    treasury.last_close_publish_time = result.close_px.publish_time;
}

/// UP outcome constant (close > open).
pub const SIDE_UP: u8 = 0;
/// DOWN outcome constant (close <= open, including ties).
pub const SIDE_DOWN: u8 = 1;