Skip to main content

krusty_kms_common/
address.rs

1//! Validated Starknet address (Felt newtype).
2
3use serde::{Deserialize, Serialize};
4use starknet_types_core::felt::Felt;
5use std::fmt;
6
7use crate::{KmsError, Result};
8
9/// A validated Starknet contract address.
10///
11/// Wraps a `Felt` and ensures it was parsed from a valid hex string.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
13#[serde(transparent)]
14pub struct Address(Felt);
15
16impl Address {
17    /// Parse an address from a hex string (with or without `0x` prefix).
18    pub fn from_hex(hex: &str) -> Result<Self> {
19        let felt =
20            Felt::from_hex(hex).map_err(|e| KmsError::DeserializationError(e.to_string()))?;
21        Ok(Self(felt))
22    }
23
24    /// Return the inner Felt.
25    pub fn as_felt(&self) -> Felt {
26        self.0
27    }
28
29    /// Return the hex representation with `0x` prefix.
30    pub fn to_hex(&self) -> String {
31        format!("{:#066x}", self.0)
32    }
33}
34
35impl fmt::Display for Address {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        write!(f, "{:#066x}", self.0)
38    }
39}
40
41impl From<Felt> for Address {
42    fn from(felt: Felt) -> Self {
43        Self(felt)
44    }
45}
46
47impl From<Address> for Felt {
48    fn from(addr: Address) -> Self {
49        addr.0
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_from_hex() {
59        let addr =
60            Address::from_hex("0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7")
61                .unwrap();
62        assert_ne!(addr.as_felt(), Felt::ZERO);
63    }
64
65    #[test]
66    fn test_from_hex_invalid() {
67        assert!(Address::from_hex("not_hex").is_err());
68    }
69
70    #[test]
71    fn test_display_roundtrip() {
72        let hex = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7";
73        let addr = Address::from_hex(hex).unwrap();
74        let displayed = addr.to_hex();
75        let addr2 = Address::from_hex(&displayed).unwrap();
76        assert_eq!(addr, addr2);
77    }
78
79    #[test]
80    fn test_from_felt() {
81        let felt = Felt::from(42u64);
82        let addr = Address::from(felt);
83        assert_eq!(addr.as_felt(), felt);
84    }
85
86    #[test]
87    fn test_serde_roundtrip() {
88        let addr = Address::from_hex("0x123").unwrap();
89        let json = serde_json::to_string(&addr).unwrap();
90        let parsed: Address = serde_json::from_str(&json).unwrap();
91        assert_eq!(addr, parsed);
92    }
93}