templar_vault_kernel/types/
mod.rs

1//! Chain-agnostic types for the vault kernel.
2//!
3//! These types are designed to be portable across NEAR and Soroban.
4
5#[cfg(feature = "schemars")]
6use alloc::borrow::ToOwned;
7#[cfg(feature = "borsh-schema")]
8use alloc::string::ToString;
9
10use derive_more::{Display, From, Into};
11
12/// Timestamp in nanoseconds.
13#[repr(transparent)]
14#[templar_vault_macros::vault_derive(borsh, borsh_schema, serde, postcard, schemars)]
15#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, From, Into, Display)]
16#[display("{_0}")]
17pub struct TimestampNs(pub u64);
18
19impl TimestampNs {
20    pub const ZERO: Self = Self(0);
21
22    /// Create a timestamp from raw nanoseconds.
23    pub const fn from_nanos(nanos: u64) -> Self {
24        Self(nanos)
25    }
26
27    /// Return the raw nanosecond value.
28    pub const fn as_u64(self) -> u64 {
29        self.0
30    }
31
32    /// Saturating addition with another timestamp-like nanosecond delta.
33    pub const fn saturating_add(self, rhs: Self) -> Self {
34        Self(self.0.saturating_add(rhs.0))
35    }
36
37    /// Saturating addition with a raw nanosecond delta.
38    pub const fn saturating_add_u64(self, rhs: u64) -> Self {
39        Self(self.0.saturating_add(rhs))
40    }
41
42    /// Saturating subtraction with another timestamp-like nanosecond value.
43    pub const fn saturating_sub(self, rhs: Self) -> Self {
44        Self(self.0.saturating_sub(rhs.0))
45    }
46}
47
48/// Expected index in a queue or plan.
49#[repr(transparent)]
50#[templar_vault_macros::vault_derive(borsh, borsh_schema, serde, postcard, schemars)]
51#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, From, Into, Display)]
52#[display("{_0}")]
53pub struct ExpectedIdx(pub u32);
54
55/// Actual index reached during processing.
56#[repr(transparent)]
57#[templar_vault_macros::vault_derive(borsh, borsh_schema, serde, postcard, schemars)]
58#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, From, Into, Display)]
59#[display("{_0}")]
60pub struct ActualIdx(pub u32);
61
62/// Canonical address bytes.
63/// Executors map chain-native account identifiers to this form (sha256 hash).
64#[repr(transparent)]
65#[templar_vault_macros::vault_derive(borsh, borsh_schema, serde, postcard, schemars)]
66#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, From, Into)]
67pub struct Address(pub [u8; 32]);
68
69impl Address {
70    /// Create an address from raw bytes.
71    pub const fn from_bytes(bytes: [u8; 32]) -> Self {
72        Self(bytes)
73    }
74
75    /// Return the raw bytes for this address.
76    pub const fn as_bytes(&self) -> &[u8; 32] {
77        &self.0
78    }
79}
80
81impl AsRef<[u8; 32]> for Address {
82    fn as_ref(&self) -> &[u8; 32] {
83        &self.0
84    }
85}
86
87impl AsRef<[u8]> for Address {
88    fn as_ref(&self) -> &[u8] {
89        &self.0
90    }
91}
92
93/// Asset identifier as a fixed 32-byte hash.
94/// Executors map chain-native asset identifiers (e.g., NEAR account id)
95/// to this form (sha256 hash) and maintain the mapping.
96#[templar_vault_macros::vault_derive(borsh, serde, postcard)]
97#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, From, Into)]
98pub struct AssetId(pub [u8; 32]);
99
100impl AssetId {
101    /// Create an AssetId from raw bytes.
102    pub const fn from_bytes(bytes: [u8; 32]) -> Self {
103        Self(bytes)
104    }
105
106    /// Return the raw bytes for this AssetId.
107    pub const fn as_bytes(&self) -> &[u8; 32] {
108        &self.0
109    }
110}
111
112impl AsRef<[u8; 32]> for AssetId {
113    fn as_ref(&self) -> &[u8; 32] {
114        &self.0
115    }
116}
117
118impl AsRef<[u8]> for AssetId {
119    fn as_ref(&self) -> &[u8] {
120        &self.0
121    }
122}
123
124/// Settlement result for escrowed shares.
125#[templar_vault_macros::vault_derive(borsh, serde, postcard)]
126#[derive(Clone, Copy, PartialEq, Eq)]
127pub struct EscrowSettlement {
128    /// Shares to burn (successfully redeemed).
129    pub to_burn: u128,
130    /// Shares to refund (excess or on failure).
131    pub refund: u128,
132}
133
134impl EscrowSettlement {
135    /// Create a settlement from escrowed shares and intended burned shares.
136    ///
137    /// Burned shares are clamped to `escrow_shares`, and the remainder is refunded.
138    pub fn from_escrow_and_burn(escrow_shares: u128, burn_shares: u128) -> Self {
139        let to_burn = burn_shares.min(escrow_shares);
140        let refund = escrow_shares.saturating_sub(to_burn);
141        Self { to_burn, refund }
142    }
143
144    /// Create a settlement that burns all shares.
145    pub fn burn_all(shares: u128) -> Self {
146        Self {
147            to_burn: shares,
148            refund: 0,
149        }
150    }
151
152    /// Create a settlement that refunds all shares.
153    pub fn refund_all(shares: u128) -> Self {
154        Self {
155            to_burn: 0,
156            refund: shares,
157        }
158    }
159
160    /// Create a settlement with partial burn.
161    pub fn partial(to_burn: u128, refund: u128) -> Self {
162        Self { to_burn, refund }
163    }
164}
165
166/// Kernel version identifier.
167#[templar_vault_macros::vault_derive(borsh, serde, postcard)]
168#[derive(Clone, Copy, PartialEq, Eq, From, Into)]
169pub struct KernelVersion(pub u32);
170
171#[cfg(test)]
172mod tests;