use blockchain::blocks::token::{CreateTokenTransaction, UnsignedCreateTokenTransaction}; use blockchain::common::cli_prompts::{prompt_hidden_nonempty, prompt_visible}; use blockchain::common::types::CREATE_TOKEN_FEE; use blockchain::json; use blockchain::wallets::structures::Wallet; use blockchain::File; use blockchain::Utc; use blockchain::{create_dir_all, AsyncWriteExt}; // pad the coin to ensure 15 characters fn pad_to_width(input: &str, width: usize) -> String { let mut result = String::with_capacity(width); // Pre-allocate string with capacity let _ = std::fmt::write( &mut result, format_args!("{input: f64 { value as f64 / 100_000_000.0 } #[tokio::main] async fn main() { // set type and timestampe let txtype = 3; let timestamp = Utc::now().timestamp() as u32; // get user input ticker let ticker_name = prompt_visible("Please enter the ticker / token name you wish to create. This can be 3 to 15 characters and must be 100% unique. First come first serve: ").await; let ticker = pad_to_width(ticker_name.trim(), 15); // get user input value let number_string = prompt_visible( "Please enter the amount of coins or tokens to create: (eg. 1, 1000, 100000, etc): ", ) .await; let number_u64: u64 = number_string .trim() .parse() .expect("Please enter a valid age"); let number = ((number_u64 as f64) * (100000000_f64)).round() as u64; let hard_limit_string = prompt_visible("Should this token have a hard cap? Enter 1 for yes or 0 for no: ").await; let hard_limit: u8 = hard_limit_string .trim() .parse() .expect("Please enter 1 or 0."); if hard_limit > 1 { println!("hard_limit must be 1 or 0."); return; } // get user input txfee let txfee_prompt = format!( "Please enter the amount for the fee: (eg. 500, minimum fee {:.8})", display_fee(CREATE_TOKEN_FEE) ); let txfee_string = prompt_visible(&format!("{txfee_prompt}: ")).await; let txfee_f32: f32 = txfee_string .trim() .parse() .expect("Please enter a valid value."); let txfee = ((txfee_f32 as f64) * (100000000_f64)).round() as u64; let decryption_key = prompt_hidden_nonempty( "What is your wallet decryption key? ", "Wallet key cannot be empty. Please try again.", ) .await; let wallet = match Wallet::try_obtain_wallet(decryption_key, None).await { Ok(wallet) => wallet, Err(err) => { eprintln!("Wallet decryption failed: {err}"); return; } }; let private_key = &wallet.saved.private_key; let address = &wallet.saved.short_address; // validate wallets if !Wallet::short_address_validation(address.trim_matches('"')) { println!("creatpr wallet invalid: {}", &address); return; } let unsigned_create_token = UnsignedCreateTokenTransaction::new( txtype, timestamp, address.trim_matches('"'), &ticker, number, hard_limit, txfee, ) .await; let create_token = match CreateTokenTransaction::new(unsigned_create_token, private_key).await { Ok(tx) => tx, Err(err) => { eprintln!("Failed to sign token transaction: {err}"); return; } }; let hashed_data = create_token.unsigned_create_token.hash().await; let signature = create_token.signature.clone(); //add the signature and hash let output = json!({ "txtype": txtype, "timestamp": timestamp, "creator": address.trim_matches('"'), "ticker": ticker, "number": number, "hard_limit": hard_limit, "txfee": txfee, "hash": hashed_data, "signature": signature, }); let output_str = serde_json::to_string_pretty(&output).expect("Failed to serialize JSON"); // Define the directory path let dir_path = "./transactions"; // Create the directory if it doesn't exist if let Err(e) = create_dir_all(&dir_path).await { eprintln!("Failed to create directory: {e}"); return; } // Define the file path let file_path = format!("{dir_path}/{hashed_data}.json"); // Open the file for writing asynchronously let mut file = File::create(&file_path) .await .expect("Failed to create file"); // Write the JSON string to the file asynchronously if let Err(e) = file.write_all(output_str.as_bytes()).await { eprintln!("Failed to write file: {e}"); return; } println!("transaction: {output_str}"); }