87 lines
2.8 KiB
Rust
87 lines
2.8 KiB
Rust
#[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<dyn std::error::Error>> {
|
|
// 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);
|
|
}
|