use crate::{state::*, utils::next_timestamp, *};
use anchor_lang::prelude::*;
#[derive(AnchorSerialize, AnchorDeserialize, Default)]
pub struct ThreadUpdateParams {
pub paused: Option<bool>,
pub trigger: Option<Trigger>,
}
#[derive(Accounts)]
pub struct ThreadUpdate<'info> {
#[account(mut)]
pub authority: Signer<'info>,
#[account(
mut,
constraint = authority.key().eq(&thread.authority),
seeds = [
SEED_THREAD,
thread.authority.as_ref(),
thread.id.as_slice(),
],
bump = thread.bump,
)]
pub thread: Account<'info, Thread>,
}
pub fn thread_update(ctx: Context<ThreadUpdate>, params: ThreadUpdateParams) -> Result<()> {
let thread = &mut ctx.accounts.thread;
if let Some(paused) = params.paused {
thread.paused = paused;
}
if let Some(ref trigger) = params.trigger {
let clock = Clock::get()?;
let current_timestamp = clock.unix_timestamp;
let thread_pubkey = thread.key();
thread.trigger = trigger.clone();
thread.schedule = match &trigger {
Trigger::Account { .. } => Schedule::OnChange { prev: 0 },
Trigger::Cron {
schedule, jitter, ..
} => {
let base_next = next_timestamp(current_timestamp, schedule.clone())
.unwrap_or(current_timestamp);
let jitter_offset = crate::utils::calculate_jitter_offset(
current_timestamp,
&thread_pubkey,
*jitter,
);
Schedule::Timed {
prev: current_timestamp,
next: base_next.saturating_add(jitter_offset),
}
}
Trigger::Immediate { .. } => Schedule::Timed {
prev: current_timestamp,
next: current_timestamp,
},
Trigger::Slot { slot } => Schedule::Block {
prev: clock.slot,
next: *slot,
},
Trigger::Epoch { epoch } => Schedule::Block {
prev: clock.epoch,
next: *epoch,
},
Trigger::Interval {
seconds, jitter, ..
} => {
let base_next = current_timestamp.saturating_add(*seconds);
let jitter_offset = crate::utils::calculate_jitter_offset(
current_timestamp,
&thread_pubkey,
*jitter,
);
Schedule::Timed {
prev: current_timestamp,
next: base_next.saturating_add(jitter_offset),
}
}
Trigger::Timestamp { unix_ts, .. } => Schedule::Timed {
prev: current_timestamp,
next: *unix_ts,
},
};
}
if params.trigger.is_some() && params.paused.is_none() {
thread.paused = false;
}
Ok(())
}