diff --git a/examples/account/config.rs b/examples/account/config.rs index 0eaedf8457..d58dcdc37c 100644 --- a/examples/account/config.rs +++ b/examples/account/config.rs @@ -7,6 +7,7 @@ use identity::account::Account; use identity::account::AccountStorage; use identity::account::AutoSave; use identity::account::Result; +use identity::iota::Network; #[tokio::main] async fn main() -> Result<()> { @@ -20,6 +21,14 @@ async fn main() -> Result<()> { .dropsave(false) // save the account state on drop .milestone(4) // save a snapshot every 4 actions .storage(AccountStorage::Memory) // use the default in-memory storage adapter + // configure the mainnet Tangle client + .client(Network::Mainnet, |builder| { + builder + .node("https://chrysalis-nodes.iota.org") + .unwrap() // unwrap is safe, we provided a valid node URL + .permanode("https://chrysalis-chronicle.iota.org/api/mainnet/", None, None) + .unwrap() // unwrap is safe, we provided a valid permanode URL + }) .build() .await?; diff --git a/identity-account/src/account/account.rs b/identity-account/src/account/account.rs index 1068aef5e1..c931e6ce6c 100644 --- a/identity-account/src/account/account.rs +++ b/identity-account/src/account/account.rs @@ -10,6 +10,7 @@ use identity_did::verification::MethodType; use identity_iota::did::DocumentDiff; use identity_iota::did::IotaDID; use identity_iota::did::IotaDocument; +use identity_iota::tangle::Client; use identity_iota::tangle::ClientMap; use identity_iota::tangle::MessageId; use identity_iota::tangle::TangleResolve; @@ -93,6 +94,10 @@ impl Account { self.state.actions.load(OSC) } + pub fn set_client(&self, client: Client) -> Result<()> { + self.state.clients.insert(client).map_err(Into::into) + } + // =========================================================================== // Identity // =========================================================================== diff --git a/identity-account/src/account/builder.rs b/identity-account/src/account/builder.rs index d12b9a0266..03cf4decb2 100644 --- a/identity-account/src/account/builder.rs +++ b/identity-account/src/account/builder.rs @@ -1,6 +1,9 @@ // Copyright 2020-2021 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use hashbrown::HashMap; +use identity_iota::tangle::ClientBuilder; +use identity_iota::tangle::Network; use std::path::PathBuf; use zeroize::Zeroize; @@ -25,6 +28,7 @@ pub enum AccountStorage { pub struct AccountBuilder { config: Config, storage: AccountStorage, + clients: Option>, } impl AccountBuilder { @@ -33,6 +37,7 @@ impl AccountBuilder { Self { config: Config::new(), storage: AccountStorage::Memory, + clients: None, } } @@ -60,10 +65,22 @@ impl AccountBuilder { self } + /// Apply configuration to the IOTA Tangle client for the given `Network`. + pub fn client(mut self, network: Network, f: F) -> Self + where + F: FnOnce(ClientBuilder) -> ClientBuilder, + { + self + .clients + .get_or_insert_with(HashMap::new) + .insert(network, f(ClientBuilder::new().network(network))); + self + } + /// Creates a new [Account] based on the builder configuration. - pub async fn build(self) -> Result { - match self.storage { - AccountStorage::Memory => Account::with_config(MemStore::new(), self.config).await, + pub async fn build(mut self) -> Result { + let account: Account = match self.storage { + AccountStorage::Memory => Account::with_config(MemStore::new(), self.config).await?, AccountStorage::Stronghold(snapshot, password) => { let passref: Option<&str> = password.as_deref(); let adapter: Stronghold = Stronghold::new(&snapshot, passref).await?; @@ -72,10 +89,18 @@ impl AccountBuilder { password.zeroize(); } - Account::with_config(adapter, self.config).await + Account::with_config(adapter, self.config).await? + } + AccountStorage::Custom(adapter) => Account::with_config(adapter, self.config).await?, + }; + + if let Some(clients) = self.clients.take() { + for (_, client) in clients.into_iter() { + account.set_client(client.build().await?)?; } - AccountStorage::Custom(adapter) => Account::with_config(adapter, self.config).await, } + + Ok(account) } } diff --git a/identity-iota/src/tangle/client_map.rs b/identity-iota/src/tangle/client_map.rs index 5f78cf1377..04d74ea2ba 100644 --- a/identity-iota/src/tangle/client_map.rs +++ b/identity-iota/src/tangle/client_map.rs @@ -54,6 +54,16 @@ impl ClientMap { Client::from_builder(builder).await.map(Self::from_client) } + pub fn insert(&self, client: Client) -> Result<()> { + self + .data + .write() + .map_err(|_| Error::SharedWritePoisoned)? + .insert(client.network, Arc::new(client)); + + Ok(()) + } + pub async fn publish_document(&self, document: &IotaDocument) -> Result { let network: Network = document.id().network(); let client: Arc = self.client(network).await?;