Skip to content
Merged
17 changes: 12 additions & 5 deletions consumer/src/resolver.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<rustls::ClientConfig>,
node_urls: Option<NodeUrls>,
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 }
Expand All @@ -37,12 +41,15 @@ impl Resolver {
async fn configure_resolver(
mut resolver: IdentityResolver,
tls_config: Option<rustls::ClientConfig>,
node_urls: Option<NodeUrls>,
basic_auth: Option<(&str, &str)>,
) -> Result<IdentityResolver, ConsumerError> {
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}")))?,
);
Expand Down
85 changes: 64 additions & 21 deletions did_iota/src/consumer.rs
Original file line number Diff line number Diff line change
@@ -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<rustls::ClientConfig>,
node_urls: Option<NodeUrls>,
basic_auth: Option<(&str, &str)>,
) -> Result<Vec<(&'static str, IdentityClientReadOnly)>, 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<String>,
pub testnet: Option<String>,
pub devnet: Option<String>,
}

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();
}
}
2 changes: 1 addition & 1 deletion did_iota/src/producer/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::consumer::iota_clients;

pub async fn resolve(did: IotaDID) -> Result<CoreDocument, anyhow::Error> {
let mut resolver = Resolver::<CoreDocument>::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)
}
Loading