Skip to main content

antegen_thread_program/instructions/
fiber_swap.rs

1use crate::{errors::AntegenThreadError, *};
2use anchor_lang::prelude::*;
3
4/// Accounts required by the `swap_fiber` instruction.
5/// Copies source fiber's instruction into target, closes source.
6/// Validates authority, CPIs to Fiber Program to swap, updates thread fiber tracking.
7#[derive(Accounts)]
8#[instruction(source_fiber_index: u8)]
9pub struct FiberSwap<'info> {
10    /// The authority of the thread or the thread itself
11    #[account(
12        constraint = authority.key().eq(&thread.authority) || authority.key().eq(&thread.key())
13    )]
14    pub authority: Signer<'info>,
15
16    /// The thread that owns both fibers
17    #[account(
18        mut,
19        constraint = thread.fiber_ids.contains(&source_fiber_index) @ AntegenThreadError::InvalidFiberIndex,
20        seeds = [
21            SEED_THREAD,
22            thread.authority.as_ref(),
23            thread.id.as_slice(),
24        ],
25        bump = thread.bump,
26    )]
27    pub thread: Account<'info, Thread>,
28
29    /// The target fiber — receives source's instruction content
30    #[account(
31        mut,
32        constraint = target.thread.eq(&thread.key()) @ AntegenThreadError::InvalidFiberAccount,
33    )]
34    pub target: Account<'info, antegen_fiber_program::state::FiberState>,
35
36    /// The source fiber — closed after its instruction is copied to target
37    #[account(
38        mut,
39        constraint = source.thread.eq(&thread.key()) @ AntegenThreadError::InvalidFiberAccount,
40    )]
41    pub source: Account<'info, antegen_fiber_program::state::FiberState>,
42
43    /// The Fiber Program for CPI
44    pub fiber_program: Program<'info, antegen_fiber_program::program::AntegenFiber>,
45}
46
47pub fn fiber_swap(ctx: Context<FiberSwap>, source_fiber_index: u8) -> Result<()> {
48    let thread = &mut ctx.accounts.thread;
49
50    // CPI to Fiber Program's swap_fiber
51    thread.sign(|seeds| {
52        antegen_fiber_program::cpi::swap_fiber(CpiContext::new_with_signer(
53            ctx.accounts.fiber_program.key(),
54            antegen_fiber_program::cpi::accounts::FiberSwap {
55                thread: thread.to_account_info(),
56                target: ctx.accounts.target.to_account_info(),
57                source: ctx.accounts.source.to_account_info(),
58            },
59            &[seeds],
60        ))
61    })?;
62
63    // Remove source fiber index from fiber_ids
64    thread.fiber_ids.retain(|&x| x != source_fiber_index);
65
66    // Adjust cursor if it was pointing to the removed source
67    if thread.fiber_cursor == source_fiber_index {
68        if thread.fiber_ids.is_empty() {
69            thread.fiber_cursor = 0;
70        } else {
71            thread.fiber_cursor = thread.fiber_ids[0];
72        }
73    }
74
75    Ok(())
76}