jup-lend-sdk 0.2.7

SDK for Jupiter lending protocol
Documentation
use anchor_client::{solana_sdk::commitment_config::CommitmentConfig, Client, Cluster};
use anchor_lang::{prelude::Pubkey, AccountDeserialize};
use anyhow::Ok;
use pyth_solana_receiver_sdk::price_update::PriceUpdateV2;
use std::sync::Arc;

use crate::{
    math::{casting::Cast, safe_math::SafeMath},
    oracle::{OraclePriceLiquidate, ORACLE_PROGRAM_ID},
    programs::oracle,
    ReadKeypair,
};

pub const RATE_OUTPUT_DECIMALS: u32 = 15;

pub async fn get_oracle_price_liquidate(
    oracle: Pubkey,
    cluster: Cluster,
) -> anyhow::Result<OraclePriceLiquidate> {
    let payer = ReadKeypair::new();
    let provider = Client::new_with_options(
        cluster.clone(),
        Arc::new(payer.clone()),
        CommitmentConfig::confirmed(),
    );
    let program = provider.program(ORACLE_PROGRAM_ID)?;
    let oracle_data: oracle::accounts::Oracle = program.account(oracle).await?;

    if oracle_data.sources.len() == 0 {
        return Err(anyhow::anyhow!("No sources found"));
    }

    let source = oracle_data.sources[0];

    let price = match source.source_type {
        oracle::types::SourceType::Pyth => {
            let rpc = program.rpc();

            let account = rpc.get_account(&source.source).await?;

            let mut price_update_data: &[u8] = account.data.iter().as_slice();

            let price_update = PriceUpdateV2::try_deserialize(&mut price_update_data).unwrap();

            if price_update.price_message.price <= 0 || price_update.price_message.exponent > 0 {
                return Err(anyhow::anyhow!("Price is not valid"));
            }

            let multiplier: u32 = price_update.price_message.exponent.abs().cast()?;
            let delta = 10u128.pow(RATE_OUTPUT_DECIMALS.safe_sub(multiplier)?);

            price_update
                .price_message
                .price
                .cast::<u128>()?
                .safe_mul(delta)?
                .saturating_div(source.divisor)
        }
        oracle::types::SourceType::StakePool => {
            return Err(anyhow::anyhow!("Unsupported source type"));
        }
    };

    Ok(OraclePriceLiquidate {
        price,
        sources: oracle_data.sources,
    })
}