antegen_thread_program/instructions/
thread_update.rs

1use crate::{state::*, utils::next_timestamp, *};
2use anchor_lang::prelude::*;
3
4/// Accounts required by the `thread_update` instruction.
5#[derive(Accounts)]
6pub struct ThreadUpdate<'info> {
7    /// The authority (owner) of the thread.
8    #[account(mut)]
9    pub authority: Signer<'info>,
10
11    /// The thread to be updated.
12    #[account(
13        mut,
14        constraint = authority.key().eq(&thread.authority),
15        seeds = [
16            SEED_THREAD,
17            thread.authority.as_ref(),
18            thread.id.as_slice(),
19        ],
20        bump = thread.bump,
21    )]
22    pub thread: Account<'info, Thread>,
23}
24
25pub fn thread_update(ctx: Context<ThreadUpdate>, new_trigger: Option<Trigger>) -> Result<()> {
26    let thread = &mut ctx.accounts.thread;
27
28    // Update the trigger if provided
29    if let Some(trigger) = new_trigger {
30        let clock = Clock::get()?;
31        let current_timestamp = clock.unix_timestamp;
32        let thread_pubkey = thread.key();
33
34        thread.trigger = trigger.clone();
35
36        // Initialize schedule based on trigger type (mirrors thread_create logic)
37        thread.schedule = match &trigger {
38            Trigger::Account { .. } => Schedule::OnChange { prev: 0 },
39            Trigger::Cron {
40                schedule, jitter, ..
41            } => {
42                let base_next =
43                    next_timestamp(current_timestamp, schedule.clone()).unwrap_or(current_timestamp);
44                let jitter_offset =
45                    crate::utils::calculate_jitter_offset(current_timestamp, &thread_pubkey, *jitter);
46                Schedule::Timed {
47                    prev: current_timestamp,
48                    next: base_next.saturating_add(jitter_offset),
49                }
50            }
51            Trigger::Immediate { .. } => Schedule::Timed {
52                prev: current_timestamp,
53                next: current_timestamp,
54            },
55            Trigger::Slot { slot } => Schedule::Block {
56                prev: clock.slot,
57                next: *slot,
58            },
59            Trigger::Epoch { epoch } => Schedule::Block {
60                prev: clock.epoch,
61                next: *epoch,
62            },
63            Trigger::Interval {
64                seconds, jitter, ..
65            } => {
66                let base_next = current_timestamp.saturating_add(*seconds);
67                let jitter_offset =
68                    crate::utils::calculate_jitter_offset(current_timestamp, &thread_pubkey, *jitter);
69                Schedule::Timed {
70                    prev: current_timestamp,
71                    next: base_next.saturating_add(jitter_offset),
72                }
73            }
74            Trigger::Timestamp { unix_ts, .. } => Schedule::Timed {
75                prev: current_timestamp,
76                next: *unix_ts,
77            },
78        };
79    }
80
81    Ok(())
82}