andromeda_std/common/
milliseconds.rs1use cosmwasm_schema::cw_serde;
2use cosmwasm_std::{BlockInfo, Timestamp};
3use cw20::Expiration;
4
5#[cw_serde]
6#[derive(Default, Eq, PartialOrd, Copy)]
7pub struct Milliseconds(pub u64);
9pub type MillisecondsDuration = Milliseconds;
10pub type MillisecondsExpiration = Milliseconds;
11
12impl Milliseconds {
13 pub fn is_expired(&self, block: &BlockInfo) -> bool {
14 let time = block.time.seconds() * 1000;
15 self.0 <= time
16 }
17
18 pub fn is_in_past(&self, block: &BlockInfo) -> bool {
19 let time = block.time.seconds() * 1000;
20 self.0 < time
21 }
22
23 #[inline]
24 pub fn zero() -> Milliseconds {
25 Milliseconds(0)
26 }
27
28 #[inline]
29 pub fn is_zero(&self) -> bool {
30 self.0 == 0
31 }
32
33 #[inline]
34 pub fn from_seconds(seconds: u64) -> Milliseconds {
35 if seconds > u64::MAX / 1000 {
36 panic!("Overflow: Cannot convert seconds to milliseconds")
37 }
38
39 Milliseconds(seconds * 1000)
40 }
41
42 #[inline]
43 pub fn from_nanos(nanos: u64) -> Milliseconds {
44 Milliseconds(nanos / 1000000)
45 }
46
47 #[inline]
48 pub fn milliseconds(&self) -> u64 {
49 self.0
50 }
51
52 #[inline]
53 pub fn seconds(&self) -> u64 {
54 self.0 / 1000
55 }
56
57 #[inline]
58 pub fn nanos(&self) -> u64 {
59 if self.0 > u64::MAX / 1000000 {
60 panic!("Overflow: Cannot convert milliseconds time to nanoseconds")
61 }
62 self.0 * 1000000
63 }
64
65 pub fn add_milliseconds(&mut self, milliseconds: Milliseconds) {
66 self.0 += milliseconds.0;
67 }
68
69 pub fn subtract_milliseconds(&mut self, milliseconds: Milliseconds) {
70 self.0 -= milliseconds.0;
71 }
72
73 pub fn plus_milliseconds(self, milliseconds: Milliseconds) -> Milliseconds {
74 Milliseconds(self.0 + milliseconds.0)
75 }
76
77 pub fn minus_milliseconds(self, milliseconds: Milliseconds) -> Milliseconds {
78 Milliseconds(self.0 - milliseconds.0)
79 }
80
81 pub fn add_seconds(&mut self, seconds: u64) {
82 self.0 += seconds * 1000;
83 }
84
85 pub fn subtract_seconds(&mut self, seconds: u64) {
86 if seconds > self.0 / 1000 {
87 panic!("Overflow: Cannot subtract seconds from milliseconds")
88 }
89
90 self.0 -= seconds * 1000;
91 }
92
93 pub fn plus_seconds(self, seconds: u64) -> Milliseconds {
94 Milliseconds(self.0 + seconds * 1000)
95 }
96
97 pub fn minus_seconds(self, seconds: u64) -> Milliseconds {
98 Milliseconds(self.0 - seconds * 1000)
99 }
100}
101
102impl From<Milliseconds> for String {
103 fn from(time: Milliseconds) -> String {
104 time.0.to_string()
105 }
106}
107
108impl From<Milliseconds> for Timestamp {
109 fn from(time: Milliseconds) -> Timestamp {
110 Timestamp::from_nanos(time.nanos())
111 }
112}
113
114impl From<Milliseconds> for Expiration {
115 fn from(time: Milliseconds) -> Expiration {
116 Expiration::AtTime(time.into())
117 }
118}
119
120impl std::fmt::Display for Milliseconds {
121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 write!(f, "{}", self.0)
123 }
124}
125
126#[cfg(test)]
127mod test {
128 use cosmwasm_std::testing::mock_env;
129
130 use super::*;
131
132 struct IsExpiredTestCase {
133 name: &'static str,
134 input: u64,
135 curr_time: u64,
136 is_expired: bool,
137 }
138
139 #[test]
140 fn test_is_expired() {
141 let test_cases: Vec<IsExpiredTestCase> = vec![
142 IsExpiredTestCase {
143 name: "valid expiration time (expired)",
144 input: 0,
145 curr_time: 1,
146 is_expired: true,
147 },
148 IsExpiredTestCase {
149 name: "valid expiration time (not expired)",
150 input: 1,
151 curr_time: 0,
152 is_expired: false,
153 },
154 IsExpiredTestCase {
155 name: "same time (expired)",
156 input: 0,
157 curr_time: 0,
158 is_expired: true,
159 },
160 ];
161
162 for test in test_cases {
163 let input = Milliseconds(test.input);
164 let curr_time = Milliseconds(test.curr_time);
165 let mut env = mock_env();
166 env.block.time = curr_time.into();
167
168 let output = input.is_expired(&env.block);
169
170 assert_eq!(test.is_expired, output, "Test failed: {}", test.name)
171 }
172 }
173}