use miden_client::account::component::{AccountComponent, BasicWallet};
use miden_client::account::{Account, AccountBuilder, AccountType};
use miden_client::auth::{AuthSchemeId as NativeAuthScheme, AuthSecretKey, AuthSingleSig};
use rand::rngs::StdRng;
use rand::{RngCore, SeedableRng};
use wasm_bindgen::JsValue;
use crate::js_error_with_context;
use crate::models::account_storage_mode::AccountStorageMode;
use crate::models::auth::AuthScheme;
pub(crate) async fn generate_wallet(
storage_mode: &AccountStorageMode,
mutable: bool,
seed: Option<Vec<u8>>,
auth_scheme: AuthScheme,
) -> Result<(Account, AuthSecretKey), JsValue> {
let mut rng = match seed {
Some(seed_bytes) => {
let seed_array: [u8; 32] = seed_bytes
.try_into()
.map_err(|_| JsValue::from_str("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(JsValue::from_str(&message));
},
};
let auth_component: AccountComponent =
AuthSingleSig::new(key_pair.public_key().to_commitment(), native_scheme).into();
let account_type = if mutable {
AccountType::RegularAccountUpdatableCode
} else {
AccountType::RegularAccountImmutableCode
};
let mut init_seed = [0u8; 32];
rng.fill_bytes(&mut init_seed);
let new_account = AccountBuilder::new(init_seed)
.account_type(account_type)
.storage_mode(storage_mode.into())
.with_auth_component(auth_component)
.with_component(BasicWallet)
.build()
.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))
}