diff --git a/crates/jstz_cli/src/bridge/deposit.rs b/crates/jstz_cli/src/bridge/deposit.rs index d7a2bf2f4..3c7f1bd6f 100644 --- a/crates/jstz_cli/src/bridge/deposit.rs +++ b/crates/jstz_cli/src/bridge/deposit.rs @@ -3,7 +3,7 @@ use log::{debug, info}; use crate::{ config::{Config, NetworkName}, error::{bail_user_error, Result}, - sandbox::SANDBOX_BOOTSTRAP_ACCOUNTS, + sandbox::{JSTZD_SERVER_BASE_URL, SANDBOX_BOOTSTRAP_ACCOUNTS}, term::styles, utils::{using_jstzd, AddressOrAlias}, }; @@ -43,20 +43,38 @@ pub async fn exec( let pkh = to_pkh.to_base58(); debug!("resolved `to` -> {}", &pkh); - let contract = match using_jstzd() || cfg.sandbox().is_ok_and(|c| c.container) { - // Since jstz contracts are loaded as bootstrap contracts in jstzd, - // octez-client does not recognise them by alias, but addresses - // remain constant for bootstrap contracts, so we can use the KT1 address here - true => NATIVE_BRIDGE_ADDRESS, - _ => "jstz_native_bridge", - }; - // Execute the octez-client command - if cfg - .octez_client(&network)? - .call_contract(&from, contract, "deposit", &format!("\"{}\"", &pkh), amount) - .is_err() - { - bail_user_error!("Failed to deposit XTZ. Please check whether the addresses and network are correct."); + if cfg.sandbox().is_ok_and(|c| c.container) { + let client = reqwest::Client::new(); + let res = client + .post(format!("{JSTZD_SERVER_BASE_URL}/contract_call")) + .json(&serde_json::json!({ + "from": from, + "contract": NATIVE_BRIDGE_ADDRESS, + "amount": amount, + "entrypoint": "deposit", + "arg": format!("\"{pkh}\"") + })) + .send() + .await?; + if !res.status().is_success() { + bail_user_error!("Failed to deposit XTZ. Please check whether the addresses and network are correct."); + } + } else { + let contract = match using_jstzd() { + // Since jstz contracts are loaded as bootstrap contracts in jstzd, + // octez-client does not recognise them by alias, but addresses + // remain constant for bootstrap contracts, so we can use the KT1 address here + true => NATIVE_BRIDGE_ADDRESS, + _ => "jstz_native_bridge", + }; + // Execute the octez-client command + if cfg + .octez_client(&network)? + .call_contract(&from, contract, "deposit", &format!("\"{}\"", &pkh), amount) + .is_err() + { + bail_user_error!("Failed to deposit XTZ. Please check whether the addresses and network are correct."); + } } info!( diff --git a/crates/jstz_cli/src/config.rs b/crates/jstz_cli/src/config.rs index 09683eb74..658ce0c77 100644 --- a/crates/jstz_cli/src/config.rs +++ b/crates/jstz_cli/src/config.rs @@ -16,14 +16,14 @@ use crate::{ error::{bail, user_error, Result}, jstz::JstzClient, sandbox::{ - SANDBOX_JSTZ_NODE_PORT, SANDBOX_LOCAL_HOST_ADDR, SANDBOX_OCTEZ_NODE_RPC_PORT, + JSTZD_SERVER_BASE_URL, SANDBOX_JSTZ_NODE_PORT, SANDBOX_LOCAL_HOST_ADDR, + SANDBOX_OCTEZ_NODE_RPC_PORT, }, utils::{using_jstzd, AddressOrAlias}, }; // hardcoding it here instead of importing from jstzd simply to avoid adding jstzd // as a new depedency of jstz_cli just for this so that build time remains the same -const JSTZD_SERVER_BASE_URL: &str = "http://127.0.0.1:54321"; pub fn jstz_home_dir() -> PathBuf { if let Ok(value) = env::var("JSTZ_HOME") { @@ -539,16 +539,27 @@ impl Config { jstz_node_endpoint: jstzd_config.jstz_node.endpoint.clone(), }) } - None => Ok(Network { - octez_node_rpc_endpoint: format!( - "http://{}:{}", - SANDBOX_LOCAL_HOST_ADDR, SANDBOX_OCTEZ_NODE_RPC_PORT - ), - jstz_node_endpoint: format!( - "http://{}:{}", - SANDBOX_LOCAL_HOST_ADDR, SANDBOX_JSTZ_NODE_PORT, - ), - }), + None => { + // Since for some reason docker does not forward 127.0.0.1 to containers + // (but [::1] works,) we need to use localhost here, assuming that users' + // localhost gets resolved to the working IP address. This only applies + // when the sandbox container is in use. Once the old sandbox is removed, + // we won't need this match. + let addr = match self.sandbox().is_ok_and(|c| c.container) { + true => "localhost", + _ => SANDBOX_LOCAL_HOST_ADDR, + }; + Ok(Network { + octez_node_rpc_endpoint: format!( + "http://{}:{}", + addr, SANDBOX_OCTEZ_NODE_RPC_PORT + ), + jstz_node_endpoint: format!( + "http://{}:{}", + addr, SANDBOX_JSTZ_NODE_PORT, + ), + }) + } }, } } @@ -621,6 +632,25 @@ mod tests { ) } + #[test] + fn lookup_network_dev_sandbox_container() { + let mut config = Config::default(); + config.sandbox.replace(SandboxConfig { + octez_client_dir: PathBuf::new(), + octez_node_dir: PathBuf::new(), + octez_rollup_node_dir: PathBuf::new(), + pid: 0, + container: true, + }); + assert_eq!( + config.lookup_network(&NetworkName::Dev).unwrap(), + Network { + octez_node_rpc_endpoint: "http://localhost:18730".to_owned(), + jstz_node_endpoint: "http://localhost:8933".to_owned() + } + ) + } + #[test] fn lookup_network_custom() { let dummy_network = Network { diff --git a/crates/jstz_cli/src/sandbox/consts.rs b/crates/jstz_cli/src/sandbox/consts.rs index 57855a388..bb9cb9dc0 100644 --- a/crates/jstz_cli/src/sandbox/consts.rs +++ b/crates/jstz_cli/src/sandbox/consts.rs @@ -1,6 +1,7 @@ use crate::sandbox::daemon::SandboxBootstrapAccount; pub const SANDBOX_LOCAL_HOST_ADDR: &str = "127.0.0.1"; +pub const JSTZD_SERVER_BASE_URL: &str = "http://localhost:54321"; pub const SANDBOX_OCTEZ_NODE_PORT: u16 = 18731; pub const SANDBOX_OCTEZ_NODE_RPC_PORT: u16 = 18730; pub const SANDBOX_JSTZ_NODE_PORT: u16 = 8933; diff --git a/crates/jstz_cli/src/sandbox/container.rs b/crates/jstz_cli/src/sandbox/container.rs index 5a0d88b89..c07efaa68 100644 --- a/crates/jstz_cli/src/sandbox/container.rs +++ b/crates/jstz_cli/src/sandbox/container.rs @@ -55,7 +55,11 @@ pub(crate) async fn start_container( container_name, image, mounts, - Some(vec![SANDBOX_OCTEZ_NODE_RPC_PORT, SANDBOX_JSTZ_NODE_PORT]), + Some(vec![ + SANDBOX_OCTEZ_NODE_RPC_PORT, + SANDBOX_JSTZ_NODE_PORT, + 54321, + ]), Some(vec!["run".to_owned(), JSTZD_CONFIG_PATH.to_owned()]), ) .await diff --git a/crates/jstzd/src/task/jstzd.rs b/crates/jstzd/src/task/jstzd.rs index fa6e6a622..011d7566d 100644 --- a/crates/jstzd/src/task/jstzd.rs +++ b/crates/jstzd/src/task/jstzd.rs @@ -16,9 +16,9 @@ use anyhow::{bail, Context, Result}; use async_dropper_simple::{AsyncDrop, AsyncDropper}; use async_trait::async_trait; use axum::{ - extract::{Path, State}, + extract::{Json, Path, State}, response::IntoResponse, - routing::{get, put}, + routing::{get, post, put}, Router, }; use indicatif::{ProgressBar, ProgressStyle}; @@ -32,7 +32,7 @@ use octez::r#async::{ rollup::OctezRollupConfig, }; use prettytable::{format::consts::FORMAT_DEFAULT, Cell, Row, Table}; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use std::io::{stdout, Write}; use std::sync::Arc; use tokio::{ @@ -351,6 +351,7 @@ impl JstzdServer { .route("/shutdown", put(shutdown_handler)) .route("/config/:config_type", get(config_handler)) .route("/config/", get(all_config_handler)) + .route("/contract_call", post(call_contract_handler)) .with_state(self.inner.state.clone()); let listener = TcpListener::bind(("0.0.0.0", self.port)).await?; @@ -563,6 +564,37 @@ async fn config_handler( } } +#[derive(Deserialize)] +struct TransferRequest { + from: String, + contract: String, + amount: f64, + entrypoint: String, + arg: String, +} + +async fn call_contract_handler( + state: State>, + Json(payload): Json, +) -> http::StatusCode { + let lock = state.read().await; + let c = lock.jstzd_config.as_ref().unwrap().octez_client_config(); + match OctezClient::new(c.clone()) + .call_contract( + &payload.from, + &payload.contract, + payload.amount, + &payload.entrypoint, + &payload.arg, + Some(100f64), + ) + .await + { + Ok(_) => http::StatusCode::OK, + _ => http::StatusCode::BAD_REQUEST, + } +} + #[cfg(test)] mod tests { use indicatif::ProgressBar;