jup_lend_sdk/oracle/
simulations.rs1use std::sync::Arc;
2
3use crate::borrow::errors::ErrorCodes;
4use crate::math::casting::Cast;
5use crate::oracle::{OraclePriceLiquidate, ORACLE_PROGRAM_ID};
6use crate::programs::oracle;
7use crate::ReadKeypair;
8
9use anchor_client::solana_sdk::message::Message;
10use anchor_client::solana_sdk::transaction::Transaction;
11use anchor_client::{
12 solana_client::rpc_config::RpcSimulateTransactionConfig,
13 solana_sdk::{commitment_config::CommitmentConfig, signer::Signer},
14 Client, Cluster,
15};
16use anchor_lang::prelude::{AccountMeta, Pubkey};
17
18pub async fn get_oracle_price_liquidate(
19 oracle: Pubkey,
20 cluster: Cluster,
21) -> anyhow::Result<OraclePriceLiquidate> {
22 let payer = ReadKeypair::new();
23 let provider = Client::new_with_options(
24 cluster.clone(),
25 Arc::new(payer.clone()),
26 CommitmentConfig::processed(),
27 );
28 let program = provider.program(ORACLE_PROGRAM_ID)?;
29 let oracle_data: oracle::accounts::Oracle = program.account(oracle).await?;
30
31 let mut remaining_accounts = vec![];
32
33 for source in &oracle_data.sources {
34 remaining_accounts.push(AccountMeta::new_readonly(source.source, false));
35 }
36
37 get_oracle_price_liquidate_from_remaining_accounts(
38 oracle,
39 &remaining_accounts,
40 &vec![remaining_accounts.len() as u8],
41 cluster,
42 )
43 .await
44}
45
46pub async fn get_oracle_price_liquidate_from_remaining_accounts(
47 oracle: Pubkey,
48 remaining_accounts: &Vec<AccountMeta>,
49 remaining_accounts_indices: &Vec<u8>,
50 cluster: Cluster,
51) -> anyhow::Result<OraclePriceLiquidate> {
52 let payer = ReadKeypair::new();
53 let provider = Client::new_with_options(
54 cluster.clone(),
55 Arc::new(payer.clone()),
56 CommitmentConfig::processed(),
57 );
58 let program = provider.program(ORACLE_PROGRAM_ID)?;
59 let oracle_data: oracle::accounts::Oracle = program.account(oracle).await?;
60
61 let mut price = 0;
62
63 let start_index: usize = 0;
64 let end_index: usize = start_index + remaining_accounts_indices[0].cast::<usize>()?;
65
66 if remaining_accounts.len() < end_index {
67 return Err(ErrorCodes::VaultLiquidateRemainingAccountsTooShort.into());
68 }
69
70 let remaining_accounts = remaining_accounts
71 .iter()
72 .take(end_index)
73 .skip(start_index)
74 .map(|x| x.clone())
75 .collect::<Vec<_>>();
76
77 let instructions = program
78 .request()
79 .accounts(oracle::client::accounts::GetExchangeRateLiquidate { oracle })
80 .accounts(remaining_accounts)
81 .args(oracle::client::args::GetExchangeRateLiquidate {
82 _nonce: oracle_data.nonce,
83 })
84 .instructions()?;
85
86 let message = Message::new(&instructions, Some(&payer.pubkey()));
87 let transaction = Transaction::new_unsigned(message);
88
89 let simulation = program
90 .rpc()
91 .simulate_transaction_with_config(
92 &transaction,
93 RpcSimulateTransactionConfig {
94 replace_recent_blockhash: true,
95 sig_verify: false,
96 ..Default::default()
97 },
98 )
99 .await?;
100
101 if let Some(data) = &simulation.value.return_data {
102 #[allow(deprecated)]
103 let raw_bytes = base64::decode(&data.data.0)?;
104 price = u128::from_le_bytes(raw_bytes.try_into().unwrap());
105 }
106
107 Ok(OraclePriceLiquidate {
108 price,
109 sources: oracle_data.sources,
110 })
111}