From ddb94acdfc6847043cfc963779f45093df074f92 Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Mon, 15 Sep 2025 09:55:56 -0300 Subject: [PATCH 01/13] refactor: component_templates now also receive `.masp` files Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 36 ++++++++++++++++------- crates/rust-client/src/account/mod.rs | 1 + 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index 9a27d2650..cd624cd99 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -6,7 +6,7 @@ use std::vec; use clap::{Parser, ValueEnum}; use miden_client::Client; -use miden_client::account::component::COMPONENT_TEMPLATE_EXTENSION; +use miden_client::account::component::{COMPONENT_TEMPLATE_EXTENSION, MIDEN_PACKAGE_EXTENSION}; use miden_client::account::{Account, AccountBuilder, AccountStorageMode, AccountType}; use miden_client::auth::{AuthSecretKey, TransactionAuthenticator}; use miden_client::crypto::SecretKey; @@ -153,8 +153,8 @@ pub struct NewAccountCmd { /// Account type to create. #[arg(long, value_enum)] pub account_type: CliAccountType, - /// Optional list of files specifying additional component template files to add to the - /// account. + /// List of files specifying component template files for the account. At + /// lease one component template is required. #[arg(short, long)] pub component_templates: Vec, /// Optional file path to a TOML file containing a list of key/values used for initializing @@ -206,14 +206,30 @@ fn load_component_templates(paths: &[PathBuf]) -> Result(); + + CliError::AccountComponentError( + Box::new(std::io::Error::new(std::io::ErrorKind::NotFound, "File not found")), + format!( + "failed to find {}. None of these files were found: +{looked_files}", + path.display() + ), + ) + })?; + + let bytes = fs::read(components_base_dir.join(found_file))?; let template = AccountComponentTemplate::read_from_bytes(&bytes).map_err(|e| { CliError::AccountComponentError( Box::new(e), diff --git a/crates/rust-client/src/account/mod.rs b/crates/rust-client/src/account/mod.rs index e733bda74..e9d837252 100644 --- a/crates/rust-client/src/account/mod.rs +++ b/crates/rust-client/src/account/mod.rs @@ -71,6 +71,7 @@ use crate::store::{AccountRecord, AccountStatus}; pub mod component { pub const COMPONENT_TEMPLATE_EXTENSION: &str = "mct"; + pub const MIDEN_PACKAGE_EXTENSION: &str = "masp"; pub use miden_lib::account::auth::AuthRpoFalcon512; pub use miden_lib::account::faucets::{BasicFungibleFaucet, FungibleFaucetExt}; From f33a3ccfefb99c42010f79eeb3384dea7967c128 Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Mon, 15 Sep 2025 12:24:59 -0300 Subject: [PATCH 02/13] wip: error handling Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 66 ++++++++++++++++++----- bin/miden-cli/src/config.rs | 1 + 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index cd624cd99..a3179c36a 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -5,26 +5,24 @@ use std::path::PathBuf; use std::vec; use clap::{Parser, ValueEnum}; -use miden_client::Client; use miden_client::account::component::{COMPONENT_TEMPLATE_EXTENSION, MIDEN_PACKAGE_EXTENSION}; use miden_client::account::{Account, AccountBuilder, AccountStorageMode, AccountType}; use miden_client::auth::{AuthSecretKey, TransactionAuthenticator}; use miden_client::crypto::SecretKey; use miden_client::transaction::TransactionRequestBuilder; use miden_client::utils::Deserializable; +use miden_client::Client; use miden_lib::account::auth::AuthRpoFalcon512; use miden_objects::account::{ - AccountComponent, - AccountComponentTemplate, - InitStorageData, - StorageValueName, + AccountComponent, AccountComponentTemplate, InitStorageData, StorageValueName, }; +use miden_objects::vm::Package; use rand::RngCore; use tracing::debug; use crate::commands::account::maybe_set_default_account; use crate::errors::CliError; -use crate::{CliKeyStore, client_binary_name, load_config_file}; +use crate::{client_binary_name, load_config_file, CliKeyStore}; // CLI TYPES // ================================================================================================ @@ -205,6 +203,7 @@ impl NewAccountCmd { fn load_component_templates(paths: &[PathBuf]) -> Result, CliError> { let (cli_config, _) = load_config_file()?; let components_base_dir = &cli_config.component_template_directory; + let packages_dir = &cli_config.package_directory; let mut templates = Vec::new(); let possible_extensions = [COMPONENT_TEMPLATE_EXTENSION, MIDEN_PACKAGE_EXTENSION]; @@ -229,13 +228,54 @@ fn load_component_templates(paths: &[PathBuf]) -> Result { + let bytes = fs::read(components_base_dir.join(&found_file))?; + AccountComponentTemplate::read_from_bytes(&bytes).map_err(|e| { + CliError::AccountComponentError( + Box::new(e), + format!( + "failed to read account component template from {}", + found_file.display() + ), + ) + })? + }, + Some(MIDEN_PACKAGE_EXTENSION) => { + let bytes = fs::read(packages_dir.join(&found_file))?; + let package = Package::read_from_bytes(&bytes).map_err(|e| { + CliError::AccountComponentError( + Box::new(e), + format!( + "failed to read account component template from Package in {}", + found_file.display() + ), + ) + })?; + + AccountComponentTemplate::try_from(package).map_err(|e| { + CliError::AccountComponentError( + Box::new(e), + format!( + "failed to read account component template from Package in {}", + found_file.display() + ), + ) + })? + }, + Some(unknown_extension) => { + todo!(); + // let a = 1; + // Err(CliError::AccountComponentError((), format!())) + }, + None => { + // This case should never occur + todo!(); + }, + }; + templates.push(template); } Ok(templates) diff --git a/bin/miden-cli/src/config.rs b/bin/miden-cli/src/config.rs index c93abdc30..e75870669 100644 --- a/bin/miden-cli/src/config.rs +++ b/bin/miden-cli/src/config.rs @@ -12,6 +12,7 @@ use crate::errors::CliError; const TOKEN_SYMBOL_MAP_FILEPATH: &str = "token_symbol_map.toml"; const DEFAULT_COMPONENT_TEMPLATE_DIR: &str = "./templates"; +const DEFAULT_PACKAGES_DIR: &str = "./packages"; // CLI CONFIG // ================================================================================================ From c0426ae568fa90934d24c97a4addde42042c8eab Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Mon, 15 Sep 2025 13:01:32 -0300 Subject: [PATCH 03/13] refactor: add new packages flag to separate inputs Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 123 +++++++++++----------- bin/miden-cli/src/config.rs | 3 + 2 files changed, 62 insertions(+), 64 deletions(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index a3179c36a..dc74738f3 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -116,6 +116,7 @@ impl NewWalletCmd { account_type, self.storage_mode.into(), &component_template_paths, + &[], self.init_storage_data_path.clone(), self.deploy, ) @@ -155,6 +156,10 @@ pub struct NewAccountCmd { /// lease one component template is required. #[arg(short, long)] pub component_templates: Vec, + /// List of [[miden_core::vm::Package]]s from where a component template is going to be extracted. + /// lease one component template is required. + #[arg(short, long)] + pub packages: Vec, /// Optional file path to a TOML file containing a list of key/values used for initializing /// storage. Each of these keys should map to the templated storage values within the passed /// list of component templates. The user will be prompted to provide values for any keys not @@ -179,6 +184,7 @@ impl NewAccountCmd { self.account_type.into(), self.storage_mode.into(), &self.component_templates, + &self.packages, self.init_storage_data_path.clone(), self.deploy, ) @@ -198,86 +204,74 @@ impl NewAccountCmd { // HELPERS // ================================================================================================ +type ComponentPath = PathBuf; +type PackagePath = PathBuf; /// Reads component templates from the given file paths. // TODO: IO errors should have more context -fn load_component_templates(paths: &[PathBuf]) -> Result, CliError> { +fn load_component_templates( + component_paths: &[ComponentPath], + package_paths: &[PackagePath], +) -> Result, CliError> { let (cli_config, _) = load_config_file()?; let components_base_dir = &cli_config.component_template_directory; let packages_dir = &cli_config.package_directory; let mut templates = Vec::new(); let possible_extensions = [COMPONENT_TEMPLATE_EXTENSION, MIDEN_PACKAGE_EXTENSION]; - for path in paths { - // If the user did not specify an extension, we check which extension - // corresponds to the given file. Extension priority is determined by - // the order in which they appear in the possible_extensions array. - let possible_files = - possible_extensions.iter().map(|extension| path.with_extension(extension)); + for path in component_paths { + let path = if path.extension().is_none() { + path.with_extension(COMPONENT_TEMPLATE_EXTENSION) + } else { + path.clone() + }; + + let bytes = fs::read(components_base_dir.join(&path)).map_err(|e| { + CliError::AccountComponentError( + Box::new(e), + format!("failed to read account component template from {}", path.display()), + ) + })?; + let template = AccountComponentTemplate::read_from_bytes(&bytes).map_err(|e| { + CliError::AccountComponentError( + Box::new(e), + format!("failed to deserialize account component template from {}", path.display()), + ) + })?; + templates.push(template); + } + for path in package_paths { + let path = if path.extension().is_none() { + path.with_extension(MIDEN_PACKAGE_EXTENSION) + } else { + path.clone() + }; - let found_file = possible_files.clone().find(|path| path.exists()).ok_or({ - let looked_files = - possible_files.map(|file| format!("- {}\n", file.display())).collect::(); + let bytes = fs::read(packages_dir.join(&path)).map_err(|e| { + CliError::AccountComponentError( + Box::new(e), + format!("failed to read Package from {}", path.display()), + ) + })?; + let package = Package::read_from_bytes(&bytes).map_err(|e| { CliError::AccountComponentError( - Box::new(std::io::Error::new(std::io::ErrorKind::NotFound, "File not found")), + Box::new(e), + format!("failed to deserialize Package in {}", path.display()), + ) + })?; + + let template = AccountComponentTemplate::try_from(package).map_err(|e| { + CliError::AccountComponentError( + Box::new(e), format!( - "failed to find {}. None of these files were found: -{looked_files}", + "failed to read account component template from Package in {}", path.display() ), ) })?; - - std::dbg!("A PUNTO DE LEER"); - std::dbg!("DONE"); - let template = match found_file.extension().and_then(|ext| ext.to_str()) { - Some(COMPONENT_TEMPLATE_EXTENSION) => { - let bytes = fs::read(components_base_dir.join(&found_file))?; - AccountComponentTemplate::read_from_bytes(&bytes).map_err(|e| { - CliError::AccountComponentError( - Box::new(e), - format!( - "failed to read account component template from {}", - found_file.display() - ), - ) - })? - }, - Some(MIDEN_PACKAGE_EXTENSION) => { - let bytes = fs::read(packages_dir.join(&found_file))?; - let package = Package::read_from_bytes(&bytes).map_err(|e| { - CliError::AccountComponentError( - Box::new(e), - format!( - "failed to read account component template from Package in {}", - found_file.display() - ), - ) - })?; - - AccountComponentTemplate::try_from(package).map_err(|e| { - CliError::AccountComponentError( - Box::new(e), - format!( - "failed to read account component template from Package in {}", - found_file.display() - ), - ) - })? - }, - Some(unknown_extension) => { - todo!(); - // let a = 1; - // Err(CliError::AccountComponentError((), format!())) - }, - None => { - // This case should never occur - todo!(); - }, - }; - templates.push(template); } + Ok(templates) } @@ -304,10 +298,11 @@ async fn create_client_account( account_type: AccountType, storage_mode: AccountStorageMode, component_template_paths: &[PathBuf], + package_paths: &[PathBuf], init_storage_data_path: Option, deploy: bool, ) -> Result { - if component_template_paths.is_empty() { + if component_template_paths.is_empty() && package_paths.is_empty() { return Err(CliError::InvalidArgument( "account must contain at least one component".into(), )); @@ -315,7 +310,7 @@ async fn create_client_account( // Load the component templates and initialization storage data. debug!("Loading component templates..."); - let component_templates = load_component_templates(component_template_paths)?; + let component_templates = load_component_templates(component_template_paths, package_paths)?; debug!("Loaded {} component templates", component_templates.len()); debug!("Loading initialization storage data..."); let init_storage_data = load_init_storage_data(init_storage_data_path)?; diff --git a/bin/miden-cli/src/config.rs b/bin/miden-cli/src/config.rs index e75870669..a0fe5f8b4 100644 --- a/bin/miden-cli/src/config.rs +++ b/bin/miden-cli/src/config.rs @@ -33,6 +33,8 @@ pub struct CliConfig { pub remote_prover_endpoint: Option, /// Path to the directory from where account component template files will be loaded. pub component_template_directory: PathBuf, + /// Path to the directory from where [[miden_core::vm::Package]]s will be loaded. + pub package_directory: PathBuf, /// Maximum number of blocks the client can be behind the network for transactions and account /// proofs to be considered valid. pub max_block_number_delta: Option, @@ -70,6 +72,7 @@ impl Default for CliConfig { token_symbol_map_filepath: Path::new(TOKEN_SYMBOL_MAP_FILEPATH).to_path_buf(), remote_prover_endpoint: None, component_template_directory: Path::new(DEFAULT_COMPONENT_TEMPLATE_DIR).to_path_buf(), + package_directory: Path::new(DEFAULT_PACKAGES_DIR).to_path_buf(), max_block_number_delta: None, } } From c4f6de029b16a8ba35deeb9363890c9e5805e602 Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Mon, 15 Sep 2025 15:07:11 -0300 Subject: [PATCH 04/13] chore: slight retouches to error handling Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 26 +++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index dc74738f3..782e13ca7 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -156,8 +156,8 @@ pub struct NewAccountCmd { /// lease one component template is required. #[arg(short, long)] pub component_templates: Vec, - /// List of [[miden_core::vm::Package]]s from where a component template is going to be extracted. - /// lease one component template is required. + /// List of files containing a Miden Package in `.masp` form from which a + /// component template is extracted. #[arg(short, long)] pub packages: Vec, /// Optional file path to a TOML file containing a list of key/values used for initializing @@ -207,46 +207,53 @@ impl NewAccountCmd { type ComponentPath = PathBuf; type PackagePath = PathBuf; /// Reads component templates from the given file paths. -// TODO: IO errors should have more context fn load_component_templates( component_paths: &[ComponentPath], package_paths: &[PackagePath], ) -> Result, CliError> { let (cli_config, _) = load_config_file()?; - let components_base_dir = &cli_config.component_template_directory; - let packages_dir = &cli_config.package_directory; let mut templates = Vec::new(); - let possible_extensions = [COMPONENT_TEMPLATE_EXTENSION, MIDEN_PACKAGE_EXTENSION]; + let components_base_dir = &cli_config.component_template_directory; for path in component_paths { let path = if path.extension().is_none() { path.with_extension(COMPONENT_TEMPLATE_EXTENSION) } else { path.clone() }; + let path = components_base_dir.join(&path); - let bytes = fs::read(components_base_dir.join(&path)).map_err(|e| { + let bytes = fs::read(&path).map_err(|e| { CliError::AccountComponentError( Box::new(e), format!("failed to read account component template from {}", path.display()), ) })?; + let template = AccountComponentTemplate::read_from_bytes(&bytes).map_err(|e| { CliError::AccountComponentError( Box::new(e), format!("failed to deserialize account component template from {}", path.display()), ) })?; + templates.push(template); } + + let packages_dir = &cli_config.package_directory; for path in package_paths { + // If a user passes in a file with the `.masp` file extension, then we + // leave the passed in path as is; since it probably is a full path. + // This is the case with cargo-miden, which displays the full path to + // stdout after compilation finishes. let path = if path.extension().is_none() { - path.with_extension(MIDEN_PACKAGE_EXTENSION) + let path = path.with_extension(MIDEN_PACKAGE_EXTENSION); + packages_dir.join(&path) } else { path.clone() }; - let bytes = fs::read(packages_dir.join(&path)).map_err(|e| { + let bytes = fs::read(&path).map_err(|e| { CliError::AccountComponentError( Box::new(e), format!("failed to read Package from {}", path.display()), @@ -269,6 +276,7 @@ fn load_component_templates( ), ) })?; + templates.push(template); } From c62aad2cacd880d338212a9abee8566cc3844b1b Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Mon, 15 Sep 2025 15:28:49 -0300 Subject: [PATCH 05/13] chore: linter errors Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 9 ++++++--- bin/miden-cli/src/config.rs | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index 782e13ca7..db70c6ddb 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -5,16 +5,19 @@ use std::path::PathBuf; use std::vec; use clap::{Parser, ValueEnum}; +use miden_client::Client; use miden_client::account::component::{COMPONENT_TEMPLATE_EXTENSION, MIDEN_PACKAGE_EXTENSION}; use miden_client::account::{Account, AccountBuilder, AccountStorageMode, AccountType}; use miden_client::auth::{AuthSecretKey, TransactionAuthenticator}; use miden_client::crypto::SecretKey; use miden_client::transaction::TransactionRequestBuilder; use miden_client::utils::Deserializable; -use miden_client::Client; use miden_lib::account::auth::AuthRpoFalcon512; use miden_objects::account::{ - AccountComponent, AccountComponentTemplate, InitStorageData, StorageValueName, + AccountComponent, + AccountComponentTemplate, + InitStorageData, + StorageValueName, }; use miden_objects::vm::Package; use rand::RngCore; @@ -22,7 +25,7 @@ use tracing::debug; use crate::commands::account::maybe_set_default_account; use crate::errors::CliError; -use crate::{client_binary_name, load_config_file, CliKeyStore}; +use crate::{CliKeyStore, client_binary_name, load_config_file}; // CLI TYPES // ================================================================================================ diff --git a/bin/miden-cli/src/config.rs b/bin/miden-cli/src/config.rs index a0fe5f8b4..72ddf4882 100644 --- a/bin/miden-cli/src/config.rs +++ b/bin/miden-cli/src/config.rs @@ -33,7 +33,7 @@ pub struct CliConfig { pub remote_prover_endpoint: Option, /// Path to the directory from where account component template files will be loaded. pub component_template_directory: PathBuf, - /// Path to the directory from where [[miden_core::vm::Package]]s will be loaded. + /// Path to the directory from where [[`miden_core::vm::Package`]]s will be loaded. pub package_directory: PathBuf, /// Maximum number of blocks the client can be behind the network for transactions and account /// proofs to be considered valid. From 2542f11087dec0a973016f25b1454189602f9b62 Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Mon, 15 Sep 2025 15:34:58 -0300 Subject: [PATCH 06/13] chore: add changelog entry Signed-off-by: Tomas Fabrizio Orsi --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5104000c..693acdc8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * Bumped web-client version in package.json after merging main into next. * Added support for getting specific vault and storage elements from `Store` along with their proofs ([#1164](https://github.com/0xMiden/miden-client/pull/1164)). * Modified the RPC client to avoid reconnection when setting commitment header ([#1166](https://github.com/0xMiden/miden-client/pull/1166)). +* Added account creation from miden packages (#TBD). ## 0.11.3 (2025-09-08) From eb6884ad2d10bc38e67d91581ebab318c7f2c41c Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Tue, 16 Sep 2025 11:24:24 -0300 Subject: [PATCH 07/13] feat: check the file extension before passing the path Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 54 ++++++++++++++++++----- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index db70c6ddb..06e3a7ffa 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -219,12 +219,26 @@ fn load_component_templates( let components_base_dir = &cli_config.component_template_directory; for path in component_paths { - let path = if path.extension().is_none() { - path.with_extension(COMPONENT_TEMPLATE_EXTENSION) - } else { - path.clone() - }; - let path = components_base_dir.join(&path); + let file_name = match path.extension() { + None => Ok(path.with_extension(COMPONENT_TEMPLATE_EXTENSION)), + Some(extension) => { + if extension != OsStr::new(COMPONENT_TEMPLATE_EXTENSION) { + Err(CliError::AccountComponentError( + Box::new(std::io::Error::new( + std::io::ErrorKind::InvalidFilename, + format!("{} has an invalid file extension: {}. Expected: {COMPONENT_TEMPLATE_EXTENSION}", path.display(), extension.display()), + )), + format!( + "failed to read account component template from {}", + path.display() + ), + )) + } else { + Ok(path.clone()) + } + }, + }?; + let path = components_base_dir.join(&file_name); let bytes = fs::read(&path).map_err(|e| { CliError::AccountComponentError( @@ -249,12 +263,28 @@ fn load_component_templates( // leave the passed in path as is; since it probably is a full path. // This is the case with cargo-miden, which displays the full path to // stdout after compilation finishes. - let path = if path.extension().is_none() { - let path = path.with_extension(MIDEN_PACKAGE_EXTENSION); - packages_dir.join(&path) - } else { - path.clone() - }; + let file_name = match path.extension() { + None => { + let path = path.with_extension(MIDEN_PACKAGE_EXTENSION); + Ok(packages_dir.join(path)) + }, + Some(extension) => { + if extension != OsStr::new(MIDEN_PACKAGE_EXTENSION) { + Err(CliError::AccountComponentError( + Box::new(std::io::Error::new( + std::io::ErrorKind::InvalidFilename, + format!("{} has an invalid file extension: {}. Expected: {MIDEN_PACKAGE_EXTENSION}", path.display(), extension.display()), + )), + format!( + "failed to read Package from {}", + path.display() + ), + )) + } else { + Ok(path.clone()) + } + }, + }?; let bytes = fs::read(&path).map_err(|e| { CliError::AccountComponentError( From dd32f20e55de3f3b769db2d15b542ace501fbc45 Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Tue, 16 Sep 2025 11:25:30 -0300 Subject: [PATCH 08/13] chore: update doc comment Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index 06e3a7ffa..cf9f0866e 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -209,7 +209,7 @@ impl NewAccountCmd { type ComponentPath = PathBuf; type PackagePath = PathBuf; -/// Reads component templates from the given file paths. +/// Reads component templates and [[miden_core::vm::Package]]s from the given file paths. fn load_component_templates( component_paths: &[ComponentPath], package_paths: &[PackagePath], From 7c684f6d1357e3088b2898e57ab6fcb5f9ad6a14 Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Tue, 16 Sep 2025 11:49:51 -0300 Subject: [PATCH 09/13] refactor: minor clean-up Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 37 +++++++++++++++-------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index cf9f0866e..dbc3cf8ef 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -220,14 +220,24 @@ fn load_component_templates( let components_base_dir = &cli_config.component_template_directory; for path in component_paths { let file_name = match path.extension() { - None => Ok(path.with_extension(COMPONENT_TEMPLATE_EXTENSION)), + None => { + // Set extension to COMPONENT_TEMPLATE_EXTENSION in case user + // did not + Ok(path.with_extension(COMPONENT_TEMPLATE_EXTENSION)) + }, Some(extension) => { if extension != OsStr::new(COMPONENT_TEMPLATE_EXTENSION) { + let error = std::io::Error::new( + std::io::ErrorKind::InvalidFilename, + format!( + "{} has an invalid file extension: '{}'. \ + Expected: {COMPONENT_TEMPLATE_EXTENSION}", + path.display(), + extension.display() + ), + ); Err(CliError::AccountComponentError( - Box::new(std::io::Error::new( - std::io::ErrorKind::InvalidFilename, - format!("{} has an invalid file extension: {}. Expected: {COMPONENT_TEMPLATE_EXTENSION}", path.display(), extension.display()), - )), + Box::new(error), format!( "failed to read account component template from {}", path.display() @@ -270,15 +280,18 @@ fn load_component_templates( }, Some(extension) => { if extension != OsStr::new(MIDEN_PACKAGE_EXTENSION) { - Err(CliError::AccountComponentError( - Box::new(std::io::Error::new( - std::io::ErrorKind::InvalidFilename, - format!("{} has an invalid file extension: {}. Expected: {MIDEN_PACKAGE_EXTENSION}", path.display(), extension.display()), - )), + let error = std::io::Error::new( + std::io::ErrorKind::InvalidFilename, format!( - "failed to read Package from {}", - path.display() + "{} has an invalid file extension: '{}'. \ + Expected: {MIDEN_PACKAGE_EXTENSION}", + path.display(), + extension.display() ), + ); + Err(CliError::AccountComponentError( + Box::new(error), + format!("failed to read Package from {}", path.display()), )) } else { Ok(path.clone()) From 0047ce1c803ed35586dd710f888937b40ee56e01 Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Tue, 16 Sep 2025 11:57:43 -0300 Subject: [PATCH 10/13] chore: clippy lints Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index dbc3cf8ef..13da4dc07 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::ffi::OsStr; use std::fs::{self, File}; use std::io::{Read, Write}; use std::path::PathBuf; @@ -209,7 +210,7 @@ impl NewAccountCmd { type ComponentPath = PathBuf; type PackagePath = PathBuf; -/// Reads component templates and [[miden_core::vm::Package]]s from the given file paths. +/// Reads component templates and [[`miden_core::vm::Package`]]s from the given file paths. fn load_component_templates( component_paths: &[ComponentPath], package_paths: &[PackagePath], @@ -226,7 +227,9 @@ fn load_component_templates( Ok(path.with_extension(COMPONENT_TEMPLATE_EXTENSION)) }, Some(extension) => { - if extension != OsStr::new(COMPONENT_TEMPLATE_EXTENSION) { + if extension == OsStr::new(COMPONENT_TEMPLATE_EXTENSION) { + Ok(path.clone()) + } else { let error = std::io::Error::new( std::io::ErrorKind::InvalidFilename, format!( @@ -243,8 +246,6 @@ fn load_component_templates( path.display() ), )) - } else { - Ok(path.clone()) } }, }?; @@ -273,13 +274,15 @@ fn load_component_templates( // leave the passed in path as is; since it probably is a full path. // This is the case with cargo-miden, which displays the full path to // stdout after compilation finishes. - let file_name = match path.extension() { + let path = match path.extension() { None => { let path = path.with_extension(MIDEN_PACKAGE_EXTENSION); Ok(packages_dir.join(path)) }, Some(extension) => { - if extension != OsStr::new(MIDEN_PACKAGE_EXTENSION) { + if extension == OsStr::new(MIDEN_PACKAGE_EXTENSION) { + Ok(path.clone()) + } else { let error = std::io::Error::new( std::io::ErrorKind::InvalidFilename, format!( @@ -293,8 +296,6 @@ fn load_component_templates( Box::new(error), format!("failed to read Package from {}", path.display()), )) - } else { - Ok(path.clone()) } }, }?; From b285982b9789cffee0cc2d1af338bc5ba699c96c Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Tue, 16 Sep 2025 11:58:21 -0300 Subject: [PATCH 11/13] typo: lease -> least Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index 13da4dc07..fd9886953 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -157,7 +157,7 @@ pub struct NewAccountCmd { #[arg(long, value_enum)] pub account_type: CliAccountType, /// List of files specifying component template files for the account. At - /// lease one component template is required. + /// least one component template is required. #[arg(short, long)] pub component_templates: Vec, /// List of files containing a Miden Package in `.masp` form from which a From 9617791eac4505f4e34ad6a000489e7018921478 Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Tue, 16 Sep 2025 12:22:50 -0300 Subject: [PATCH 12/13] feat: add packages flag to new-wallet command Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index fd9886953..57594cd75 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -86,6 +86,10 @@ pub struct NewWalletCmd { /// Optional list of files specifying additional components to add to the account. #[arg(short, long)] pub extra_components: Vec, + /// Optional list of files containing a Miden Package in `.masp` form from which a + /// component template can be extracted. + #[arg(short, long)] + pub packages: Vec, /// Optional file path to a TOML file containing a list of key/values used for initializing /// storage. Each of these keys should map to the templated storage values within the passed /// list of component templates. The user will be prompted to provide values for any keys not @@ -120,7 +124,7 @@ impl NewWalletCmd { account_type, self.storage_mode.into(), &component_template_paths, - &[], + &self.packages, self.init_storage_data_path.clone(), self.deploy, ) @@ -156,11 +160,13 @@ pub struct NewAccountCmd { /// Account type to create. #[arg(long, value_enum)] pub account_type: CliAccountType, - /// List of files specifying component template files for the account. At - /// least one component template is required. + /// List of files specifying component template files for the account. + /// At least one component template is required, either specified by + /// [[NewAccountCmd::component_templates]] or by [[NewAccountCmd::packages]]. #[arg(short, long)] pub component_templates: Vec, /// List of files containing a Miden Package in `.masp` form from which a + /// component template is extracted. #[arg(short, long)] pub packages: Vec, From 90c41b3dbe0510af19367703ad2d95a785b18be4 Mon Sep 17 00:00:00 2001 From: Tomas Fabrizio Orsi Date: Tue, 16 Sep 2025 12:49:50 -0300 Subject: [PATCH 13/13] chore: clippy Signed-off-by: Tomas Fabrizio Orsi --- bin/miden-cli/src/commands/new_account.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bin/miden-cli/src/commands/new_account.rs b/bin/miden-cli/src/commands/new_account.rs index 57594cd75..7a9622ee6 100644 --- a/bin/miden-cli/src/commands/new_account.rs +++ b/bin/miden-cli/src/commands/new_account.rs @@ -162,11 +162,10 @@ pub struct NewAccountCmd { pub account_type: CliAccountType, /// List of files specifying component template files for the account. /// At least one component template is required, either specified by - /// [[NewAccountCmd::component_templates]] or by [[NewAccountCmd::packages]]. + /// [[`NewAccountCmd::component_templates`]] or by [[`NewAccountCmd::packages`]]. #[arg(short, long)] pub component_templates: Vec, /// List of files containing a Miden Package in `.masp` form from which a - /// component template is extracted. #[arg(short, long)] pub packages: Vec,