Skip to main content

agsol_common/
timelock.rs

1use super::*;
2use borsh::{BorshDeserialize, BorshSerialize};
3use solana_program::clock::UnixTimestamp;
4
5#[derive(BorshSerialize, BorshDeserialize, Debug, Clone)]
6pub struct Timelock<T: BorshDeserialize + BorshSerialize + MaxSerializedLen, const N: usize>(
7    Vec<LockedItem<T>>,
8);
9
10impl<T, const N: usize> MaxSerializedLen for Timelock<T, N>
11where
12    T: BorshSerialize + BorshDeserialize + MaxSerializedLen,
13{
14    const MAX_SERIALIZED_LEN: usize = 4 + N * (T::MAX_SERIALIZED_LEN + 8); // UnixTimestamp is an extra 8 bytes
15}
16
17//impl<T, const N: usize> AccountState for Timelock<T, N> where T: MaxSerializedLen + Clone {}
18//
19impl<T, const N: usize> Timelock<T, N>
20where
21    T: BorshSerialize + BorshDeserialize + MaxSerializedLen,
22{
23    pub fn new() -> Self {
24        Self(Vec::new())
25    }
26
27    pub fn lock(&mut self, item: T, expiration_date: UnixTimestamp) -> Result<(), TimelockError> {
28        if self.0.len() < N {
29            self.0.push(LockedItem {
30                item,
31                expires: expiration_date,
32            });
33            Ok(())
34        } else {
35            Err(TimelockError::TimelockStorageFull)
36        }
37    }
38
39    pub fn locked_items(&self) -> &Vec<LockedItem<T>> {
40        &self.0
41    }
42
43    pub fn locked_items_mut(&mut self) -> &mut Vec<LockedItem<T>> {
44        &mut self.0
45    }
46
47    pub fn len(&self) -> usize {
48        self.0.len()
49    }
50
51    pub fn is_empty(&self) -> bool {
52        self.0.is_empty()
53    }
54
55    pub fn max_len(&self) -> usize {
56        N
57    }
58}
59
60impl<T, const N: usize> Default for Timelock<T, N>
61where
62    T: BorshSerialize + BorshDeserialize + MaxSerializedLen,
63{
64    fn default() -> Self {
65        Self::new()
66    }
67}
68
69#[derive(Debug)]
70pub enum TimelockError {
71    TimelockStorageFull,
72}
73
74#[cfg(test)]
75mod test {
76    use super::*;
77
78    #[derive(BorshSerialize, BorshDeserialize, Clone, Copy, Debug)]
79    struct Dummy {
80        a: u64,
81        b: i32,
82        c: [u8; 5],
83    }
84
85    impl MaxSerializedLen for Dummy {
86        const MAX_SERIALIZED_LEN: usize = 17;
87    }
88
89    const L: usize = 10;
90
91    #[test]
92    #[rustfmt::skip]
93    fn serialized_len() {
94        let mut timelock = Timelock::<Dummy, L>::new();
95        for i in 0..L {
96            timelock.lock(Dummy { a: 4, b: -3423, c: [0_u8; 5] }, 32445 + i as UnixTimestamp).unwrap();
97        }
98        assert_eq!(Timelock::<Dummy, L>::MAX_SERIALIZED_LEN, timelock.try_to_vec().unwrap().len());
99
100        // limit reached
101        assert!(timelock.lock(Dummy { a: 4, b: -3423, c: [0_u8; 5] }, 32445).is_err());
102        assert_eq!(timelock.len(), L);
103    }
104}