1use near_sdk::{json_types::U64, near};
2
3use crate::oracle::pyth::PythTimestamp;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
6#[near(serializers = [json, borsh])]
7#[serde(transparent)]
8pub struct Nanoseconds(U64);
9
10impl Nanoseconds {
11 pub fn try_from_pyth(value: PythTimestamp) -> Option<Self> {
12 let ms = value.as_ms()?;
13 Some(Self::from_ms(u64::try_from(ms).ok()?))
14 }
15
16 pub fn try_to_pyth(&self) -> Option<PythTimestamp> {
17 Some(PythTimestamp::from_ms(i64::try_from(self.as_ms()).ok()?))
18 }
19
20 pub const fn zero() -> Self {
21 Self(U64(0))
22 }
23
24 pub const fn from_ns(value: u64) -> Self {
26 Self(U64(value))
27 }
28
29 pub const fn from_ms(value: u64) -> Self {
31 Self(U64(value.saturating_mul(1_000_000)))
32 }
33
34 pub const fn from_secs(value: u64) -> Self {
36 Self(U64(value.saturating_mul(1_000_000_000)))
37 }
38
39 pub const fn as_secs(&self) -> u64 {
41 self.0 .0 / 1_000_000_000
42 }
43
44 pub const fn as_ms(&self) -> u64 {
46 self.0 .0 / 1_000_000
47 }
48
49 pub const fn as_ns(&self) -> u64 {
51 self.0 .0
52 }
53
54 pub fn now() -> Self {
55 Self::from_ns(near_sdk::env::block_timestamp())
56 }
57
58 #[must_use]
59 pub const fn saturating_add(self, rhs: Self) -> Self {
60 Self(U64(self.0 .0.saturating_add(rhs.0 .0)))
61 }
62
63 #[must_use]
64 pub const fn saturating_sub(self, rhs: Self) -> Self {
65 Self(U64(self.0 .0.saturating_sub(rhs.0 .0)))
66 }
67}
68
69impl std::fmt::Display for Nanoseconds {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 write!(f, "{}ns", self.as_ns())
72 }
73}
74
75impl From<redstone::TimestampMillis> for Nanoseconds {
76 fn from(value: redstone::TimestampMillis) -> Self {
77 Self::from_ms(value.as_millis())
78 }
79}
80
81impl From<Nanoseconds> for redstone::TimestampMillis {
82 fn from(value: Nanoseconds) -> Self {
83 Self::from_millis(value.as_ms())
84 }
85}