use std::rc::Rc;
use crate::programs::oracle::ID;
use crate::programs::{oracle, oracle::types::Sources};
use anchor_client::solana_sdk::message::Message;
use anchor_client::solana_sdk::transaction::Transaction;
use anchor_client::{
solana_client::rpc_config::RpcSimulateTransactionConfig,
solana_sdk::{commitment_config::CommitmentConfig, signer::Signer},
Client, Cluster,
};
use anchor_lang::prelude::{AccountMeta, Pubkey};
pub const ORACLE_PROGRAM_ID: Pubkey = ID;
#[derive(Debug, Clone)]
pub struct OraclePriceLiquidate {
pub price: u128,
pub sources: Vec<Sources>,
}
#[derive(Debug, Clone)]
pub struct OraclePriceLiquidateParams {
pub oracle: Pubkey,
pub cluster: Cluster,
}
#[derive(Debug, Clone)]
struct Keypair;
impl Keypair {
fn new() -> Self {
Keypair
}
}
impl Signer for Keypair {
fn pubkey(&self) -> Pubkey {
Pubkey::from_str_const("HEyJLdMfZhhQ7FHCtjD5DWDFNFQhaeAVAsHeWqoY6dSD")
}
fn try_pubkey(&self) -> Result<Pubkey, anchor_client::solana_sdk::signer::SignerError> {
Ok(self.pubkey())
}
fn try_sign_message(
&self,
_message: &[u8],
) -> Result<
anchor_client::solana_sdk::signature::Signature,
anchor_client::solana_sdk::signer::SignerError,
> {
Ok(anchor_client::solana_sdk::signature::Signature::default())
}
fn is_interactive(&self) -> bool {
true
}
}
pub fn get_oracle_price_liquidate(
params: OraclePriceLiquidateParams,
) -> anyhow::Result<OraclePriceLiquidate> {
let payer = Keypair::new();
let provider = Client::new_with_options(
params.cluster.clone(),
Rc::new(payer.clone()),
CommitmentConfig::confirmed(),
);
let program = provider.program(ORACLE_PROGRAM_ID)?;
let oracle: oracle::accounts::Oracle = program.account(params.oracle)?;
let mut remaining_accounts = vec![];
for source in &oracle.sources {
remaining_accounts.push(AccountMeta::new_readonly(source.source, false));
}
let mut price = 0;
let instructions = program
.request()
.accounts(oracle::client::accounts::GetExchangeRateLiquidate {
oracle: params.oracle,
})
.accounts(remaining_accounts)
.args(oracle::client::args::GetExchangeRateLiquidate {
_nonce: oracle.nonce,
})
.instructions()?;
let message = Message::new(&instructions, Some(&payer.pubkey()));
let transaction = Transaction::new_unsigned(message);
let simulation = program.rpc().simulate_transaction_with_config(
&transaction,
RpcSimulateTransactionConfig {
replace_recent_blockhash: true,
sig_verify: false,
..Default::default()
},
)?;
if let Some(data) = &simulation.value.return_data {
let raw_bytes = base64::decode(&data.data.0)?;
price = u128::from_le_bytes(raw_bytes.try_into().unwrap());
}
Ok(OraclePriceLiquidate {
price,
sources: oracle.sources,
})
}