snarkvm_console_types_address/
parse.rs1use super::*;
17
18static ADDRESS_PREFIX: &str = "aleo";
19
20impl<E: Environment> Parser for Address<E> {
21 #[inline]
23 fn parse(string: &str) -> ParserResult<Self> {
24 let parse_address = recognize(pair(
26 tag("aleo1"),
27 many1(terminated(one_of("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), many0(char('_')))),
28 ));
29
30 map_res(parse_address, |address: &str| -> Result<_, Error> { Self::from_str(&address.replace('_', "")) })(
32 string,
33 )
34 }
35}
36
37impl<E: Environment> FromStr for Address<E> {
38 type Err = Error;
39
40 fn from_str(address: &str) -> Result<Self, Self::Err> {
42 if address.len() != 63 {
44 bail!("Invalid account address length: found {}, expected 63", address.len())
45 }
46 let (hrp, data, variant) = bech32::decode(address)?;
48 if hrp != ADDRESS_PREFIX {
49 bail!("Failed to decode address: '{hrp}' is an invalid prefix")
50 } else if data.is_empty() {
51 bail!("Failed to decode address: data field is empty")
52 } else if variant != bech32::Variant::Bech32m {
53 bail!("Found an address that is not bech32m encoded: {address}");
54 }
55 Ok(Self::read_le(&Vec::from_base32(&data)?[..])?)
57 }
58}
59
60impl<E: Environment> Debug for Address<E> {
61 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
62 Display::fmt(self, f)
63 }
64}
65
66impl<E: Environment> Display for Address<E> {
67 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
69 let bytes = self.to_bytes_le().map_err(|_| fmt::Error)?;
71 let string =
73 bech32::encode(ADDRESS_PREFIX, bytes.to_base32(), bech32::Variant::Bech32m).map_err(|_| fmt::Error)?;
74 Display::fmt(&string, f)
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use snarkvm_console_network_environment::Console;
83
84 type CurrentEnvironment = Console;
85
86 const ITERATIONS: u64 = 1_000;
87
88 #[test]
89 fn test_parse() -> Result<()> {
90 assert!(Address::<CurrentEnvironment>::parse(Address::<CurrentEnvironment>::type_name()).is_err());
92 assert!(Address::<CurrentEnvironment>::parse("").is_err());
93
94 let mut rng = TestRng::default();
95
96 for _ in 0..ITERATIONS {
97 let address = Address::<CurrentEnvironment>::rand(&mut rng);
99
100 let expected = format!("{address}");
101 let (remainder, candidate) = Address::<CurrentEnvironment>::parse(&expected).unwrap();
102 assert_eq!(format!("{expected}"), candidate.to_string());
103 assert_eq!(ADDRESS_PREFIX, candidate.to_string().split('1').next().unwrap());
104 assert_eq!("", remainder);
105 }
106 Ok(())
107 }
108
109 #[test]
110 fn test_string() -> Result<()> {
111 let mut rng = TestRng::default();
112
113 for _ in 0..ITERATIONS {
114 let expected = Address::<CurrentEnvironment>::rand(&mut rng);
116
117 let candidate = format!("{expected}");
119 assert_eq!(expected, Address::from_str(&candidate)?);
120 assert_eq!(ADDRESS_PREFIX, candidate.split('1').next().unwrap());
121 }
122 Ok(())
123 }
124
125 #[test]
126 fn test_display() -> Result<()> {
127 let mut rng = TestRng::default();
128
129 for _ in 0..ITERATIONS {
130 let expected = Address::<CurrentEnvironment>::rand(&mut rng);
132
133 let candidate = expected.to_string();
134 assert_eq!(format!("{expected}"), candidate);
135 assert_eq!(ADDRESS_PREFIX, candidate.split('1').next().unwrap());
136
137 let candidate_recovered = Address::<CurrentEnvironment>::from_str(&candidate.to_string())?;
138 assert_eq!(expected, candidate_recovered);
139 }
140 Ok(())
141 }
142}