use anchor_lang::{prelude::*, AnchorDeserialize, AnchorSerialize};
use sablier_utils::{
account::AccountInfoExt,
thread::{ClockData, SerializableInstruction, Trigger},
MinSpace, Space,
};
use crate::constants::SEED_THREAD;
#[account]
#[derive(Debug)]
pub struct Thread {
pub authority: Pubkey,
pub bump: u8,
pub created_at: ClockData,
pub domain: Option<Vec<u8>>,
pub exec_context: Option<ExecContext>,
pub fee: u64,
pub id: Vec<u8>,
pub instructions: Vec<SerializableInstruction>,
pub next_instruction: Option<SerializableInstruction>,
pub paused: bool,
pub rate_limit: u64,
pub trigger: Trigger,
}
impl Thread {
pub fn pubkey(authority: Pubkey, id: Vec<u8>, domain: Option<Vec<u8>>) -> Pubkey {
Pubkey::find_program_address(
&[
SEED_THREAD,
authority.as_ref(),
id.as_slice(),
domain.unwrap_or_default().as_slice(),
],
&crate::ID,
)
.0
}
}
impl PartialEq for Thread {
fn eq(&self, other: &Self) -> bool {
self.authority.eq(&other.authority) && self.id.eq(&other.id)
}
}
impl Eq for Thread {}
pub trait ThreadAccount {
fn pubkey(&self) -> Pubkey;
fn realloc_account(&mut self) -> Result<()>;
}
impl Thread {
pub fn min_space(instructions: &[SerializableInstruction]) -> Result<usize> {
let ins_space = instructions.try_to_vec()?.len();
let max_ins_size = instructions
.iter()
.map(|ins| ins.try_to_vec().map(|v| v.len()).unwrap_or(0))
.max()
.unwrap_or(0);
Ok(
8
+ Pubkey::MIN_SPACE + u8::MIN_SPACE + ClockData::MIN_SPACE + (1 + 4 + 32) + <Option<ExecContext>>::MIN_SPACE + u64::MIN_SPACE + (4 + 32) + (4 + ins_space) + (1 + max_ins_size) + bool::MIN_SPACE + u64::MIN_SPACE + Trigger::MIN_SPACE, )
}
}
impl ThreadAccount for Account<'_, Thread> {
fn pubkey(&self) -> Pubkey {
Thread::pubkey(self.authority, self.id.clone(), self.domain.clone())
}
fn realloc_account(&mut self) -> Result<()> {
let data_len = 8 + self.try_to_vec()?.len();
self.realloc(data_len, false)?;
Ok(())
}
}
#[derive(AnchorDeserialize, AnchorSerialize, MinSpace, Clone, Copy, Debug, PartialEq, Eq)]
pub struct ExecContext {
pub exec_index: u64,
pub execs_since_reimbursement: u64,
pub execs_since_slot: u64,
pub last_exec_at: u64,
pub trigger_context: TriggerContext,
}
#[derive(AnchorDeserialize, AnchorSerialize, MinSpace, Clone, Copy, Debug, PartialEq, Eq)]
pub enum TriggerContext {
Account {
data_hash: u64,
},
Cron {
started_at: i64,
},
Now,
Slot {
started_at: u64,
},
Epoch {
started_at: u64,
},
Timestamp {
started_at: i64,
},
Pyth { price: i64 },
Periodic {
started_at: i64,
},
}
#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct ThreadSettings {
pub fee: Option<u64>,
pub instructions: Option<Vec<SerializableInstruction>>,
pub name: Option<String>,
pub rate_limit: Option<u64>,
pub trigger: Option<Trigger>,
}