use std::path::PathBuf;
use std::sync::Arc;
use std::{env, fs};
use miden_client::account::component::{
AccountComponentMetadata,
AuthMultisig,
AuthSingleSig,
AuthSingleSigAcl,
BasicWallet,
FungibleFaucet,
MIDEN_PACKAGE_EXTENSION,
NoAuth,
};
use miden_client::assembly::Library;
use miden_client::utils::Serializable;
use miden_client::vm::{
Package,
PackageExport,
PackageManifest,
ProcedureExport,
QualifiedProcedureName,
Section,
SectionId,
TargetType,
};
const PACKAGE_DIR: &str = "packages";
fn main() {
let basic_wallet_metadata = BasicWallet::component_metadata();
build_package(
"basic-wallet",
BasicWallet::code().as_library().clone(),
&basic_wallet_metadata,
None,
);
let basic_faucet_metadata = FungibleFaucet::component_metadata();
build_package(
"basic-fungible-faucet",
FungibleFaucet::code().as_library().clone(),
&basic_faucet_metadata,
None,
);
let singlesig_metadata = AuthSingleSig::component_metadata();
build_package(
"basic-auth",
AuthSingleSig::code().as_library().clone(),
&singlesig_metadata,
Some("auth"),
);
build_package(
"ecdsa-auth",
AuthSingleSig::code().as_library().clone(),
&singlesig_metadata,
Some("auth"),
);
let no_auth_metadata = NoAuth::component_metadata();
build_package("no-auth", NoAuth::code().as_library().clone(), &no_auth_metadata, Some("auth"));
let multisig_metadata = AuthMultisig::component_metadata();
build_package(
"multisig-auth",
AuthMultisig::code().as_library().clone(),
&multisig_metadata,
Some("auth"),
);
let acl_metadata = AuthSingleSigAcl::component_metadata();
build_package(
"acl-auth",
AuthSingleSigAcl::code().as_library().clone(),
&acl_metadata,
Some("auth"),
);
}
pub fn build_package(
package_name: &str,
library: Library,
metadata: &AccountComponentMetadata,
subdirectory: Option<&str>,
) {
let mut exports: Vec<PackageExport> = Vec::new();
for module_info in library.module_infos() {
for (_, proc_info) in module_info.procedures() {
let name = QualifiedProcedureName::new(module_info.path(), proc_info.name.clone());
let export = ProcedureExport {
path: name.into_inner(),
digest: proc_info.digest,
signature: proc_info.signature.as_deref().cloned(),
attributes: proc_info.attributes.clone(),
};
exports.push(PackageExport::Procedure(export));
}
}
let mast = Arc::new(library);
let manifest = PackageManifest::new(exports).expect("manifest validation failed");
let account_component_metadata_section =
Section::new(SectionId::ACCOUNT_COMPONENT_METADATA, metadata.to_bytes());
let package = Package {
name: metadata.name().to_string().into(),
version: metadata.version().clone(),
description: Some(metadata.description().to_string()),
mast,
manifest,
sections: vec![account_component_metadata_section],
kind: TargetType::AccountComponent,
};
let out_dir = env::var("OUT_DIR").expect("OUT_DIR environment variable not set");
let mut packages_out_dir = PathBuf::from(&out_dir).join(PACKAGE_DIR);
if let Some(subdir) = subdirectory {
packages_out_dir = packages_out_dir.join(subdir);
}
fs::create_dir_all(&packages_out_dir).expect("Failed to packages directory in OUT_DIR");
let output_filename = format!("{package_name}.{MIDEN_PACKAGE_EXTENSION}");
let output_file = packages_out_dir.join(&output_filename);
fs::write(&output_file, package.to_bytes()).unwrap_or_else(|e| {
panic!(
"Failed to write Package {} to file {} in {}. Error: {}",
package.name, output_filename, out_dir, e
);
});
}