antegen_thread_program/instructions/
thread_close.rs1use {
2 crate::{errors::AntegenThreadError, *},
3 anchor_lang::prelude::*,
4 antegen_fiber_program::{
5 cpi::close,
6 state::{Fiber, FiberState},
7 },
8};
9
10#[derive(Accounts)]
15pub struct ThreadClose<'info> {
16 #[account(
18 constraint = authority.key().eq(&thread.authority) || authority.key().eq(&thread.key())
19 )]
20 pub authority: Signer<'info>,
21
22 #[account(mut)]
24 pub close_to: SystemAccount<'info>,
25
26 #[account(
28 mut,
29 close = close_to,
30 seeds = [
31 SEED_THREAD,
32 thread.authority.as_ref(),
33 thread.id.as_slice(),
34 ],
35 bump = thread.bump
36 )]
37 pub thread: Account<'info, Thread>,
38
39 pub fiber_program: Option<Program<'info, antegen_fiber_program::program::AntegenFiber>>,
41}
42
43pub fn thread_close<'info>(ctx: Context<'info, ThreadClose<'info>>) -> Result<()> {
44 let thread = &mut ctx.accounts.thread;
45 let thread_key = thread.key();
46
47 for account in ctx.remaining_accounts.iter() {
49 let fiber_read = Fiber::try_deserialize(&mut &account.data.borrow()[..])?;
51 require!(
52 fiber_read.thread() == thread_key,
53 AntegenThreadError::InvalidFiberAccount
54 );
55
56 let account_key = account.key();
58 let pos = thread
59 .fiber_ids
60 .iter()
61 .position(|&idx| FiberState::pubkey(thread_key, idx) == account_key)
62 .ok_or(AntegenThreadError::InvalidFiberAccount)?;
63 thread.fiber_ids.remove(pos);
64
65 let fiber_program = ctx
67 .accounts
68 .fiber_program
69 .as_ref()
70 .ok_or(AntegenThreadError::MissingFiberAccounts)?;
71
72 thread.sign(|seeds| {
73 close(CpiContext::new_with_signer(
74 fiber_program.key(),
75 antegen_fiber_program::cpi::accounts::Close {
76 thread: thread.to_account_info(),
77 fiber: account.to_account_info(),
78 },
79 &[seeds],
80 ))
81 })?;
82 }
83
84 require!(
86 thread.fiber_ids.is_empty(),
87 AntegenThreadError::MissingFiberAccounts
88 );
89
90 Ok(())
93}