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