novax_data/types/
address.rs1use std::hash::{Hash, Hasher};
2use std::ops::Deref;
3use multiversx_sc::api::ManagedTypeApi;
4use multiversx_sc::types::ManagedAddress;
5use multiversx_sc_codec::{DecodeError, TopDecode, TopDecodeInput};
6use multiversx_sc_scenario::api::StaticApi;
7use multiversx_sc_scenario::scenario_model::AddressValue;
8use multiversx_sdk::data::address::Address as SDKAddress;
9use serde::{Deserialize, Deserializer, Serialize};
10use serde::de::Error;
11use crate::error::AddressError;
12use crate::error::DataError;
13use crate::types::managed::ManagedConvertible;
14use crate::types::native::NativeConvertible;
15
16#[derive(Serialize, Clone, Debug)]
40pub struct Address(SDKAddress);
41
42impl Default for Address {
43 fn default() -> Self {
44 Address::from_bytes([0; 32])
45 }
46}
47
48impl PartialEq for Address {
49 fn eq(&self, other: &Self) -> bool {
50 self.to_bytes() == other.to_bytes()
51 }
52}
53
54impl Address {
57 pub fn from_bech32_string(bech32: &str) -> Result<Address, DataError> {
72 let Ok(address) = SDKAddress::from_bech32_string(bech32) else { return Err(AddressError::InvalidBech32String { invalid_value: bech32.to_string() }.into()) };
73
74 Ok(Address(address))
75 }
76
77 pub fn from_bytes(bytes: [u8; 32]) -> Address {
91 Address(SDKAddress::from_bytes(bytes))
92 }
93
94 pub fn to_bech32_string(&self) -> Result<String, DataError> {
107 let Ok(string) = self.0.to_bech32_string() else {
108 return Err(AddressError::CannotConvertToBech32String.into())
109 };
110
111 Ok(string)
112 }
113
114 pub fn to_bytes(&self) -> [u8; 32] {
127 self.0.to_bytes()
128 }
129}
130
131
132impl Deref for Address {
133 type Target = multiversx_sdk::data::address::Address;
134
135 fn deref(&self) -> &Self::Target {
136 &self.0
137 }
138}
139
140impl Hash for Address {
141 fn hash<H: Hasher>(&self, state: &mut H) {
142 self.0.to_bytes().hash(state)
143 }
144}
145
146impl<M: ManagedTypeApi> NativeConvertible for ManagedAddress<M> {
147 type Native = Address;
148
149 fn to_native(&self) -> Self::Native {
150 Address(SDKAddress::from_bytes(self.to_byte_array()))
151 }
152}
153
154impl NativeConvertible for Address {
155 type Native = Self;
156
157 fn to_native(&self) -> Self::Native {
158 self.clone()
159 }
160}
161
162impl ManagedConvertible<ManagedAddress<StaticApi>> for Address {
163 fn to_managed(&self) -> ManagedAddress<StaticApi> {
164 ManagedAddress::from_address(&multiversx_sc::types::Address::from(self.to_bytes()))
165 }
166}
167
168impl TopDecode for Address {
169 fn top_decode<I>(input: I) -> Result<Self, DecodeError> where I: TopDecodeInput {
170 let bytes = ManagedAddress::<StaticApi>::top_decode(input)?.to_byte_array();
171 Ok(Address(SDKAddress::from_bytes(bytes)))
172 }
173}
174
175impl From<&Address> for AddressValue {
176 fn from(value: &Address) -> Self {
177 (&multiversx_sc::types::Address::from(value.0.to_bytes())).into()
178 }
179}
180
181impl From<SDKAddress> for Address {
182 fn from(value: SDKAddress) -> Self {
183 Address::from_bytes(value.to_bytes())
184 }
185}
186
187impl From<&SDKAddress> for Address {
188 fn from(value: &SDKAddress) -> Self {
189 Address::from_bytes(value.to_bytes())
190 }
191}
192
193impl From<&multiversx_sc::types::Address> for Address {
194 fn from(value: &multiversx_sc::types::Address) -> Self {
195 Address::from_bytes(*value.as_array())
196 }
197}
198
199impl From<multiversx_sc::types::Address> for Address {
200 fn from(value: multiversx_sc::types::Address) -> Self {
201 Address::from_bytes(*value.as_array())
202 }
203}
204
205impl From<Address> for multiversx_sc::types::Address {
206 fn from(value: Address) -> Self {
207 multiversx_sc::types::Address::from(value.to_bytes())
208 }
209}
210
211impl From<&str> for Address {
212 fn from(value: &str) -> Self {
213 if value.starts_with("erd1") {
214 Address::from_bech32_string(value).unwrap()
215 } else {
216 (&AddressValue::from(value).value).into()
217 }
218 }
219}
220
221impl From<&String> for Address {
222 fn from(value: &String) -> Self {
223 From::<&str>::from(value)
224 }
225}
226
227impl<'a> Deserialize<'a> for Address {
228 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'a> {
229 let string = String::deserialize(deserializer)?;
230
231 let Ok(address) = Address::from_bech32_string(&string) else {
232 return Err(D::Error::custom(format!("Cannot parse bech32 address : {string}")))
233 };
234
235 Ok(address)
236 }
237}
238
239#[cfg(test)]
240mod tests {
241 use multiversx_sc::types::ManagedAddress;
242 use multiversx_sc_scenario::api::StaticApi;
243 use crate::{Address, AddressError, DataError};
244 use crate::types::managed::ManagedConvertible;
245 use crate::types::native::NativeConvertible;
246
247 #[test]
248 fn test_managed_address_to_native() {
249 let expected = Address::from_bech32_string("erd1qqqqqqqqqqqqqpgq7ykazrzd905zvnlr88dpfw06677lxe9w0n4suz00uh").unwrap();
250 let managed_address: ManagedAddress<StaticApi> = ManagedAddress::from(expected.to_bytes());
251 let native = managed_address.to_native();
252
253 assert_eq!(
254 native.to_bytes(),
255 expected.to_bytes()
256 )
257 }
258
259 #[test]
260 fn test_managed_address_to_managed() {
261 let address = Address::from_bech32_string("erd1qqqqqqqqqqqqqpgq7ykazrzd905zvnlr88dpfw06677lxe9w0n4suz00uh").unwrap();
262 let managed = address.to_managed();
263
264 assert_eq!(
265 address.to_bytes(),
266 managed.to_byte_array()
267 )
268 }
269
270 #[test]
271 fn test_from_bech32_string_valid_address() {
272 Address::from_bech32_string("erd1an4xpn58j7ymd58m2jznr32t0vmas75egrdfa8mta6fzvqn9tkxq4jvghn").unwrap();
273 }
274
275 #[test]
276 fn test_from_bech32_string_invalid_address() {
277 let str = "erd1an4xpn58j7ymd58m2jznr32t0vmas75egrdfa8mta6fzvqn9tkxq4jvghm";
278 let error = Address::from_bech32_string(str).unwrap_err();
279
280 let expected = DataError::Address(AddressError::InvalidBech32String { invalid_value: str.to_string() });
281
282 assert_eq!(error, expected);
283 }
284
285 #[test]
286 fn test_from_bech32_string_invalid_address_bad_length() {
287 let str = "erd1an4xpn58j7ymd58m2jznr32t";
288 let error = Address::from_bech32_string(str).unwrap_err();
289
290 let expected = DataError::Address(AddressError::InvalidBech32String { invalid_value: str.to_string() });
291
292 assert_eq!(error, expected);
293 }
294
295}