Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions seedelf-platform/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ members = [

[workspace.dependencies]
seedelf-core = "0.4.10"
seedelf-cli = "0.4.10"
seedelf-crypto = "0.4.10"
seedelf-display = "0.4.10"
seedelf-koios = "0.4.10"


[patch.crates-io]
seedelf-core = { path = "seedelf-core" }
seedelf-cli = { path = "seedelf-cli" }
seedelf-crypto = { path = "seedelf-crypto" }
seedelf-display = { path = "seedelf-display" }
seedelf-koios = { path = "seedelf-koios" }
Expand Down
3 changes: 2 additions & 1 deletion seedelf-platform/seedelf-cli/src/commands/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ pub async fn run(network_flag: bool, variant: u64) -> Result<()> {

println!("{}", "\nSeedelf Wallet Information:".bright_white());

let scalar: Scalar = setup::load_wallet();
let password: String = setup::enter_password();
let scalar: Scalar = setup::load_wallet(password);

let config: Config = get_config(variant, network_flag).unwrap_or_else(|| {
eprintln!("Error: Invalid Variant");
Expand Down
5 changes: 3 additions & 2 deletions seedelf-platform/seedelf-cli/src/commands/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,9 @@ pub async fn run(args: LabelArgs, network_flag: bool, variant: u64) -> Result<()
}

// this is going to be the datum on the seedelf
let sk: Scalar = setup::load_wallet();
let datum_vector: Vec<u8> = Register::create(sk)?.rerandomize()?.to_vec()?;
let password: String = setup::enter_password();
let scalar: Scalar = setup::load_wallet(password);
let datum_vector: Vec<u8> = Register::create(scalar)?.rerandomize()?.to_vec()?;
let redeemer_vector: Vec<u8> = data_structures::create_mint_redeemer(label.clone())?;

// lets build the seelfelf token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ pub async fn run(network_flag: bool) -> Result<()> {
"This wallet may receive funds without using the wallet contract.".bright_yellow()
);

let scalar: Scalar = setup::load_wallet();
let password: String = setup::enter_password();
let scalar: Scalar = setup::load_wallet(password);

let vkey: String = convert::secret_key_to_public_key(scalar);
println!("Public Key Hash: {}", vkey.bright_blue());
Expand Down
3 changes: 2 additions & 1 deletion seedelf-platform/seedelf-cli/src/commands/external/sweep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ pub async fn run(network_flag: bool, variant: u64) -> Result<()> {
let mut draft_tx: StagingTransaction = StagingTransaction::new();

// we need this to rerandomize a datum
let scalar: Scalar = setup::load_wallet();
let password: String = setup::enter_password();
let scalar: Scalar = setup::load_wallet(password);

let vkey: String = convert::secret_key_to_public_key(scalar);
let addr: Address = address::dapp_address(vkey.clone(), network_flag)?;
Expand Down
3 changes: 2 additions & 1 deletion seedelf-platform/seedelf-cli/src/commands/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ pub async fn run(args: RemoveArgs, network_flag: bool, variant: u64) -> Result<(
let mut input_vector: Vec<Input> = Vec::new();

// There is a single register here so we can do this
let scalar: Scalar = setup::load_wallet();
let password: String = setup::enter_password();
let scalar: Scalar = setup::load_wallet(password);

let every_utxo: Vec<UtxoResponse> =
utxos::get_credential_utxos(config.contract.wallet_contract_hash, network_flag).await?;
Expand Down
3 changes: 2 additions & 1 deletion seedelf-platform/seedelf-cli/src/commands/sweep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ pub async fn run(args: SweepArgs, network_flag: bool, variant: u64) -> Result<()
let lovelace_goal: u64 = args.lovelace.unwrap_or(minimum_lovelace);

// if there is change going back then we need this to rerandomize a datum
let scalar: Scalar = setup::load_wallet();
let password: String = setup::enter_password();
let scalar: Scalar = setup::load_wallet(password);

let every_utxo: Vec<UtxoResponse> =
utxos::get_credential_utxos(config.contract.wallet_contract_hash, network_flag).await?;
Expand Down
3 changes: 2 additions & 1 deletion seedelf-platform/seedelf-cli/src/commands/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ pub async fn run(args: TransforArgs, network_flag: bool, variant: u64) -> Result
let lovelace_goal: u64 = args.lovelace.unwrap_or(minimum_lovelace);

// if there is change going back then we need this to rerandomize a datum
let scalar: Scalar = setup::load_wallet();
let password: String = setup::enter_password();
let scalar: Scalar = setup::load_wallet(password);

let every_utxo: Vec<UtxoResponse> =
utxos::get_credential_utxos(config.contract.wallet_contract_hash, network_flag).await?;
Expand Down
3 changes: 2 additions & 1 deletion seedelf-platform/seedelf-cli/src/commands/util/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use seedelf_crypto::register::Register;

pub fn run() {
println!("\n{}", "Register Base Element".bright_cyan());
let scalar: Scalar = setup::load_wallet();
let password: String = setup::enter_password();
let scalar: Scalar = setup::load_wallet(password);
let base: Register = Register::create(scalar).unwrap();
println!(
"\n{} {}",
Expand Down
3 changes: 2 additions & 1 deletion seedelf-platform/seedelf-cli/src/commands/util/expose_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub fn run() {
"\n{}\n",
"This command will display your secret key. Press Crtl-C To Exit.".bright_yellow()
);
let scalar: Scalar = setup::load_wallet();
let password: String = setup::enter_password();
let scalar: Scalar = setup::load_wallet(password);
println!("\n{scalar}\n");
}
3 changes: 2 additions & 1 deletion seedelf-platform/seedelf-cli/src/commands/util/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ pub async fn run(args: HistoryArgs, network_flag: bool, variant: u64) -> Result<
display::is_their_an_update().await;
display::preprod_text(network_flag);

let scalar: Scalar = setup::load_wallet();
let password: String = setup::enter_password();
let scalar: Scalar = setup::load_wallet(password);
let config: Config = get_config(variant, network_flag).unwrap_or_else(|| {
eprintln!("Error: Invalid Variant");
std::process::exit(1);
Expand Down
3 changes: 2 additions & 1 deletion seedelf-platform/seedelf-cli/src/commands/util/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ pub async fn run(args: MintArgs, network_flag: bool, variant: u64) -> Result<()>
let label: String = args.label.unwrap_or_default();

// if there is change going back then we need this to rerandomize a datum
let scalar: Scalar = setup::load_wallet();
let password: String = setup::enter_password();
let scalar: Scalar = setup::load_wallet(password);

let every_utxo: Vec<UtxoResponse> =
utxos::get_credential_utxos(config.contract.wallet_contract_hash, network_flag).await?;
Expand Down
13 changes: 12 additions & 1 deletion seedelf-platform/seedelf-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use clap::{Parser, Subcommand};
mod commands;
use seedelf_cli::setup;
use seedelf_core::constants::VARIANT;
use seedelf_display::text_coloring::{display_blue, display_cyan, display_yellow};
// use std::path::PathBuf;

#[derive(Parser)]
#[command(name = "seedelf-cli")]
Expand Down Expand Up @@ -49,7 +51,16 @@ async fn main() {

// Run setup only if the command is not `--help` or `--version`
if cli.command.is_some() {
setup::check_and_prepare_seedelf();
display_blue("Checking For Existing Seedelf Wallet");
match setup::check_and_prepare_seedelf() {
None => {
let wallet_name: String = setup::prompt_wallet_name();
let password: String = setup::is_valid_password();
setup::create_wallet(wallet_name.clone(), password);
display_yellow(format!("Wallet Created: {wallet_name}").as_str());
}
Some(wallet_name) => display_cyan(format!("Found Wallet: {wallet_name}").as_str()),
}
}

match cli.command {
Expand Down
92 changes: 42 additions & 50 deletions seedelf-platform/seedelf-cli/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ struct EncryptedData {
data: String,
}

/// Check if `.seedelf` exists, create it if it doesn't, and handle file logic
pub fn check_and_prepare_seedelf() {
println!("{}", "Checking For Existing Seedelf Wallet".bright_blue());

pub fn seedelf_home_path() -> PathBuf {
let home: PathBuf = home_dir().expect("Failed to get home directory");
let seedelf_path: PathBuf = home.join(".seedelf");
seedelf_path
}

/// Check if `.seedelf` exists, create it if it doesn't, and handle file logic
pub fn check_and_prepare_seedelf() -> Option<String> {
let seedelf_path: PathBuf = seedelf_home_path();

// Check if `.seedelf` exists
if !seedelf_path.exists() {
Expand All @@ -48,21 +51,19 @@ pub fn check_and_prepare_seedelf() {
.collect::<Vec<_>>();

if contents.is_empty() {
// Prompt the user for a wallet name
let wallet_name = prompt_wallet_name();
let wallet_file_path = seedelf_path.join(format!("{wallet_name}.wallet"));
create_wallet(&wallet_file_path);
None
} else {
for entry in &contents {
if let Ok(file_name) = entry.file_name().into_string() {
println!("Found Wallet: {}", file_name.bright_cyan());
return Some(file_name);
}
}
None
}
}

/// Prompt the user to enter a wallet name
fn prompt_wallet_name() -> String {
pub fn prompt_wallet_name() -> String {
let mut wallet_name = String::new();
println!("{}", "\nEnter A Wallet Name:".bright_purple());
io::stdout().flush().unwrap();
Expand All @@ -77,28 +78,17 @@ fn prompt_wallet_name() -> String {
final_name
}

/// Create a wallet file and save a random private key
fn create_wallet(wallet_path: &PathBuf) {
// Generate a random private key
let sk: Scalar = random_scalar(); // Requires `Field` trait in scope
let private_key_bytes: [u8; 32] = sk.to_repr(); // Use `to_repr()` to get canonical bytes
let private_key_hex: String = hex::encode(private_key_bytes);

// Serialize the wallet
let wallet: Wallet = Wallet {
private_key: private_key_hex,
};
let wallet_data: String =
serde_json::to_string_pretty(&wallet).expect("Failed to serialize wallet");

// Prompt user for an encryption password
pub fn enter_password() -> String {
println!(
"{}",
"\nEnter A Password To Encrypt The Wallet:".bright_purple()
);
let password: String = read_password().expect("Failed to read password");
password
}

// check for basic password complexity
pub fn is_valid_password() -> String {
let password: String = enter_password();
if !password_complexity_check(password.clone()) {
println!(
"{}",
Expand All @@ -110,17 +100,30 @@ fn create_wallet(wallet_path: &PathBuf) {
Special Character: Requires At Least One Special Symbol.\n"
.red()
);
return create_wallet(wallet_path);
return is_valid_password();
}
let password_copy: String = enter_password();

println!("{}", "Re-enter the password:".purple());
let password_copy: String = read_password().expect("Failed to read password");
// this is just a simple way to check if the user typed it in correctly
// if they do it twice then they probably mean it
if password != password_copy {
println!("{}", "Passwords Do Not Match; Try Again!".red());
return create_wallet(wallet_path);
return is_valid_password();
}
password
}

/// Create a wallet file and save a random private key
pub fn create_wallet(wallet_name: String, password: String) {
// Generate a random private key
let sk: Scalar = random_scalar(); // Requires `Field` trait in scope
let private_key_bytes: [u8; 32] = sk.to_repr(); // Use `to_repr()` to get canonical bytes
let private_key_hex: String = hex::encode(private_key_bytes);

// Serialize the wallet
let wallet: Wallet = Wallet {
private_key: private_key_hex,
};
let wallet_data: String =
serde_json::to_string_pretty(&wallet).expect("Failed to serialize wallet");

let salt: SaltString = SaltString::generate(&mut OsRng);
let mut output_key_material: [u8; 32] = [0u8; 32];
Expand All @@ -130,8 +133,6 @@ fn create_wallet(wallet_path: &PathBuf) {
&mut output_key_material,
);

// let key: &Key<Aes256Gcm> = output_key_material.into();
// let key = Key::from_slice(&output_key_material);
let key = Key::<Aes256Gcm>::from_slice(&output_key_material);
let cipher = Aes256Gcm::new(key);
let nonce = Aes256Gcm::generate_nonce(&mut OsRng);
Expand All @@ -150,18 +151,16 @@ fn create_wallet(wallet_path: &PathBuf) {
let output_data: String =
serde_json::to_string_pretty(&output).expect("Failed to serialize wallet");

let seedelf_path: PathBuf = seedelf_home_path();
let wallet_path = seedelf_path.join(format!("{wallet_name}.wallet"));

// Save to file
fs::write(wallet_path, output_data).expect("Failed to write wallet file");
println!(
"Wallet Created At: {}",
wallet_path.display().to_string().yellow()
);
fs::write(wallet_path.clone(), output_data).expect("Failed to write wallet file");
}

/// Load the wallet file and deserialize the private key into a Scalar
pub fn load_wallet() -> Scalar {
let home: PathBuf = home_dir().expect("Failed to get home directory");
let seedelf_path: PathBuf = home.join(".seedelf");
pub fn load_wallet(password: String) -> Scalar {
let seedelf_path: PathBuf = seedelf_home_path();

// Get the list of files in `.seedelf`
let contents: Vec<fs::DirEntry> = fs::read_dir(&seedelf_path)
Expand All @@ -184,13 +183,6 @@ pub fn load_wallet() -> Scalar {
let encrypted_wallet: EncryptedData =
serde_json::from_str(&wallet_data).expect("Failed to parse wallet JSON");

// Prompt user for the decryption password
println!(
"{}",
"\nEnter The Password To Decrypt The Wallet:".bright_purple()
);
let password: String = read_password().expect("Failed to read password");

// Derive the decryption key using the provided salt
let salt: SaltString =
SaltString::from_b64(&encrypted_wallet.salt).expect("Invalid salt format");
Expand Down Expand Up @@ -231,7 +223,7 @@ pub fn load_wallet() -> Scalar {
}
Err(_) => {
eprintln!("{}", "Failed To Decrypt; Try Again!".red());
load_wallet()
load_wallet(password)
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions seedelf-platform/seedelf-display/src/text_coloring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@ pub fn display_blue(text: &str) {
println!("\n{}", text.bright_blue());
}

pub fn display_cyan(text: &str) {
println!("\n{}", text.bright_cyan());
}

pub fn display_purple(text: &str) {
println!("\n{}", text.bright_purple());
}

pub fn display_yellow(text: &str) {
println!("\n{}", text.bright_yellow());
}

/// Print the UTxO & balance counts in a consistent, coloured style.
pub fn show_lovelace_and_utxos_counts(
total_utxos: usize,
Expand Down
Loading