1use solana_client::rpc_client::RpcClient;
2use solana_sdk::{
3 pubkey::Pubkey,
4 signature::{Keypair, Signer},
5 transaction::Transaction,
6};
7use crate::instructions::{build_deposit_ix, build_withdraw_ix, build_execute_trade_ix, build_keeper_crank_ix};
8use crate::accounts::{fetch_risk_engine, RiskEngine, Account};
9
10pub struct PercolatorClient {
15 pub client: RpcClient,
17 pub program_id: Pubkey,
19 pub engine_state: Pubkey,
21}
22
23impl PercolatorClient {
24 pub fn new(rpc_url: &str, program_id: Pubkey, engine_state: Pubkey) -> Self {
26 Self {
27 client: RpcClient::new(rpc_url.to_string()),
28 program_id,
29 engine_state,
30 }
31 }
32
33 pub fn get_engine_state(&self) -> Result<RiskEngine, Box<dyn std::error::Error>> {
35 fetch_risk_engine(&self.client, &self.engine_state)
36 }
37
38 pub fn get_account(&self, index: usize) -> Result<Option<Account>, Box<dyn std::error::Error>> {
40 let engine = self.get_engine_state()?;
41 if index < crate::percolator::MAX_ACCOUNTS && engine.is_used(index) {
42 Ok(Some(engine.accounts[index].clone()))
43 } else {
44 Ok(None)
45 }
46 }
47
48 pub fn send_deposit(
50 &self,
51 payer: &Keypair,
52 account_index: u64,
53 amount: u128,
54 now_slot: u64,
55 ) -> Result<String, Box<dyn std::error::Error>> {
56 let ix = build_deposit_ix(
57 self.program_id,
58 self.engine_state,
59 payer.pubkey(),
60 account_index,
61 amount,
62 now_slot,
63 );
64
65 let recent_blockhash = self.client.get_latest_blockhash()?;
66 let tx = Transaction::new_signed_with_payer(
67 &[ix],
68 Some(&payer.pubkey()),
69 &[payer],
70 recent_blockhash,
71 );
72
73 let sig = self.client.send_and_confirm_transaction(&tx)?;
74 Ok(sig.to_string())
75 }
76
77 pub fn send_withdraw(
79 &self,
80 payer: &Keypair,
81 account_index: u64,
82 amount: u128,
83 now_slot: u64,
84 oracle_price: u64,
85 ) -> Result<String, Box<dyn std::error::Error>> {
86 let ix = build_withdraw_ix(
87 self.program_id,
88 self.engine_state,
89 payer.pubkey(),
90 account_index,
91 amount,
92 now_slot,
93 oracle_price,
94 );
95
96 let recent_blockhash = self.client.get_latest_blockhash()?;
97 let tx = Transaction::new_signed_with_payer(
98 &[ix],
99 Some(&payer.pubkey()),
100 &[payer],
101 recent_blockhash,
102 );
103
104 let sig = self.client.send_and_confirm_transaction(&tx)?;
105 Ok(sig.to_string())
106 }
107
108 pub fn send_trade(
110 &self,
111 payer: &Keypair,
112 lp_index: u64,
113 user_index: u64,
114 now_slot: u64,
115 oracle_price: u64,
116 size: i128,
117 ) -> Result<String, Box<dyn std::error::Error>> {
118 let ix = build_execute_trade_ix(
119 self.program_id,
120 self.engine_state,
121 payer.pubkey(),
122 lp_index,
123 user_index,
124 now_slot,
125 oracle_price,
126 size,
127 );
128
129 let recent_blockhash = self.client.get_latest_blockhash()?;
130 let tx = Transaction::new_signed_with_payer(
131 &[ix],
132 Some(&payer.pubkey()),
133 &[payer],
134 recent_blockhash,
135 );
136
137 let sig = self.client.send_and_confirm_transaction(&tx)?;
138 Ok(sig.to_string())
139 }
140
141 pub fn send_crank(
143 &self,
144 payer: &Keypair,
145 caller_index: u64,
146 now_slot: u64,
147 oracle_price: u64,
148 funding_rate: i64,
149 allow_panic: bool,
150 ) -> Result<String, Box<dyn std::error::Error>> {
151 let ix = build_keeper_crank_ix(
152 self.program_id,
153 self.engine_state,
154 payer.pubkey(),
155 caller_index,
156 now_slot,
157 oracle_price,
158 funding_rate,
159 allow_panic,
160 );
161
162 let recent_blockhash = self.client.get_latest_blockhash()?;
163 let tx = Transaction::new_signed_with_payer(
164 &[ix],
165 Some(&payer.pubkey()),
166 &[payer],
167 recent_blockhash,
168 );
169
170 let sig = self.client.send_and_confirm_transaction(&tx)?;
171 Ok(sig.to_string())
172 }
173}