defuse_core/nonce/
expirable.rs1use defuse_borsh_utils::adapters::{As, TimestampNanoSeconds};
2use near_sdk::borsh::{BorshDeserialize, BorshSerialize};
3
4use crate::Deadline;
5
6#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
8#[borsh(crate = "::near_sdk::borsh")]
9pub struct ExpirableNonce<T>
10where
11 T: BorshSerialize + BorshDeserialize,
12{
13 #[borsh(
14 serialize_with = "As::<TimestampNanoSeconds>::serialize",
15 deserialize_with = "As::<TimestampNanoSeconds>::deserialize"
16 )]
17 pub deadline: Deadline,
18 pub nonce: T,
19}
20
21impl<T> ExpirableNonce<T>
22where
23 T: BorshSerialize + BorshDeserialize,
24{
25 pub const fn new(deadline: Deadline, nonce: T) -> Self {
26 Self { deadline, nonce }
27 }
28
29 #[inline]
30 pub fn has_expired(&self) -> bool {
31 self.deadline.has_expired()
32 }
33}
34
35#[cfg(test)]
36mod tests {
37 use super::*;
38
39 use chrono::{Days, Utc};
40 use defuse_test_utils::random::random_bytes;
41 use rstest::rstest;
42
43 #[rstest]
44 fn expirable_test(random_bytes: Vec<u8>) {
45 let current_timestamp = Utc::now();
46 let mut u = arbitrary::Unstructured::new(&random_bytes);
47 let nonce: [u8; 24] = u.arbitrary().unwrap();
48
49 let expired = ExpirableNonce::new(
50 Deadline::new(current_timestamp.checked_sub_days(Days::new(1)).unwrap()),
51 nonce,
52 );
53 assert!(expired.has_expired());
54
55 let not_expired = ExpirableNonce::new(
56 Deadline::new(current_timestamp.checked_add_days(Days::new(1)).unwrap()),
57 nonce,
58 );
59 assert!(!not_expired.has_expired());
60 }
61}