use super::hrpset::HrpSet;
use crate::address::AddressBech32DecodeError;
use crate::network::NetworkDefinition;
use crate::types::EntityType;
use bech32::{self, FromBase32, Variant};
use sbor::rust::prelude::*;
pub struct AddressBech32Decoder {
pub hrp_set: HrpSet,
}
impl AddressBech32Decoder {
pub fn for_simulator() -> Self {
Self::new(&NetworkDefinition::simulator())
}
pub fn new(network: &NetworkDefinition) -> Self {
Self {
hrp_set: network.into(),
}
}
pub fn validate_and_decode_ignore_hrp(
address: &str,
) -> Result<(String, EntityType, Vec<u8>), AddressBech32DecodeError> {
let (hrp, data, variant) = bech32::decode(address)
.map_err(|err| AddressBech32DecodeError::Bech32mDecodingError(err))?;
match variant {
Variant::Bech32m => {}
_ => return Err(AddressBech32DecodeError::InvalidVariant(variant)),
};
let data = Vec::<u8>::from_base32(&data)
.map_err(|err| AddressBech32DecodeError::Bech32mDecodingError(err))?;
let entity_type = if let Some(entity_type_id) = data.get(0) {
EntityType::from_repr(*entity_type_id).ok_or(
AddressBech32DecodeError::InvalidEntityTypeId(*entity_type_id),
)?
} else {
return Err(AddressBech32DecodeError::MissingEntityTypeByte);
};
Ok((hrp, entity_type, data))
}
pub fn validate_and_decode(
&self,
address: &str,
) -> Result<(EntityType, Vec<u8>), AddressBech32DecodeError> {
let (actual_hrp, entity_type, data) = Self::validate_and_decode_ignore_hrp(address)?;
let expected_hrp = self.hrp_set.get_entity_hrp(&entity_type);
if actual_hrp != expected_hrp {
return Err(AddressBech32DecodeError::InvalidHrp);
}
Ok((entity_type, data))
}
}