antegen_thread_program/
utils.rs

1use anchor_lang::prelude::*;
2use chrono::{DateTime, Utc};
3use antegen_cron::Schedule;
4use std::collections::hash_map::DefaultHasher;
5use std::hash::{Hash, Hasher};
6use std::str::FromStr;
7
8/// Calculate the next timestamp for a cron schedule
9pub fn next_timestamp(after: i64, schedule: String) -> Option<i64> {
10    Schedule::from_str(&schedule)
11        .unwrap()
12        .next_after(&DateTime::<Utc>::from_timestamp(after, 0).unwrap())
13        .take()
14        .map(|datetime| datetime.timestamp())
15}
16
17/// Calculate deterministic jitter offset using prev timestamp and thread pubkey
18/// This creates a feedback loop where each execution's timing affects the next jitter
19pub fn calculate_jitter_offset(
20    prev_timestamp: i64,
21    thread_pubkey: &Pubkey,
22    jitter: u64,
23) -> i64 {
24    if jitter == 0 {
25        return 0;
26    }
27
28    let mut hasher = DefaultHasher::new();
29    prev_timestamp.hash(&mut hasher);
30    thread_pubkey.hash(&mut hasher);
31    let hash = hasher.finish();
32
33    (hash % jitter) as i64
34}
35
36/// Safely transfer lamports from one account to another
37pub fn transfer_lamports(from: &AccountInfo, to: &AccountInfo, amount: u64) -> Result<()> {
38    if amount == 0 {
39        return Ok(());
40    }
41    
42    // Deduct from source
43    **from.try_borrow_mut_lamports()? = from
44        .lamports()
45        .checked_sub(amount)
46        .ok_or(ProgramError::InsufficientFunds)?;
47    
48    // Add to destination
49    **to.try_borrow_mut_lamports()? = to
50        .lamports()
51        .checked_add(amount)
52        .ok_or(ProgramError::ArithmeticOverflow)?;
53    
54    Ok(())
55}