sablier_thread_program/state/
thread.rs1use anchor_lang::{prelude::*, AnchorDeserialize, AnchorSerialize};
2use sablier_utils::{
3 account::AccountInfoExt,
4 thread::{ClockData, SerializableInstruction, Trigger},
5 MinSpace, Space,
6};
7
8use crate::constants::SEED_THREAD;
9
10#[account]
12#[derive(Debug)]
13pub struct Thread {
14 pub authority: Pubkey,
16 pub bump: u8,
18 pub created_at: ClockData,
20 pub domain: Option<Vec<u8>>,
21 pub exec_context: Option<ExecContext>,
23 pub fee: u64,
25 pub id: Vec<u8>,
27 pub instructions: Vec<SerializableInstruction>,
29 pub next_instruction: Option<SerializableInstruction>,
31 pub paused: bool,
33 pub rate_limit: u64,
35 pub trigger: Trigger,
37}
38
39impl Thread {
40 pub fn pubkey(authority: Pubkey, id: Vec<u8>, domain: Option<Vec<u8>>) -> Pubkey {
42 Pubkey::find_program_address(
43 &[
44 SEED_THREAD,
45 authority.as_ref(),
46 id.as_slice(),
47 domain.unwrap_or_default().as_slice(),
48 ],
49 &crate::ID,
50 )
51 .0
52 }
53}
54
55impl PartialEq for Thread {
56 fn eq(&self, other: &Self) -> bool {
57 self.authority.eq(&other.authority) && self.id.eq(&other.id)
58 }
59}
60
61impl Eq for Thread {}
62
63pub trait ThreadAccount {
65 fn pubkey(&self) -> Pubkey;
67
68 fn realloc_account(&mut self) -> Result<()>;
70}
71
72impl Thread {
73 pub fn min_space(instructions: &[SerializableInstruction]) -> Result<usize> {
74 let ins_space = instructions.try_to_vec()?.len();
75 let max_ins_size = instructions
76 .iter()
77 .map(|ins| ins.try_to_vec().map(|v| v.len()).unwrap_or(0))
78 .max()
79 .unwrap_or(0);
80
81 Ok(
82 8
83 + 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, )
96 }
97}
98
99impl ThreadAccount for Account<'_, Thread> {
100 fn pubkey(&self) -> Pubkey {
101 Thread::pubkey(self.authority, self.id.clone(), self.domain.clone())
102 }
103
104 fn realloc_account(&mut self) -> Result<()> {
105 let data_len = 8 + self.try_to_vec()?.len();
107
108 self.realloc(data_len, false)?;
109 Ok(())
110 }
111}
112
113#[derive(AnchorDeserialize, AnchorSerialize, MinSpace, Clone, Copy, Debug, PartialEq, Eq)]
115pub struct ExecContext {
116 pub exec_index: u64,
118
119 pub execs_since_reimbursement: u64,
122
123 pub execs_since_slot: u64,
125
126 pub last_exec_at: u64,
128
129 pub trigger_context: TriggerContext,
131}
132
133#[derive(AnchorDeserialize, AnchorSerialize, MinSpace, Clone, Copy, Debug, PartialEq, Eq)]
135pub enum TriggerContext {
136 Account {
138 data_hash: u64,
140 },
141
142 Cron {
144 started_at: i64,
146 },
147
148 Now,
150
151 Slot {
153 started_at: u64,
155 },
156
157 Epoch {
159 started_at: u64,
161 },
162
163 Timestamp {
165 started_at: i64,
167 },
168
169 Pyth { price: i64 },
171
172 Periodic {
174 started_at: i64,
176 },
177}
178
179#[derive(AnchorSerialize, AnchorDeserialize)]
181pub struct ThreadSettings {
182 pub fee: Option<u64>,
183 pub instructions: Option<Vec<SerializableInstruction>>,
184 pub name: Option<String>,
185 pub rate_limit: Option<u64>,
186 pub trigger: Option<Trigger>,
187}