diff --git a/Cargo.lock b/Cargo.lock index 8632a1173..f3f072056 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1654,6 +1654,7 @@ dependencies = [ "jstz_proto", "nix 0.20.2", "rand 0.8.5", + "reqwest", "rustyline", "serde", "serde_json", @@ -1666,6 +1667,7 @@ dependencies = [ "tezos-smart-rollup-mock", "tezos_crypto_rs", "tiny-bip39", + "tokio", ] [[package]] @@ -3293,13 +3295,26 @@ dependencies = [ "bytes", "libc", "mio", + "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2 0.5.5", + "tokio-macros", "windows-sys", ] +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "tokio-native-tls" version = "0.3.1" diff --git a/jstz_cli/Cargo.toml b/jstz_cli/Cargo.toml index baa016684..0afd1f0c4 100644 --- a/jstz_cli/Cargo.toml +++ b/jstz_cli/Cargo.toml @@ -37,6 +37,8 @@ sha2 = "0.9" rand = "0.8" tiny-bip39 = "1.0.0" bincode = "1.3.3" +reqwest = { version = "0.11.22", features = ["json"] } +tokio = { version = "1.33.0", features = ["full"] } [[bin]] name = "jstz" diff --git a/jstz_cli/src/config.rs b/jstz_cli/src/config.rs index 891b38bfe..47fee8d64 100644 --- a/jstz_cli/src/config.rs +++ b/jstz_cli/src/config.rs @@ -71,6 +71,8 @@ pub struct Config { pub octez_node_port: u16, /// The port of the octez RPC node pub octez_node_rpc_port: u16, + /// The port of the jstz node + pub jstz_node_port: u16, /// Sandbox config (None if sandbox is not running) pub sandbox: Option, /// List of accounts @@ -114,6 +116,7 @@ impl Config { octez_path: PathBuf::from_str(".").unwrap(), octez_node_port: 18731, octez_node_rpc_port: 18730, + jstz_node_port: 8933, sandbox: None, accounts: AccountConfig::default(), } diff --git a/jstz_cli/src/deploy.rs b/jstz_cli/src/deploy.rs index 54c238604..f99571380 100644 --- a/jstz_cli/src/deploy.rs +++ b/jstz_cli/src/deploy.rs @@ -3,11 +3,12 @@ use jstz_proto::operation::{Content, DeployContract, Operation, SignedOperation} use crate::{ config::Config, + jstz::JstzClient, octez::OctezClient, utils::{from_file_or_id, piped_input}, }; -pub fn exec( +pub async fn exec( self_address: Option, contract_code: Option, balance: u64, @@ -39,6 +40,8 @@ pub fn exec( op, ); + let hash = signed_op.hash(); + println!( "Signed operation: {}", serde_json::to_string_pretty(&serde_json::to_value(&signed_op)?)? @@ -51,6 +54,13 @@ pub fn exec( bincode::serialize(&signed_op)?, )?; + let receipt = JstzClient::new(cfg) + .wait_for_operation_receipt(&hash) + .await?; + + println!("Receipt: {:?}", receipt); + cfg.save()?; + Ok(()) } diff --git a/jstz_cli/src/jstz.rs b/jstz_cli/src/jstz.rs new file mode 100644 index 000000000..49b3fd082 --- /dev/null +++ b/jstz_cli/src/jstz.rs @@ -0,0 +1,60 @@ +use std::time::Duration; + +use anyhow::Result; +use jstz_proto::{operation::OperationHash, receipt::Receipt}; +use tokio::time::sleep; + +use crate::config::Config; + +pub struct JstzClient { + endpoint: String, + client: reqwest::Client, +} + +impl JstzClient { + pub fn new(cfg: &Config) -> Self { + Self { + endpoint: format!("http://127.0.0.1:{}", cfg.jstz_node_port), + client: reqwest::Client::new(), + } + } + + pub async fn get_operation_receipt( + &self, + hash: &OperationHash, + ) -> Result> { + let response = self + .get(&format!( + "{}/operations/{}/receipt", + self.endpoint, + hash.to_string() + )) + .await?; + + if response.status().is_success() { + let receipt = response.json::().await?; + + Ok(Some(receipt)) + } else { + Ok(None) + } + } + + pub async fn wait_for_operation_receipt( + &self, + hash: &OperationHash, + ) -> Result { + loop { + if let Some(receipt) = self.get_operation_receipt(hash).await? { + return Ok(receipt); + } + + // tokio sleep + sleep(Duration::from_millis(100)).await; + } + } + + async fn get(&self, url: &str) -> Result { + Ok(self.client.get(url).send().await?) + } +} diff --git a/jstz_cli/src/main.rs b/jstz_cli/src/main.rs index 1aecb3bd8..2d2051e5a 100644 --- a/jstz_cli/src/main.rs +++ b/jstz_cli/src/main.rs @@ -1,15 +1,17 @@ use anyhow::Result; use clap::Parser; +use tokio; mod account; mod bridge; mod config; mod deploy; +mod jstz; mod octez; mod repl; mod run; mod sandbox; -pub(crate) mod utils; +mod utils; use config::Config; @@ -60,7 +62,7 @@ enum Command { }, } -fn exec(command: Command, cfg: &mut Config) -> Result<()> { +async fn exec(command: Command, cfg: &mut Config) -> Result<()> { match command { Command::Sandbox(sandbox_command) => sandbox::exec(cfg, sandbox_command), Command::Bridge(bridge_command) => bridge::exec(bridge_command, cfg), @@ -69,21 +71,22 @@ fn exec(command: Command, cfg: &mut Config) -> Result<()> { self_address, function_code, balance, - } => deploy::exec(self_address, function_code, balance, cfg), + } => deploy::exec(self_address, function_code, balance, cfg).await, Command::Run { url, referrer, http_method, json_data, - } => run::exec(cfg, referrer, url, http_method, json_data), + } => run::exec(cfg, referrer, url, http_method, json_data).await, Command::Repl { self_address } => repl::exec(self_address, cfg), } } -fn main() -> Result<()> { +#[tokio::main] +async fn main() -> Result<()> { let command = Command::parse(); let mut cfg = Config::load()?; - exec(command, &mut cfg) + exec(command, &mut cfg).await } diff --git a/jstz_cli/src/run.rs b/jstz_cli/src/run.rs index c1e1afe8a..d9f49e010 100644 --- a/jstz_cli/src/run.rs +++ b/jstz_cli/src/run.rs @@ -6,11 +6,12 @@ use jstz_proto::operation::{Content, Operation, RunContract, SignedOperation}; use crate::{ config::Config, + jstz::JstzClient, octez::OctezClient, utils::{from_file_or_id, piped_input}, }; -pub fn exec( +pub async fn exec( cfg: &mut Config, referrer: Option, url: String, @@ -51,6 +52,8 @@ pub fn exec( op, ); + let hash = signed_op.hash(); + println!( "Signed operation: {}", serde_json::to_string_pretty(&serde_json::to_value(&signed_op)?)? @@ -63,6 +66,13 @@ pub fn exec( bincode::serialize(&signed_op)?, )?; + let receipt = JstzClient::new(cfg) + .wait_for_operation_receipt(&hash) + .await?; + + println!("Receipt: {:?}", receipt); + cfg.save()?; + Ok(()) }