1use borsh::BorshSerialize;
9use borsh::BorshDeserialize;
10
11#[derive(Debug)]
13pub struct Withdraw {
14
15
16 pub authority: solana_pubkey::Pubkey,
17
18
19 pub treasury: solana_pubkey::Pubkey,
20
21
22 pub position: solana_pubkey::Pubkey,
23
24
25 pub treasury_staked_token_account: solana_pubkey::Pubkey,
26
27
28 pub treasury_reward_token_account: solana_pubkey::Pubkey,
29
30
31 pub authority_staked_token_account: solana_pubkey::Pubkey,
32
33
34 pub authority_reward_token_account: solana_pubkey::Pubkey,
35
36
37 pub token_program: solana_pubkey::Pubkey,
38 }
39
40impl Withdraw {
41 pub fn instruction(&self) -> solana_instruction::Instruction {
42 self.instruction_with_remaining_accounts(&[])
43 }
44 #[allow(clippy::arithmetic_side_effects)]
45 #[allow(clippy::vec_init_then_push)]
46 pub fn instruction_with_remaining_accounts(&self, remaining_accounts: &[solana_instruction::AccountMeta]) -> solana_instruction::Instruction {
47 let mut accounts = Vec::with_capacity(8+ remaining_accounts.len());
48 accounts.push(solana_instruction::AccountMeta::new(
49 self.authority,
50 true
51 ));
52 accounts.push(solana_instruction::AccountMeta::new(
53 self.treasury,
54 false
55 ));
56 accounts.push(solana_instruction::AccountMeta::new(
57 self.position,
58 false
59 ));
60 accounts.push(solana_instruction::AccountMeta::new(
61 self.treasury_staked_token_account,
62 false
63 ));
64 accounts.push(solana_instruction::AccountMeta::new(
65 self.treasury_reward_token_account,
66 false
67 ));
68 accounts.push(solana_instruction::AccountMeta::new(
69 self.authority_staked_token_account,
70 false
71 ));
72 accounts.push(solana_instruction::AccountMeta::new(
73 self.authority_reward_token_account,
74 false
75 ));
76 accounts.push(solana_instruction::AccountMeta::new_readonly(
77 self.token_program,
78 false
79 ));
80 accounts.extend_from_slice(remaining_accounts);
81 let data = borsh::to_vec(&WithdrawInstructionData::new()).unwrap();
82
83 solana_instruction::Instruction {
84 program_id: crate::TUNA_STAKING_ID,
85 accounts,
86 data,
87 }
88 }
89}
90
91#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)]
92#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
93 pub struct WithdrawInstructionData {
94 discriminator: [u8; 8],
95 }
96
97impl WithdrawInstructionData {
98 pub fn new() -> Self {
99 Self {
100 discriminator: [183, 18, 70, 156, 148, 109, 161, 34],
101 }
102 }
103}
104
105impl Default for WithdrawInstructionData {
106 fn default() -> Self {
107 Self::new()
108 }
109}
110
111
112
113#[derive(Clone, Debug, Default)]
126pub struct WithdrawBuilder {
127 authority: Option<solana_pubkey::Pubkey>,
128 treasury: Option<solana_pubkey::Pubkey>,
129 position: Option<solana_pubkey::Pubkey>,
130 treasury_staked_token_account: Option<solana_pubkey::Pubkey>,
131 treasury_reward_token_account: Option<solana_pubkey::Pubkey>,
132 authority_staked_token_account: Option<solana_pubkey::Pubkey>,
133 authority_reward_token_account: Option<solana_pubkey::Pubkey>,
134 token_program: Option<solana_pubkey::Pubkey>,
135 __remaining_accounts: Vec<solana_instruction::AccountMeta>,
136}
137
138impl WithdrawBuilder {
139 pub fn new() -> Self {
140 Self::default()
141 }
142 #[inline(always)]
143 pub fn authority(&mut self, authority: solana_pubkey::Pubkey) -> &mut Self {
144 self.authority = Some(authority);
145 self
146 }
147 #[inline(always)]
148 pub fn treasury(&mut self, treasury: solana_pubkey::Pubkey) -> &mut Self {
149 self.treasury = Some(treasury);
150 self
151 }
152 #[inline(always)]
153 pub fn position(&mut self, position: solana_pubkey::Pubkey) -> &mut Self {
154 self.position = Some(position);
155 self
156 }
157 #[inline(always)]
158 pub fn treasury_staked_token_account(&mut self, treasury_staked_token_account: solana_pubkey::Pubkey) -> &mut Self {
159 self.treasury_staked_token_account = Some(treasury_staked_token_account);
160 self
161 }
162 #[inline(always)]
163 pub fn treasury_reward_token_account(&mut self, treasury_reward_token_account: solana_pubkey::Pubkey) -> &mut Self {
164 self.treasury_reward_token_account = Some(treasury_reward_token_account);
165 self
166 }
167 #[inline(always)]
168 pub fn authority_staked_token_account(&mut self, authority_staked_token_account: solana_pubkey::Pubkey) -> &mut Self {
169 self.authority_staked_token_account = Some(authority_staked_token_account);
170 self
171 }
172 #[inline(always)]
173 pub fn authority_reward_token_account(&mut self, authority_reward_token_account: solana_pubkey::Pubkey) -> &mut Self {
174 self.authority_reward_token_account = Some(authority_reward_token_account);
175 self
176 }
177 #[inline(always)]
179 pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self {
180 self.token_program = Some(token_program);
181 self
182 }
183 #[inline(always)]
185 pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self {
186 self.__remaining_accounts.push(account);
187 self
188 }
189 #[inline(always)]
191 pub fn add_remaining_accounts(&mut self, accounts: &[solana_instruction::AccountMeta]) -> &mut Self {
192 self.__remaining_accounts.extend_from_slice(accounts);
193 self
194 }
195 #[allow(clippy::clone_on_copy)]
196 pub fn instruction(&self) -> solana_instruction::Instruction {
197 let accounts = Withdraw {
198 authority: self.authority.expect("authority is not set"),
199 treasury: self.treasury.expect("treasury is not set"),
200 position: self.position.expect("position is not set"),
201 treasury_staked_token_account: self.treasury_staked_token_account.expect("treasury_staked_token_account is not set"),
202 treasury_reward_token_account: self.treasury_reward_token_account.expect("treasury_reward_token_account is not set"),
203 authority_staked_token_account: self.authority_staked_token_account.expect("authority_staked_token_account is not set"),
204 authority_reward_token_account: self.authority_reward_token_account.expect("authority_reward_token_account is not set"),
205 token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")),
206 };
207
208 accounts.instruction_with_remaining_accounts(&self.__remaining_accounts)
209 }
210}
211
212 pub struct WithdrawCpiAccounts<'a, 'b> {
214
215
216 pub authority: &'b solana_account_info::AccountInfo<'a>,
217
218
219 pub treasury: &'b solana_account_info::AccountInfo<'a>,
220
221
222 pub position: &'b solana_account_info::AccountInfo<'a>,
223
224
225 pub treasury_staked_token_account: &'b solana_account_info::AccountInfo<'a>,
226
227
228 pub treasury_reward_token_account: &'b solana_account_info::AccountInfo<'a>,
229
230
231 pub authority_staked_token_account: &'b solana_account_info::AccountInfo<'a>,
232
233
234 pub authority_reward_token_account: &'b solana_account_info::AccountInfo<'a>,
235
236
237 pub token_program: &'b solana_account_info::AccountInfo<'a>,
238 }
239
240pub struct WithdrawCpi<'a, 'b> {
242 pub __program: &'b solana_account_info::AccountInfo<'a>,
244
245
246 pub authority: &'b solana_account_info::AccountInfo<'a>,
247
248
249 pub treasury: &'b solana_account_info::AccountInfo<'a>,
250
251
252 pub position: &'b solana_account_info::AccountInfo<'a>,
253
254
255 pub treasury_staked_token_account: &'b solana_account_info::AccountInfo<'a>,
256
257
258 pub treasury_reward_token_account: &'b solana_account_info::AccountInfo<'a>,
259
260
261 pub authority_staked_token_account: &'b solana_account_info::AccountInfo<'a>,
262
263
264 pub authority_reward_token_account: &'b solana_account_info::AccountInfo<'a>,
265
266
267 pub token_program: &'b solana_account_info::AccountInfo<'a>,
268 }
269
270impl<'a, 'b> WithdrawCpi<'a, 'b> {
271 pub fn new(
272 program: &'b solana_account_info::AccountInfo<'a>,
273 accounts: WithdrawCpiAccounts<'a, 'b>,
274 ) -> Self {
275 Self {
276 __program: program,
277 authority: accounts.authority,
278 treasury: accounts.treasury,
279 position: accounts.position,
280 treasury_staked_token_account: accounts.treasury_staked_token_account,
281 treasury_reward_token_account: accounts.treasury_reward_token_account,
282 authority_staked_token_account: accounts.authority_staked_token_account,
283 authority_reward_token_account: accounts.authority_reward_token_account,
284 token_program: accounts.token_program,
285 }
286 }
287 #[inline(always)]
288 pub fn invoke(&self) -> solana_program_entrypoint::ProgramResult {
289 self.invoke_signed_with_remaining_accounts(&[], &[])
290 }
291 #[inline(always)]
292 pub fn invoke_with_remaining_accounts(&self, remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)]) -> solana_program_entrypoint::ProgramResult {
293 self.invoke_signed_with_remaining_accounts(&[], remaining_accounts)
294 }
295 #[inline(always)]
296 pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_entrypoint::ProgramResult {
297 self.invoke_signed_with_remaining_accounts(signers_seeds, &[])
298 }
299 #[allow(clippy::arithmetic_side_effects)]
300 #[allow(clippy::clone_on_copy)]
301 #[allow(clippy::vec_init_then_push)]
302 pub fn invoke_signed_with_remaining_accounts(
303 &self,
304 signers_seeds: &[&[&[u8]]],
305 remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)]
306 ) -> solana_program_entrypoint::ProgramResult {
307 let mut accounts = Vec::with_capacity(8+ remaining_accounts.len());
308 accounts.push(solana_instruction::AccountMeta::new(
309 *self.authority.key,
310 true
311 ));
312 accounts.push(solana_instruction::AccountMeta::new(
313 *self.treasury.key,
314 false
315 ));
316 accounts.push(solana_instruction::AccountMeta::new(
317 *self.position.key,
318 false
319 ));
320 accounts.push(solana_instruction::AccountMeta::new(
321 *self.treasury_staked_token_account.key,
322 false
323 ));
324 accounts.push(solana_instruction::AccountMeta::new(
325 *self.treasury_reward_token_account.key,
326 false
327 ));
328 accounts.push(solana_instruction::AccountMeta::new(
329 *self.authority_staked_token_account.key,
330 false
331 ));
332 accounts.push(solana_instruction::AccountMeta::new(
333 *self.authority_reward_token_account.key,
334 false
335 ));
336 accounts.push(solana_instruction::AccountMeta::new_readonly(
337 *self.token_program.key,
338 false
339 ));
340 remaining_accounts.iter().for_each(|remaining_account| {
341 accounts.push(solana_instruction::AccountMeta {
342 pubkey: *remaining_account.0.key,
343 is_signer: remaining_account.1,
344 is_writable: remaining_account.2,
345 })
346 });
347 let data = borsh::to_vec(&WithdrawInstructionData::new()).unwrap();
348
349 let instruction = solana_instruction::Instruction {
350 program_id: crate::TUNA_STAKING_ID,
351 accounts,
352 data,
353 };
354 let mut account_infos = Vec::with_capacity(9 + remaining_accounts.len());
355 account_infos.push(self.__program.clone());
356 account_infos.push(self.authority.clone());
357 account_infos.push(self.treasury.clone());
358 account_infos.push(self.position.clone());
359 account_infos.push(self.treasury_staked_token_account.clone());
360 account_infos.push(self.treasury_reward_token_account.clone());
361 account_infos.push(self.authority_staked_token_account.clone());
362 account_infos.push(self.authority_reward_token_account.clone());
363 account_infos.push(self.token_program.clone());
364 remaining_accounts.iter().for_each(|remaining_account| account_infos.push(remaining_account.0.clone()));
365
366 if signers_seeds.is_empty() {
367 solana_cpi::invoke(&instruction, &account_infos)
368 } else {
369 solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds)
370 }
371 }
372}
373
374#[derive(Clone, Debug)]
387pub struct WithdrawCpiBuilder<'a, 'b> {
388 instruction: Box<WithdrawCpiBuilderInstruction<'a, 'b>>,
389}
390
391impl<'a, 'b> WithdrawCpiBuilder<'a, 'b> {
392 pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self {
393 let instruction = Box::new(WithdrawCpiBuilderInstruction {
394 __program: program,
395 authority: None,
396 treasury: None,
397 position: None,
398 treasury_staked_token_account: None,
399 treasury_reward_token_account: None,
400 authority_staked_token_account: None,
401 authority_reward_token_account: None,
402 token_program: None,
403 __remaining_accounts: Vec::new(),
404 });
405 Self { instruction }
406 }
407 #[inline(always)]
408 pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
409 self.instruction.authority = Some(authority);
410 self
411 }
412 #[inline(always)]
413 pub fn treasury(&mut self, treasury: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
414 self.instruction.treasury = Some(treasury);
415 self
416 }
417 #[inline(always)]
418 pub fn position(&mut self, position: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
419 self.instruction.position = Some(position);
420 self
421 }
422 #[inline(always)]
423 pub fn treasury_staked_token_account(&mut self, treasury_staked_token_account: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
424 self.instruction.treasury_staked_token_account = Some(treasury_staked_token_account);
425 self
426 }
427 #[inline(always)]
428 pub fn treasury_reward_token_account(&mut self, treasury_reward_token_account: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
429 self.instruction.treasury_reward_token_account = Some(treasury_reward_token_account);
430 self
431 }
432 #[inline(always)]
433 pub fn authority_staked_token_account(&mut self, authority_staked_token_account: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
434 self.instruction.authority_staked_token_account = Some(authority_staked_token_account);
435 self
436 }
437 #[inline(always)]
438 pub fn authority_reward_token_account(&mut self, authority_reward_token_account: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
439 self.instruction.authority_reward_token_account = Some(authority_reward_token_account);
440 self
441 }
442 #[inline(always)]
443 pub fn token_program(&mut self, token_program: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
444 self.instruction.token_program = Some(token_program);
445 self
446 }
447 #[inline(always)]
449 pub fn add_remaining_account(&mut self, account: &'b solana_account_info::AccountInfo<'a>, is_writable: bool, is_signer: bool) -> &mut Self {
450 self.instruction.__remaining_accounts.push((account, is_writable, is_signer));
451 self
452 }
453 #[inline(always)]
458 pub fn add_remaining_accounts(&mut self, accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)]) -> &mut Self {
459 self.instruction.__remaining_accounts.extend_from_slice(accounts);
460 self
461 }
462 #[inline(always)]
463 pub fn invoke(&self) -> solana_program_entrypoint::ProgramResult {
464 self.invoke_signed(&[])
465 }
466 #[allow(clippy::clone_on_copy)]
467 #[allow(clippy::vec_init_then_push)]
468 pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_entrypoint::ProgramResult {
469 let instruction = WithdrawCpi {
470 __program: self.instruction.__program,
471
472 authority: self.instruction.authority.expect("authority is not set"),
473
474 treasury: self.instruction.treasury.expect("treasury is not set"),
475
476 position: self.instruction.position.expect("position is not set"),
477
478 treasury_staked_token_account: self.instruction.treasury_staked_token_account.expect("treasury_staked_token_account is not set"),
479
480 treasury_reward_token_account: self.instruction.treasury_reward_token_account.expect("treasury_reward_token_account is not set"),
481
482 authority_staked_token_account: self.instruction.authority_staked_token_account.expect("authority_staked_token_account is not set"),
483
484 authority_reward_token_account: self.instruction.authority_reward_token_account.expect("authority_reward_token_account is not set"),
485
486 token_program: self.instruction.token_program.expect("token_program is not set"),
487 };
488 instruction.invoke_signed_with_remaining_accounts(signers_seeds, &self.instruction.__remaining_accounts)
489 }
490}
491
492#[derive(Clone, Debug)]
493struct WithdrawCpiBuilderInstruction<'a, 'b> {
494 __program: &'b solana_account_info::AccountInfo<'a>,
495 authority: Option<&'b solana_account_info::AccountInfo<'a>>,
496 treasury: Option<&'b solana_account_info::AccountInfo<'a>>,
497 position: Option<&'b solana_account_info::AccountInfo<'a>>,
498 treasury_staked_token_account: Option<&'b solana_account_info::AccountInfo<'a>>,
499 treasury_reward_token_account: Option<&'b solana_account_info::AccountInfo<'a>>,
500 authority_staked_token_account: Option<&'b solana_account_info::AccountInfo<'a>>,
501 authority_reward_token_account: Option<&'b solana_account_info::AccountInfo<'a>>,
502 token_program: Option<&'b solana_account_info::AccountInfo<'a>>,
503 __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>,
505}
506