Skip to main content

antegen_thread_program/instructions/
fiber_close.rs

1use crate::*;
2use anchor_lang::prelude::*;
3
4/// Accounts required by the `fiber_close` instruction.
5#[derive(Accounts)]
6#[instruction(fiber_index: u8)]
7pub struct FiberClose<'info> {
8    /// The authority of the thread or the thread itself
9    #[account(
10        constraint = authority.key().eq(&thread.authority) || authority.key().eq(&thread.key())
11    )]
12    pub authority: Signer<'info>,
13
14    /// The address to return the data rent lamports to
15    #[account(mut)]
16    pub close_to: SystemAccount<'info>,
17
18    /// The thread to remove the fiber from
19    #[account(
20        mut,
21        seeds = [
22            SEED_THREAD,
23            thread.authority.as_ref(),
24            thread.id.as_slice(),
25        ],
26        bump = thread.bump,
27    )]
28    pub thread: Account<'info, Thread>,
29
30    /// The fiber account to close (optional - not needed if closing inline fiber)
31    #[account(
32        mut,
33        seeds = [
34            SEED_THREAD_FIBER,
35            thread.key().as_ref(),
36            &[fiber_index],
37        ],
38        bump,
39        close = close_to,
40    )]
41    pub fiber: Option<Account<'info, FiberState>>,
42}
43
44pub fn fiber_close(ctx: Context<FiberClose>, fiber_index: u8) -> Result<()> {
45    let thread = &mut ctx.accounts.thread;
46
47    // Check if closing default fiber (index 0 with default_fiber present)
48    if fiber_index == 0 && thread.default_fiber.is_some() {
49        // Clear default fiber
50        thread.default_fiber = None;
51        thread.default_fiber_priority_fee = 0;
52
53        // If we're closing the current fiber, advance to next one first
54        if thread.fiber_cursor == 0 && thread.fiber_ids.len() > 1 {
55            thread.advance_to_next_fiber();
56        }
57
58        // Remove from fiber_ids
59        thread.fiber_ids.retain(|&x| x != 0);
60
61        // If this was the last fiber, reset fiber_cursor
62        if thread.fiber_ids.is_empty() {
63            thread.fiber_cursor = 0;
64        }
65    } else {
66        // Closing account-based fiber - ensure account is provided
67        require!(
68            ctx.accounts.fiber.is_some(),
69            crate::errors::AntegenThreadError::FiberAccountRequired
70        );
71
72        // If we're closing the current fiber, advance to next one first
73        if thread.fiber_cursor == fiber_index && thread.fiber_ids.len() > 1 {
74            thread.advance_to_next_fiber();
75        }
76
77        // Remove the fiber index from the thread's fiber_ids
78        thread.fiber_ids.retain(|&x| x != fiber_index);
79
80        // If this was the last fiber, reset fiber_cursor
81        if thread.fiber_ids.is_empty() {
82            thread.fiber_cursor = 0;
83        }
84
85        // Account closure is handled by Anchor's close constraint
86    }
87
88    Ok(())
89}