diff --git a/consumer/src/resolver.rs b/consumer/src/resolver.rs index 8aa78b0..8191843 100644 --- a/consumer/src/resolver.rs +++ b/consumer/src/resolver.rs @@ -1,4 +1,4 @@ -use did_iota::consumer::iota_clients; +use did_iota::consumer::{iota_clients, NodeUrls}; use did_jwk::consumer::resolve_did_jwk; use did_key::consumer::resolve_did_key; use did_web::consumer::resolve_did_web; @@ -14,14 +14,18 @@ pub struct Resolver { impl Resolver { pub async fn new() -> Self { - let resolver = configure_resolver(IdentityResolver::new(), None) + let resolver = configure_resolver(IdentityResolver::new(), None, None, None) .await .expect("Failed to configure resolver"); Self { resolver } } - pub async fn new_with_tls_config(tls_config: rustls::ClientConfig) -> Self { - let resolver = configure_resolver(IdentityResolver::new(), Some(tls_config)) + pub async fn new_with_options( + tls_config: Option, + node_urls: Option, + basic_auth: Option<(&str, &str)>, + ) -> Self { + let resolver = configure_resolver(IdentityResolver::new(), tls_config, node_urls, basic_auth) .await .expect("Failed to configure resolver"); Self { resolver } @@ -37,12 +41,15 @@ impl Resolver { async fn configure_resolver( mut resolver: IdentityResolver, tls_config: Option, + node_urls: Option, + basic_auth: Option<(&str, &str)>, ) -> Result { resolver.attach_handler("jwk".to_owned(), resolve_did_jwk); resolver.attach_handler("key".to_owned(), resolve_did_key); resolver.attach_handler("web".to_owned(), resolve_did_web); + resolver.attach_multiple_iota_handlers( - iota_clients(tls_config) + iota_clients(tls_config, node_urls, basic_auth) .await .map_err(|e| ConsumerError::Generic(format!("Failed to attach IOTA handlers: {e}")))?, ); diff --git a/did_iota/src/consumer.rs b/did_iota/src/consumer.rs index eb3ffd5..85082d4 100644 --- a/did_iota/src/consumer.rs +++ b/did_iota/src/consumer.rs @@ -1,38 +1,81 @@ use identity_iota::iota::rebased::client::IdentityClientReadOnly; use identity_iota::iota::rebased::Error; -use iota_sdk::IotaClientBuilder; +use iota_sdk::{IotaClient, IotaClientBuilder}; /// Builds clients for all IOTA networks. +/// +/// Parameters: +/// - TLS configuration (optional) +/// - Node URLs (optional) +/// - Basic Authentication (optional) +/// +/// This function only returns an error if it fails to build. The provided values are not validated. pub async fn iota_clients( tls_config: Option, + node_urls: Option, + basic_auth: Option<(&str, &str)>, ) -> Result, Error> { - let mut iota_testnet_client_builder = IotaClientBuilder::default(); - - if let Some(tls_config) = &tls_config { - iota_testnet_client_builder = iota_testnet_client_builder.tls_config(tls_config.clone()); + let iota_mainnet: IotaClient; + let iota_testnet: IotaClient; + let iota_devnet: IotaClient; + if let Some(urls) = &node_urls { + iota_mainnet = match &urls.mainnet { + Some(url) => client_builder(tls_config.as_ref(), basic_auth).build(url).await?, + None => client_builder(tls_config.as_ref(), basic_auth).build_mainnet().await?, + }; + iota_testnet = match &urls.testnet { + Some(url) => client_builder(tls_config.as_ref(), basic_auth).build(url).await?, + None => client_builder(tls_config.as_ref(), basic_auth).build_testnet().await?, + }; + iota_devnet = match &urls.devnet { + Some(url) => client_builder(tls_config.as_ref(), basic_auth).build(url).await?, + None => client_builder(tls_config.as_ref(), basic_auth).build_devnet().await?, + }; + } else { + iota_mainnet = client_builder(tls_config.as_ref(), basic_auth).build_mainnet().await?; + iota_testnet = client_builder(tls_config.as_ref(), basic_auth).build_testnet().await?; + iota_devnet = client_builder(tls_config.as_ref(), basic_auth).build_devnet().await?; } - let iota_testnet = iota_testnet_client_builder.build_testnet().await?; - - let mut iota_devnet_client_builder = IotaClientBuilder::default(); + Ok(vec![ + ("iota", IdentityClientReadOnly::new(iota_mainnet).await?), + ("testnet", IdentityClientReadOnly::new(iota_testnet).await?), + ("devnet", IdentityClientReadOnly::new(iota_devnet).await?), + ]) +} - if let Some(tls_config) = &tls_config { - iota_devnet_client_builder = iota_devnet_client_builder.tls_config(tls_config.clone()); +fn client_builder(tls_config: Option<&rustls::ClientConfig>, basic_auth: Option<(&str, &str)>) -> IotaClientBuilder { + let mut builder = IotaClientBuilder::default(); + if let Some(cfg) = tls_config { + builder = builder.tls_config(cfg.clone()); + } + if let Some((username, password)) = basic_auth { + builder = builder.basic_auth(username, password); } + builder +} - let iota_devnet = iota_devnet_client_builder.build_devnet().await?; +#[derive(Debug, Clone)] +pub struct NodeUrls { + pub mainnet: Option, + pub testnet: Option, + pub devnet: Option, +} - let mut iota_mainnet_client_builder = IotaClientBuilder::default(); +#[cfg(test)] +mod tests { + use super::*; - if let Some(tls_config) = tls_config { - iota_mainnet_client_builder = iota_mainnet_client_builder.tls_config(tls_config); - } + #[tokio::test] + async fn test_iota_clients_custom_node_config() { + let node_urls = NodeUrls { + mainnet: Some("https://rpc.mainnet.iota.monochain.p2p.org/".to_string()), + testnet: None, + devnet: None, + }; - let iota_mainnet = iota_mainnet_client_builder.build_mainnet().await?; + let basic_auth = Some(("username", "password")); - Ok(vec![ - ("testnet", IdentityClientReadOnly::new(iota_testnet).await?), - ("devnet", IdentityClientReadOnly::new(iota_devnet).await?), - ("iota", IdentityClientReadOnly::new(iota_mainnet).await?), - ]) + let _ = iota_clients(None, Some(node_urls), basic_auth).await.unwrap(); + } } diff --git a/did_iota/src/producer/resolve.rs b/did_iota/src/producer/resolve.rs index 3738f09..c6d9893 100644 --- a/did_iota/src/producer/resolve.rs +++ b/did_iota/src/producer/resolve.rs @@ -4,7 +4,7 @@ use crate::consumer::iota_clients; pub async fn resolve(did: IotaDID) -> Result { let mut resolver = Resolver::::new(); - resolver.attach_multiple_iota_handlers(iota_clients(None).await.unwrap()); + resolver.attach_multiple_iota_handlers(iota_clients(None, None, None).await.unwrap()); let document = resolver.resolve(&did).await?; Ok(document) }