use std::sync::Arc;
use crate::borrow::errors::ErrorCodes;
use crate::math::casting::Cast;
use crate::oracle::{OraclePriceLiquidate, ORACLE_PROGRAM_ID};
use crate::programs::oracle;
use crate::ReadKeypair;
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 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?;
let mut remaining_accounts = vec![];
for source in &oracle_data.sources {
remaining_accounts.push(AccountMeta::new_readonly(source.source, false));
}
get_oracle_price_liquidate_from_remaining_accounts(
oracle,
&remaining_accounts,
&vec![remaining_accounts.len() as u8],
cluster,
)
.await
}
pub async fn get_oracle_price_liquidate_from_remaining_accounts(
oracle: Pubkey,
remaining_accounts: &Vec<AccountMeta>,
remaining_accounts_indices: &Vec<u8>,
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?;
let mut price = 0;
let start_index: usize = 0;
let end_index: usize = start_index + remaining_accounts_indices[0].cast::<usize>()?;
if remaining_accounts.len() < end_index {
return Err(ErrorCodes::VaultLiquidateRemainingAccountsTooShort.into());
}
let remaining_accounts = remaining_accounts
.iter()
.take(end_index)
.skip(start_index)
.map(|x| x.clone())
.collect::<Vec<_>>();
let instructions = program
.request()
.accounts(oracle::client::accounts::GetExchangeRateLiquidate { oracle })
.accounts(remaining_accounts)
.args(oracle::client::args::GetExchangeRateLiquidate {
_nonce: oracle_data.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()
},
)
.await?;
if let Some(data) = &simulation.value.return_data {
#[allow(deprecated)]
let raw_bytes = base64::decode(&data.data.0)?;
price = u128::from_le_bytes(raw_bytes.try_into().unwrap());
}
Ok(OraclePriceLiquidate {
price,
sources: oracle_data.sources,
})
}