defuse_core/nonce/
expirable.rs1use defuse_borsh_utils::As;
2use defuse_time::{Timestamp, borsh::TimestampNanoSeconds};
3use near_sdk::borsh::{BorshDeserialize, BorshSerialize};
4
5#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
7#[borsh(crate = "::near_sdk::borsh")]
8pub struct ExpirableNonce<T>
9where
10 T: BorshSerialize + BorshDeserialize,
11{
12 #[borsh(
13 serialize_with = "As::<TimestampNanoSeconds<i64>>::serialize",
14 deserialize_with = "As::<TimestampNanoSeconds<i64>>::deserialize"
15 )]
16 pub deadline: Timestamp,
17 pub nonce: T,
18}
19
20impl<T> ExpirableNonce<T>
21where
22 T: BorshSerialize + BorshDeserialize,
23{
24 pub const fn new(deadline: Timestamp, nonce: T) -> Self {
25 Self { deadline, nonce }
26 }
27
28 #[inline]
29 pub fn has_expired(&self) -> bool {
30 self.deadline < Timestamp::now()
31 }
32}
33
34#[cfg(test)]
35mod tests {
36 use std::time::Duration;
37
38 use super::*;
39
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 mut u = arbitrary::Unstructured::new(&random_bytes);
46 let nonce: [u8; 24] = u.arbitrary().unwrap();
47
48 let expired = ExpirableNonce::new(Timestamp::now() - Duration::from_hours(24), nonce);
49 assert!(expired.has_expired());
50
51 let not_expired = ExpirableNonce::new(Timestamp::now() + Duration::from_hours(24), nonce);
52 assert!(!not_expired.has_expired());
53 }
54}