use miden_client::account::component::{
AccountComponent,
BasicWallet,
BurnPolicyConfig,
FungibleFaucet,
MintPolicyConfig,
PolicyRegistration,
TokenName,
TokenPolicyManager,
};
use miden_client::account::{Account, AccountBuilder, AccountBuilderSchemaCommitmentExt};
use miden_client::asset::{AssetAmount, TokenSymbol};
use miden_client::auth::{AuthSchemeId as NativeAuthScheme, AuthSecretKey, AuthSingleSig};
use rand::rngs::StdRng;
use rand::{RngCore, SeedableRng};
use crate::js_error_with_context;
use crate::models::account_storage_mode::AccountStorageMode;
use crate::models::auth::AuthScheme;
use crate::platform::{JsErr, from_str_err};
pub(crate) async fn generate_wallet(
storage_mode: &AccountStorageMode,
seed: Option<Vec<u8>>,
auth_scheme: AuthScheme,
) -> Result<(Account, AuthSecretKey), JsErr> {
let mut rng = match seed {
Some(seed_bytes) => {
let seed_array: [u8; 32] = seed_bytes
.try_into()
.map_err(|_| from_str_err("Seed must be exactly 32 bytes"))?;
StdRng::from_seed(seed_array)
},
None => StdRng::from_os_rng(),
};
let native_scheme: NativeAuthScheme = auth_scheme.try_into()?;
let key_pair = match native_scheme {
NativeAuthScheme::Falcon512Poseidon2 => {
AuthSecretKey::new_falcon512_poseidon2_with_rng(&mut rng)
},
NativeAuthScheme::EcdsaK256Keccak => {
AuthSecretKey::new_ecdsa_k256_keccak_with_rng(&mut rng)
},
_ => {
let message = format!("unsupported auth scheme: {native_scheme:?}");
return Err(from_str_err(&message));
},
};
let auth_component: AccountComponent =
AuthSingleSig::new(key_pair.public_key().to_commitment(), native_scheme).into();
let mut init_seed = [0u8; 32];
rng.fill_bytes(&mut init_seed);
let new_account = AccountBuilder::new(init_seed)
.account_type(storage_mode.into())
.with_auth_component(auth_component)
.with_component(BasicWallet)
.build_with_schema_commitment()
.map_err(|err| js_error_with_context(err, "failed to create new wallet"))?;
let _account_seed =
new_account.seed().expect("newly built wallet should always contain a seed");
Ok((new_account, key_pair))
}
pub(crate) async fn generate_faucet(
storage_mode: &AccountStorageMode,
token_name: String,
token_symbol: String,
decimals: u8,
max_supply: u64,
auth_scheme: AuthScheme,
) -> Result<(Account, AuthSecretKey), JsErr> {
let mut rng = StdRng::from_os_rng();
let native_scheme: NativeAuthScheme = auth_scheme.try_into()?;
let key_pair = match native_scheme {
NativeAuthScheme::Falcon512Poseidon2 => {
AuthSecretKey::new_falcon512_poseidon2_with_rng(&mut rng)
},
NativeAuthScheme::EcdsaK256Keccak => {
AuthSecretKey::new_ecdsa_k256_keccak_with_rng(&mut rng)
},
_ => {
let message = format!("unsupported auth scheme: {native_scheme:?}");
return Err(from_str_err(&message));
},
};
let auth_component: AccountComponent =
AuthSingleSig::new(key_pair.public_key().to_commitment(), native_scheme).into();
let symbol = TokenSymbol::new(&token_symbol).map_err(|err| from_str_err(&err.to_string()))?;
let name = TokenName::new(&token_name).map_err(|err| from_str_err(&err.to_string()))?;
let max_supply = AssetAmount::new(max_supply).map_err(|err| from_str_err(&err.to_string()))?;
let faucet = FungibleFaucet::builder()
.name(name)
.symbol(symbol)
.decimals(decimals)
.max_supply(max_supply)
.build()
.map_err(|err| js_error_with_context(err, "failed to build fungible faucet"))?;
let policy_manager = TokenPolicyManager::new()
.with_mint_policy(MintPolicyConfig::AllowAll, PolicyRegistration::Active)
.map_err(|err| js_error_with_context(err, "failed to register mint policy"))?
.with_burn_policy(BurnPolicyConfig::AllowAll, PolicyRegistration::Active)
.map_err(|err| js_error_with_context(err, "failed to register burn policy"))?;
let mut init_seed = [0u8; 32];
rng.fill_bytes(&mut init_seed);
let new_account = AccountBuilder::new(init_seed)
.account_type(storage_mode.into())
.with_auth_component(auth_component)
.with_component(faucet)
.with_components(policy_manager)
.build_with_schema_commitment()
.map_err(|err| js_error_with_context(err, "failed to create new faucet"))?;
Ok((new_account, key_pair))
}