starkli 0.1.4

Starkli (/ˈstɑːrklaɪ/), a blazing fast CLI tool for Starknet powered by starknet-rs
use std::{io::Read, path::PathBuf};

use anyhow::Result;
use clap::Parser;
use colored::Colorize;
use starknet::{core::types::FieldElement, signers::SigningKey};

#[derive(Debug, Parser)]
pub struct FromKey {
    #[clap(long, help = "Overwrite the file if it already exists")]
    force: bool,
    #[clap(long, help = "Take the private key from stdin instead of prompt")]
    private_key_stdin: bool,
    #[clap(
        long,
        help = "Supply password from command line option instead of prompt"
    )]
    password: Option<String>,
    #[clap(help = "Path to save the JSON keystore")]
    file: PathBuf,
}

impl FromKey {
    pub fn run(self) -> Result<()> {
        if self.password.is_some() {
            eprintln!(
                "{}",
                "WARNING: setting passwords via --password is generally considered insecure, \
                as they will be stored in your shell history or other log files."
                    .bright_magenta()
            );
        }

        if self.file.exists() && !self.force {
            anyhow::bail!("keystore file already exists");
        }

        let private_key = if self.private_key_stdin {
            let mut buffer = String::new();
            std::io::stdin().read_to_string(&mut buffer)?;

            buffer
        } else {
            rpassword::prompt_password("Enter private key: ")?
        };
        let private_key = FieldElement::from_hex_be(private_key.trim())?;

        let password = if let Some(password) = self.password {
            password
        } else {
            rpassword::prompt_password("Enter password: ")?
        };

        let key = SigningKey::from_secret_scalar(private_key);
        key.save_as_keystore(&self.file, &password)?;

        println!(
            "Created new encrypted keystore file: {}",
            std::fs::canonicalize(self.file)?.display()
        );
        println!("Public key: {:#064x}", key.verifying_key().scalar());

        Ok(())
    }
}