2026-05-24 17:56:57 +00:00
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
2026-05-26 06:24:57 +00:00
let _ = std ::fmt ::write ( & mut result , format_args! ( " {input:<width$} " ) ) ;
2026-05-24 17:56:57 +00:00
result
}
fn display_fee ( value : u64 ) -> 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} " ) ;
}