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