unc 0.15.0

human-friendly console utility that helps to interact with utility building Rust smart contracts from command line.
Documentation
use std::str::FromStr;

use color_eyre::eyre::ContextCompat;
use names::Generator;

use crate::commands::account::create_account::sponsor_by_faucet_service::{
    add_key, before_creating_account, network, NewAccountContext,
};

#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
#[interactive_clap(input_context = crate::GlobalContext)]
#[interactive_clap(output_context = RandomAccountContext)]
pub struct RandomAccount {
    #[interactive_clap(subcommand)]
    access_key_mode: add_key::AccessKeyMode,
}

#[derive(Clone)]
pub struct RandomAccountContext(NewAccountContext);

impl RandomAccountContext {
    pub fn from_previous_context(
        previous_context: crate::GlobalContext,
        _scope: &<RandomAccount as interactive_clap::ToInteractiveClapContextScope>::InteractiveClapContextScope,
    ) -> color_eyre::eyre::Result<Self> {
        let credentials_home_dir = previous_context.config.credentials_home_dir.clone();
        let random_account_id = random_account_id(&previous_context.config.network_connection)?;

        let on_before_creating_account_callback: network::OnBeforeCreatingAccountCallback =
            std::sync::Arc::new({
                move |network_config, new_account_id, public_key| {
                    before_creating_account(
                        network_config,
                        new_account_id,
                        public_key,
                        &credentials_home_dir,
                    )
                }
            });

        Ok(Self(NewAccountContext {
            config: previous_context.config,
            new_account_id: random_account_id,
            on_before_creating_account_callback,
        }))
    }
}

impl From<RandomAccountContext> for NewAccountContext {
    fn from(item: RandomAccountContext) -> Self {
        item.0
    }
}

pub fn random_account_id(
    networks: &linked_hash_map::LinkedHashMap<String, crate::config::NetworkConfig>,
) -> color_eyre::eyre::Result<crate::types::account_id::AccountId> {
    loop {
        let mut generator = Generator::default();
        let random_name = generator.next().wrap_err("Random name generator error")?;
        let account_id = crate::types::account_id::AccountId::from_str(&format!(
            "{random_name}.testnet"
        ))?;
        if !crate::common::is_account_exist(networks, account_id.clone().into()) {
            return Ok(account_id);
        }
    }
}