mod error;
mod resolver;
mod types;
mod config;
mod metrics;
mod monitoring;
#[cfg(feature = "ffi")]
pub mod ffi;
#[cfg(feature = "python")]
pub mod python;
pub use error::Bip353Error;
pub use resolver::{Bip353Resolver, ResolverType};
pub use types::{PaymentInfo, PaymentType};
pub use config::ResolverConfig;
pub use metrics::{Bip353Metrics, ResolutionStats, CacheStats};
pub use monitoring::{ChainMonitor, ChainBackend, AddressUsedEvent};
pub fn parse_address(address: &str) -> Result<(String, String), Bip353Error> {
let addr = address.trim();
let addr = addr.strip_prefix("₿").unwrap_or(addr);
let parts: Vec<&str> = addr.split('@').collect();
if parts.len() != 2 {
return Err(Bip353Error::InvalidAddress("Address must be in format user@domain".into()));
}
let user = parts[0].trim();
let domain = parts[1].trim();
if user.is_empty() || domain.is_empty() {
return Err(Bip353Error::InvalidAddress("User and domain cannot be empty".into()));
}
Ok((user.to_string(), domain.to_string()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_address() {
let result = parse_address("alice@example.com");
assert!(result.is_ok());
let (user, domain) = result.unwrap();
assert_eq!(user, "alice");
assert_eq!(domain, "example.com");
let result = parse_address("₿bob@bitcoin.org");
assert!(result.is_ok());
let (user, domain) = result.unwrap();
assert_eq!(user, "bob");
assert_eq!(domain, "bitcoin.org");
let result = parse_address(" charlie@example.org ");
assert!(result.is_ok());
let (user, domain) = result.unwrap();
assert_eq!(user, "charlie");
assert_eq!(domain, "example.org");
}
#[test]
fn test_invalid_addresses() {
let result = parse_address("aliceexample.com");
assert!(result.is_err());
let result = parse_address("@example.com");
assert!(result.is_err());
let result = parse_address("alice@");
assert!(result.is_err());
let result = parse_address("alice@example@com");
assert!(result.is_err());
}
}