#[cfg(windows)] use contractless::common::cli_prompts::prompt_hidden_nonempty; #[cfg(windows)] use contractless::startup::unlock_pipe::pipe_name; #[cfg(windows)] use contractless::startup::unlock_structs::{UnlockPipeRequest, UnlockPipeResponse}; #[cfg(windows)] use contractless::{env, from_slice, to_string}; #[cfg(windows)] use tokio::io::{AsyncReadExt, AsyncWriteExt}; #[cfg(windows)] use tokio::net::windows::named_pipe::ClientOptions; #[cfg(windows)] #[tokio::main] async fn main() { // Keep the Windows-only service helper small: run the pipe request and print any failure. if let Err(err) = run().await { eprintln!("{err}"); std::process::exit(1); } } #[cfg(windows)] async fn run() -> Result<(), Box> { // The helper supports simple service checks as well as submitting the wallet key. let command = env::args().nth(1).unwrap_or_else(|| "submit".to_string()); let request = match command.as_str() { "ping" => UnlockPipeRequest::Ping, "status" => UnlockPipeRequest::Status, "submit" => { // Wallet keys are hidden at the terminal and rejected if the user enters nothing. let wallet_key = prompt_hidden_nonempty( "Please enter your wallet key: ", "Wallet key cannot be empty. Please try again.", ) .await; UnlockPipeRequest::SubmitKey { wallet_key } } other => { return Err(format!( "Unsupported command '{other}'. Use 'submit', 'ping', or 'status'." ) .into()) } }; let pipe = pipe_name(); let payload = to_string(&request)?; // The service unlock pipe uses a length-prefixed JSON payload. let mut client = ClientOptions::new().open(&pipe)?; client.write_u32_le(payload.len() as u32).await?; client.write_all(payload.as_bytes()).await?; // Read the length-prefixed service reply and decode the response enum. let response_len = client.read_u32_le().await? as usize; let mut response_bytes = vec![0u8; response_len]; client.read_exact(&mut response_bytes).await?; let response: UnlockPipeResponse = from_slice(&response_bytes)?; match response { UnlockPipeResponse::Pong => { println!("Pong"); } UnlockPipeResponse::Status { state } => { println!("Service state: {state:?}"); } UnlockPipeResponse::KeyAccepted => { println!("Wallet key accepted."); } UnlockPipeResponse::Error { message } => { return Err(message.into()); } } Ok(()) } #[cfg(not(windows))] fn main() { // Non-Windows builds keep the binary present but clearly report that the pipe does not exist. eprintln!("contractless-submit-key is only supported on Windows."); std::process::exit(1); }