1use borsh::BorshSerialize;
9use borsh::BorshDeserialize;
10
11pub const WITHDRAW_DISCRIMINATOR: [u8; 8] = [183, 18, 70, 156, 148, 109, 161, 34];
12
13#[derive(Debug)]
15pub struct Withdraw {
16
17
18 pub authority: solana_pubkey::Pubkey,
19
20
21 pub mint: solana_pubkey::Pubkey,
22
23
24 pub tuna_config: solana_pubkey::Pubkey,
25
26
27 pub lending_position: solana_pubkey::Pubkey,
28
29
30 pub vault: solana_pubkey::Pubkey,
31
32
33 pub vault_ata: solana_pubkey::Pubkey,
34
35
36 pub authority_ata: solana_pubkey::Pubkey,
37
38
39 pub token_program: solana_pubkey::Pubkey,
40
41
42 pub memo_program: solana_pubkey::Pubkey,
43 }
44
45impl Withdraw {
46 pub fn instruction(&self, args: WithdrawInstructionArgs) -> solana_instruction::Instruction {
47 self.instruction_with_remaining_accounts(args, &[])
48 }
49 #[allow(clippy::arithmetic_side_effects)]
50 #[allow(clippy::vec_init_then_push)]
51 pub fn instruction_with_remaining_accounts(&self, args: WithdrawInstructionArgs, remaining_accounts: &[solana_instruction::AccountMeta]) -> solana_instruction::Instruction {
52 let mut accounts = Vec::with_capacity(9+ remaining_accounts.len());
53 accounts.push(solana_instruction::AccountMeta::new(
54 self.authority,
55 true
56 ));
57 accounts.push(solana_instruction::AccountMeta::new_readonly(
58 self.mint,
59 false
60 ));
61 accounts.push(solana_instruction::AccountMeta::new_readonly(
62 self.tuna_config,
63 false
64 ));
65 accounts.push(solana_instruction::AccountMeta::new(
66 self.lending_position,
67 false
68 ));
69 accounts.push(solana_instruction::AccountMeta::new(
70 self.vault,
71 false
72 ));
73 accounts.push(solana_instruction::AccountMeta::new(
74 self.vault_ata,
75 false
76 ));
77 accounts.push(solana_instruction::AccountMeta::new(
78 self.authority_ata,
79 false
80 ));
81 accounts.push(solana_instruction::AccountMeta::new_readonly(
82 self.token_program,
83 false
84 ));
85 accounts.push(solana_instruction::AccountMeta::new_readonly(
86 self.memo_program,
87 false
88 ));
89 accounts.extend_from_slice(remaining_accounts);
90 let mut data = borsh::to_vec(&WithdrawInstructionData::new()).unwrap();
91 let mut args = borsh::to_vec(&args).unwrap();
92 data.append(&mut args);
93
94 solana_instruction::Instruction {
95 program_id: crate::TUNA_ID,
96 accounts,
97 data,
98 }
99 }
100}
101
102#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)]
103#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
104 pub struct WithdrawInstructionData {
105 discriminator: [u8; 8],
106 }
107
108impl WithdrawInstructionData {
109 pub fn new() -> Self {
110 Self {
111 discriminator: [183, 18, 70, 156, 148, 109, 161, 34],
112 }
113 }
114}
115
116impl Default for WithdrawInstructionData {
117 fn default() -> Self {
118 Self::new()
119 }
120}
121
122#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)]
123#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
124 pub struct WithdrawInstructionArgs {
125 pub funds: u64,
126 pub shares: u64,
127 }
128
129
130#[derive(Clone, Debug, Default)]
144pub struct WithdrawBuilder {
145 authority: Option<solana_pubkey::Pubkey>,
146 mint: Option<solana_pubkey::Pubkey>,
147 tuna_config: Option<solana_pubkey::Pubkey>,
148 lending_position: Option<solana_pubkey::Pubkey>,
149 vault: Option<solana_pubkey::Pubkey>,
150 vault_ata: Option<solana_pubkey::Pubkey>,
151 authority_ata: Option<solana_pubkey::Pubkey>,
152 token_program: Option<solana_pubkey::Pubkey>,
153 memo_program: Option<solana_pubkey::Pubkey>,
154 funds: Option<u64>,
155 shares: Option<u64>,
156 __remaining_accounts: Vec<solana_instruction::AccountMeta>,
157}
158
159impl WithdrawBuilder {
160 pub fn new() -> Self {
161 Self::default()
162 }
163 #[inline(always)]
164 pub fn authority(&mut self, authority: solana_pubkey::Pubkey) -> &mut Self {
165 self.authority = Some(authority);
166 self
167 }
168 #[inline(always)]
169 pub fn mint(&mut self, mint: solana_pubkey::Pubkey) -> &mut Self {
170 self.mint = Some(mint);
171 self
172 }
173 #[inline(always)]
174 pub fn tuna_config(&mut self, tuna_config: solana_pubkey::Pubkey) -> &mut Self {
175 self.tuna_config = Some(tuna_config);
176 self
177 }
178 #[inline(always)]
179 pub fn lending_position(&mut self, lending_position: solana_pubkey::Pubkey) -> &mut Self {
180 self.lending_position = Some(lending_position);
181 self
182 }
183 #[inline(always)]
184 pub fn vault(&mut self, vault: solana_pubkey::Pubkey) -> &mut Self {
185 self.vault = Some(vault);
186 self
187 }
188 #[inline(always)]
189 pub fn vault_ata(&mut self, vault_ata: solana_pubkey::Pubkey) -> &mut Self {
190 self.vault_ata = Some(vault_ata);
191 self
192 }
193 #[inline(always)]
194 pub fn authority_ata(&mut self, authority_ata: solana_pubkey::Pubkey) -> &mut Self {
195 self.authority_ata = Some(authority_ata);
196 self
197 }
198 #[inline(always)]
200 pub fn token_program(&mut self, token_program: solana_pubkey::Pubkey) -> &mut Self {
201 self.token_program = Some(token_program);
202 self
203 }
204 #[inline(always)]
205 pub fn memo_program(&mut self, memo_program: solana_pubkey::Pubkey) -> &mut Self {
206 self.memo_program = Some(memo_program);
207 self
208 }
209 #[inline(always)]
210 pub fn funds(&mut self, funds: u64) -> &mut Self {
211 self.funds = Some(funds);
212 self
213 }
214 #[inline(always)]
215 pub fn shares(&mut self, shares: u64) -> &mut Self {
216 self.shares = Some(shares);
217 self
218 }
219 #[inline(always)]
221 pub fn add_remaining_account(&mut self, account: solana_instruction::AccountMeta) -> &mut Self {
222 self.__remaining_accounts.push(account);
223 self
224 }
225 #[inline(always)]
227 pub fn add_remaining_accounts(&mut self, accounts: &[solana_instruction::AccountMeta]) -> &mut Self {
228 self.__remaining_accounts.extend_from_slice(accounts);
229 self
230 }
231 #[allow(clippy::clone_on_copy)]
232 pub fn instruction(&self) -> solana_instruction::Instruction {
233 let accounts = Withdraw {
234 authority: self.authority.expect("authority is not set"),
235 mint: self.mint.expect("mint is not set"),
236 tuna_config: self.tuna_config.expect("tuna_config is not set"),
237 lending_position: self.lending_position.expect("lending_position is not set"),
238 vault: self.vault.expect("vault is not set"),
239 vault_ata: self.vault_ata.expect("vault_ata is not set"),
240 authority_ata: self.authority_ata.expect("authority_ata is not set"),
241 token_program: self.token_program.unwrap_or(solana_pubkey::pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")),
242 memo_program: self.memo_program.expect("memo_program is not set"),
243 };
244 let args = WithdrawInstructionArgs {
245 funds: self.funds.clone().expect("funds is not set"),
246 shares: self.shares.clone().expect("shares is not set"),
247 };
248
249 accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts)
250 }
251}
252
253 pub struct WithdrawCpiAccounts<'a, 'b> {
255
256
257 pub authority: &'b solana_account_info::AccountInfo<'a>,
258
259
260 pub mint: &'b solana_account_info::AccountInfo<'a>,
261
262
263 pub tuna_config: &'b solana_account_info::AccountInfo<'a>,
264
265
266 pub lending_position: &'b solana_account_info::AccountInfo<'a>,
267
268
269 pub vault: &'b solana_account_info::AccountInfo<'a>,
270
271
272 pub vault_ata: &'b solana_account_info::AccountInfo<'a>,
273
274
275 pub authority_ata: &'b solana_account_info::AccountInfo<'a>,
276
277
278 pub token_program: &'b solana_account_info::AccountInfo<'a>,
279
280
281 pub memo_program: &'b solana_account_info::AccountInfo<'a>,
282 }
283
284pub struct WithdrawCpi<'a, 'b> {
286 pub __program: &'b solana_account_info::AccountInfo<'a>,
288
289
290 pub authority: &'b solana_account_info::AccountInfo<'a>,
291
292
293 pub mint: &'b solana_account_info::AccountInfo<'a>,
294
295
296 pub tuna_config: &'b solana_account_info::AccountInfo<'a>,
297
298
299 pub lending_position: &'b solana_account_info::AccountInfo<'a>,
300
301
302 pub vault: &'b solana_account_info::AccountInfo<'a>,
303
304
305 pub vault_ata: &'b solana_account_info::AccountInfo<'a>,
306
307
308 pub authority_ata: &'b solana_account_info::AccountInfo<'a>,
309
310
311 pub token_program: &'b solana_account_info::AccountInfo<'a>,
312
313
314 pub memo_program: &'b solana_account_info::AccountInfo<'a>,
315 pub __args: WithdrawInstructionArgs,
317 }
318
319impl<'a, 'b> WithdrawCpi<'a, 'b> {
320 pub fn new(
321 program: &'b solana_account_info::AccountInfo<'a>,
322 accounts: WithdrawCpiAccounts<'a, 'b>,
323 args: WithdrawInstructionArgs,
324 ) -> Self {
325 Self {
326 __program: program,
327 authority: accounts.authority,
328 mint: accounts.mint,
329 tuna_config: accounts.tuna_config,
330 lending_position: accounts.lending_position,
331 vault: accounts.vault,
332 vault_ata: accounts.vault_ata,
333 authority_ata: accounts.authority_ata,
334 token_program: accounts.token_program,
335 memo_program: accounts.memo_program,
336 __args: args,
337 }
338 }
339 #[inline(always)]
340 pub fn invoke(&self) -> solana_program_error::ProgramResult {
341 self.invoke_signed_with_remaining_accounts(&[], &[])
342 }
343 #[inline(always)]
344 pub fn invoke_with_remaining_accounts(&self, remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)]) -> solana_program_error::ProgramResult {
345 self.invoke_signed_with_remaining_accounts(&[], remaining_accounts)
346 }
347 #[inline(always)]
348 pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult {
349 self.invoke_signed_with_remaining_accounts(signers_seeds, &[])
350 }
351 #[allow(clippy::arithmetic_side_effects)]
352 #[allow(clippy::clone_on_copy)]
353 #[allow(clippy::vec_init_then_push)]
354 pub fn invoke_signed_with_remaining_accounts(
355 &self,
356 signers_seeds: &[&[&[u8]]],
357 remaining_accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)]
358 ) -> solana_program_error::ProgramResult {
359 let mut accounts = Vec::with_capacity(9+ remaining_accounts.len());
360 accounts.push(solana_instruction::AccountMeta::new(
361 *self.authority.key,
362 true
363 ));
364 accounts.push(solana_instruction::AccountMeta::new_readonly(
365 *self.mint.key,
366 false
367 ));
368 accounts.push(solana_instruction::AccountMeta::new_readonly(
369 *self.tuna_config.key,
370 false
371 ));
372 accounts.push(solana_instruction::AccountMeta::new(
373 *self.lending_position.key,
374 false
375 ));
376 accounts.push(solana_instruction::AccountMeta::new(
377 *self.vault.key,
378 false
379 ));
380 accounts.push(solana_instruction::AccountMeta::new(
381 *self.vault_ata.key,
382 false
383 ));
384 accounts.push(solana_instruction::AccountMeta::new(
385 *self.authority_ata.key,
386 false
387 ));
388 accounts.push(solana_instruction::AccountMeta::new_readonly(
389 *self.token_program.key,
390 false
391 ));
392 accounts.push(solana_instruction::AccountMeta::new_readonly(
393 *self.memo_program.key,
394 false
395 ));
396 remaining_accounts.iter().for_each(|remaining_account| {
397 accounts.push(solana_instruction::AccountMeta {
398 pubkey: *remaining_account.0.key,
399 is_signer: remaining_account.1,
400 is_writable: remaining_account.2,
401 })
402 });
403 let mut data = borsh::to_vec(&WithdrawInstructionData::new()).unwrap();
404 let mut args = borsh::to_vec(&self.__args).unwrap();
405 data.append(&mut args);
406
407 let instruction = solana_instruction::Instruction {
408 program_id: crate::TUNA_ID,
409 accounts,
410 data,
411 };
412 let mut account_infos = Vec::with_capacity(10 + remaining_accounts.len());
413 account_infos.push(self.__program.clone());
414 account_infos.push(self.authority.clone());
415 account_infos.push(self.mint.clone());
416 account_infos.push(self.tuna_config.clone());
417 account_infos.push(self.lending_position.clone());
418 account_infos.push(self.vault.clone());
419 account_infos.push(self.vault_ata.clone());
420 account_infos.push(self.authority_ata.clone());
421 account_infos.push(self.token_program.clone());
422 account_infos.push(self.memo_program.clone());
423 remaining_accounts.iter().for_each(|remaining_account| account_infos.push(remaining_account.0.clone()));
424
425 if signers_seeds.is_empty() {
426 solana_cpi::invoke(&instruction, &account_infos)
427 } else {
428 solana_cpi::invoke_signed(&instruction, &account_infos, signers_seeds)
429 }
430 }
431}
432
433#[derive(Clone, Debug)]
447pub struct WithdrawCpiBuilder<'a, 'b> {
448 instruction: Box<WithdrawCpiBuilderInstruction<'a, 'b>>,
449}
450
451impl<'a, 'b> WithdrawCpiBuilder<'a, 'b> {
452 pub fn new(program: &'b solana_account_info::AccountInfo<'a>) -> Self {
453 let instruction = Box::new(WithdrawCpiBuilderInstruction {
454 __program: program,
455 authority: None,
456 mint: None,
457 tuna_config: None,
458 lending_position: None,
459 vault: None,
460 vault_ata: None,
461 authority_ata: None,
462 token_program: None,
463 memo_program: None,
464 funds: None,
465 shares: None,
466 __remaining_accounts: Vec::new(),
467 });
468 Self { instruction }
469 }
470 #[inline(always)]
471 pub fn authority(&mut self, authority: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
472 self.instruction.authority = Some(authority);
473 self
474 }
475 #[inline(always)]
476 pub fn mint(&mut self, mint: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
477 self.instruction.mint = Some(mint);
478 self
479 }
480 #[inline(always)]
481 pub fn tuna_config(&mut self, tuna_config: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
482 self.instruction.tuna_config = Some(tuna_config);
483 self
484 }
485 #[inline(always)]
486 pub fn lending_position(&mut self, lending_position: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
487 self.instruction.lending_position = Some(lending_position);
488 self
489 }
490 #[inline(always)]
491 pub fn vault(&mut self, vault: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
492 self.instruction.vault = Some(vault);
493 self
494 }
495 #[inline(always)]
496 pub fn vault_ata(&mut self, vault_ata: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
497 self.instruction.vault_ata = Some(vault_ata);
498 self
499 }
500 #[inline(always)]
501 pub fn authority_ata(&mut self, authority_ata: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
502 self.instruction.authority_ata = Some(authority_ata);
503 self
504 }
505 #[inline(always)]
506 pub fn token_program(&mut self, token_program: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
507 self.instruction.token_program = Some(token_program);
508 self
509 }
510 #[inline(always)]
511 pub fn memo_program(&mut self, memo_program: &'b solana_account_info::AccountInfo<'a>) -> &mut Self {
512 self.instruction.memo_program = Some(memo_program);
513 self
514 }
515 #[inline(always)]
516 pub fn funds(&mut self, funds: u64) -> &mut Self {
517 self.instruction.funds = Some(funds);
518 self
519 }
520 #[inline(always)]
521 pub fn shares(&mut self, shares: u64) -> &mut Self {
522 self.instruction.shares = Some(shares);
523 self
524 }
525 #[inline(always)]
527 pub fn add_remaining_account(&mut self, account: &'b solana_account_info::AccountInfo<'a>, is_writable: bool, is_signer: bool) -> &mut Self {
528 self.instruction.__remaining_accounts.push((account, is_writable, is_signer));
529 self
530 }
531 #[inline(always)]
536 pub fn add_remaining_accounts(&mut self, accounts: &[(&'b solana_account_info::AccountInfo<'a>, bool, bool)]) -> &mut Self {
537 self.instruction.__remaining_accounts.extend_from_slice(accounts);
538 self
539 }
540 #[inline(always)]
541 pub fn invoke(&self) -> solana_program_error::ProgramResult {
542 self.invoke_signed(&[])
543 }
544 #[allow(clippy::clone_on_copy)]
545 #[allow(clippy::vec_init_then_push)]
546 pub fn invoke_signed(&self, signers_seeds: &[&[&[u8]]]) -> solana_program_error::ProgramResult {
547 let args = WithdrawInstructionArgs {
548 funds: self.instruction.funds.clone().expect("funds is not set"),
549 shares: self.instruction.shares.clone().expect("shares is not set"),
550 };
551 let instruction = WithdrawCpi {
552 __program: self.instruction.__program,
553
554 authority: self.instruction.authority.expect("authority is not set"),
555
556 mint: self.instruction.mint.expect("mint is not set"),
557
558 tuna_config: self.instruction.tuna_config.expect("tuna_config is not set"),
559
560 lending_position: self.instruction.lending_position.expect("lending_position is not set"),
561
562 vault: self.instruction.vault.expect("vault is not set"),
563
564 vault_ata: self.instruction.vault_ata.expect("vault_ata is not set"),
565
566 authority_ata: self.instruction.authority_ata.expect("authority_ata is not set"),
567
568 token_program: self.instruction.token_program.expect("token_program is not set"),
569
570 memo_program: self.instruction.memo_program.expect("memo_program is not set"),
571 __args: args,
572 };
573 instruction.invoke_signed_with_remaining_accounts(signers_seeds, &self.instruction.__remaining_accounts)
574 }
575}
576
577#[derive(Clone, Debug)]
578struct WithdrawCpiBuilderInstruction<'a, 'b> {
579 __program: &'b solana_account_info::AccountInfo<'a>,
580 authority: Option<&'b solana_account_info::AccountInfo<'a>>,
581 mint: Option<&'b solana_account_info::AccountInfo<'a>>,
582 tuna_config: Option<&'b solana_account_info::AccountInfo<'a>>,
583 lending_position: Option<&'b solana_account_info::AccountInfo<'a>>,
584 vault: Option<&'b solana_account_info::AccountInfo<'a>>,
585 vault_ata: Option<&'b solana_account_info::AccountInfo<'a>>,
586 authority_ata: Option<&'b solana_account_info::AccountInfo<'a>>,
587 token_program: Option<&'b solana_account_info::AccountInfo<'a>>,
588 memo_program: Option<&'b solana_account_info::AccountInfo<'a>>,
589 funds: Option<u64>,
590 shares: Option<u64>,
591 __remaining_accounts: Vec<(&'b solana_account_info::AccountInfo<'a>, bool, bool)>,
593}
594