use crate::error::{Error, Result};
use bech32::primitives::hrp::Hrp;
use bech32::Bech32;
pub const DEFAULT_PREFIX: &str = "qor";
fn strip_hex_prefix(s: &str) -> &str {
if let Some(rest) = s.strip_prefix("0x").or_else(|| s.strip_prefix("0X")) {
rest
} else {
s
}
}
fn hex_to_bytes(s: &str) -> Result<Vec<u8>> {
let body = strip_hex_prefix(s);
if body.is_empty() || body.len() % 2 != 0 {
return Err(Error::Address(format!("invalid hex string: {s}")));
}
hex::decode(body).map_err(|_| Error::Address(format!("invalid hex string: {s}")))
}
pub fn bytes_to_bech32(data: &[u8], prefix: &str) -> Result<String> {
let hrp =
Hrp::parse(prefix).map_err(|e| Error::Address(format!("invalid bech32 prefix: {e}")))?;
bech32::encode::<Bech32>(hrp, data)
.map_err(|e| Error::Address(format!("failed to encode bech32 address: {e}")))
}
pub fn hex_to_bech32(hex_str: &str, prefix: &str) -> Result<String> {
let bytes = hex_to_bytes(hex_str)?;
bytes_to_bech32(&bytes, prefix)
}
pub fn bech32_to_hex(addr: &str) -> Result<String> {
let (_hrp, data) = bech32::decode(addr)
.map_err(|_| Error::Address(format!("invalid bech32 address: {addr}")))?;
Ok(format!("0x{}", hex::encode(data)))
}
pub fn is_valid_bech32(addr: &str, prefix: Option<&str>) -> bool {
match bech32::decode(addr) {
Ok((hrp, _data)) => match prefix {
None => true,
Some(p) => hrp.as_str().eq_ignore_ascii_case(p),
},
Err(_) => false,
}
}