acta_maker_sdk/ws/vault/
tx.rs1use std::time::{SystemTime, UNIX_EPOCH};
2
3use crate::chain::vault::VaultIntentError;
4
5#[derive(Debug, thiserror::Error)]
6#[non_exhaustive]
7pub enum VaultTxError {
8 #[error("{field} `{deadline}` is not a unix timestamp")]
9 InvalidDeadline {
10 field: &'static str,
11 deadline: String,
12 },
13 #[error("{field} has passed: deadline {deadline}, now {now}")]
14 Expired {
15 field: &'static str,
16 deadline: u64,
17 now: u64,
18 },
19 #[error("system clock is before the unix epoch")]
20 ClockBeforeEpoch,
21 #[error(transparent)]
22 Intent(#[from] VaultIntentError),
23}
24
25pub(super) fn ensure_deadline_ahead(
26 field: &'static str,
27 deadline: &str,
28) -> Result<u64, VaultTxError> {
29 ensure_deadline_ahead_at(field, deadline, unix_now()?)
30}
31
32pub(super) fn ensure_deadline_ahead_at(
33 field: &'static str,
34 deadline: &str,
35 now: u64,
36) -> Result<u64, VaultTxError> {
37 let deadline_secs =
38 deadline
39 .trim()
40 .parse::<u64>()
41 .map_err(|_| VaultTxError::InvalidDeadline {
42 field,
43 deadline: deadline.to_owned(),
44 })?;
45 ensure_ahead(field, deadline_secs, now)
46}
47
48pub(super) fn ensure_system_time_ahead(
49 field: &'static str,
50 deadline: SystemTime,
51) -> Result<u64, VaultTxError> {
52 let deadline_secs = deadline
53 .duration_since(UNIX_EPOCH)
54 .map_err(|_| VaultTxError::ClockBeforeEpoch)?
55 .as_secs();
56 ensure_ahead(field, deadline_secs, unix_now()?)
57}
58
59fn ensure_ahead(field: &'static str, deadline: u64, now: u64) -> Result<u64, VaultTxError> {
60 if now >= deadline {
61 return Err(VaultTxError::Expired {
62 field,
63 deadline,
64 now,
65 });
66 }
67 Ok(deadline)
68}
69
70fn unix_now() -> Result<u64, VaultTxError> {
71 SystemTime::now()
72 .duration_since(UNIX_EPOCH)
73 .map(|elapsed| elapsed.as_secs())
74 .map_err(|_| VaultTxError::ClockBeforeEpoch)
75}