diff --git a/crates/jstzd/src/task/octez_client.rs b/crates/jstzd/src/task/octez_client.rs index c7a7e5b7..7bc14c41 100644 --- a/crates/jstzd/src/task/octez_client.rs +++ b/crates/jstzd/src/task/octez_client.rs @@ -2,7 +2,7 @@ use super::{directory::Directory, endpoint::Endpoint, octez_node::DEFAULT_RPC_EN use anyhow::{anyhow, bail, Result}; use http::Uri; use std::path::Path; -use std::{ffi::OsStr, path::PathBuf, str::FromStr}; +use std::{ffi::OsStr, fmt, path::PathBuf, str::FromStr}; use tempfile::tempdir; use tokio::process::{Child, Command}; @@ -76,6 +76,25 @@ impl OctezClientBuilder { } } +#[derive(Debug)] +pub enum Signature { + ED25519, + SECP256K1, + P256, + BLS, +} + +impl fmt::Display for Signature { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Signature::ED25519 => write!(f, "ed25519"), + Signature::SECP256K1 => write!(f, "secp256k1"), + Signature::P256 => write!(f, "p256"), + Signature::BLS => write!(f, "bls"), + } + } +} + #[derive(Debug)] pub struct OctezClient { binary_path: PathBuf, @@ -121,6 +140,22 @@ impl OctezClient { .await?; Ok(()) } + + pub async fn gen_keys( + &self, + alias: &str, + signature: Option, + ) -> Result<()> { + let mut command = self.command(["gen", "keys", alias])?; + if let Some(signature) = signature { + command.args(["--sig", &signature.to_string()]); + } + let status = command.spawn()?.wait().await?; + match status.code() { + Some(0) => Ok(()), + _ => bail!("failed to generate keys for {}", alias), + } + } } #[cfg(test)] diff --git a/crates/jstzd/tests/octez_client_test.rs b/crates/jstzd/tests/octez_client_test.rs index fa227ee4..c14f4096 100644 --- a/crates/jstzd/tests/octez_client_test.rs +++ b/crates/jstzd/tests/octez_client_test.rs @@ -1,8 +1,20 @@ use jstzd::task::{endpoint::Endpoint, octez_client::OctezClientBuilder}; use serde_json::Value; -use std::fs::{read_to_string, remove_file}; +use std::{ + fs::{read_to_string, remove_file}, + path::Path, +}; use tempfile::{NamedTempFile, TempDir}; +fn read_file(path: &Path) -> Value { + serde_json::from_str(&read_to_string(path).expect("Unable to read file")) + .expect("Unable to parse JSON") +} + +fn first_item(json: Value) -> Value { + json.as_array().unwrap()[0].clone() +} + #[tokio::test] async fn config_init() { let temp_dir = TempDir::new().unwrap(); @@ -26,3 +38,36 @@ async fn config_init() { ); assert_eq!(actual["endpoint"], expected_endpoint.to_string()); } + +#[tokio::test] +async fn generates_keys() { + let temp_dir = TempDir::new().unwrap(); + let base_dir = temp_dir.path().to_path_buf(); + let octez_client = OctezClientBuilder::new() + .set_base_dir(base_dir.clone()) + .build() + .unwrap(); + let alias = "test_alias".to_string(); + let res = octez_client.gen_keys(&alias, None).await; + assert!(res.is_ok()); + let hashes = first_item(read_file(&base_dir.join("public_key_hashs"))); + let pub_keys = first_item(read_file(&base_dir.join("public_keys"))); + let secret_keys = first_item(read_file(&base_dir.join("secret_keys"))); + assert_eq!(hashes["name"], alias); + assert_eq!(pub_keys["name"], alias); + assert_eq!(secret_keys["name"], alias); +} + +#[tokio::test] +async fn generates_keys_throws() { + let temp_dir = TempDir::new().unwrap(); + let base_dir = temp_dir.path().to_path_buf(); + let octez_client = OctezClientBuilder::new() + .set_base_dir(base_dir.clone()) + .build() + .unwrap(); + let alias = "test_alias".to_string(); + let _ = octez_client.gen_keys(&alias, None).await; + let res = octez_client.gen_keys(&alias, None).await; + assert!(res.is_err_and(|e| e.to_string().contains("failed to generate key"))); +}