diff --git a/DockerfileRocket b/DockerfileRocket index 7dac5a2f..421f2daa 100644 --- a/DockerfileRocket +++ b/DockerfileRocket @@ -51,8 +51,8 @@ RUN cargo build --release RUN chmod +x ./docker_run.sh # Build the cairo compiler -WORKDIR /opt/app/api/cairo -RUN cargo build --release --workspace +WORKDIR /opt/app/api/cairo_compilers +RUN chmod +x ./build.sh; ./build.sh EXPOSE 8000 diff --git a/api/Dockerfile b/api/Dockerfile index ca44bfb6..a7f3f58d 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -19,12 +19,16 @@ RUN rustup install stable # Create and activate a Python virtual environment RUN python -m venv ~/cairo_venv -RUN source ~/cairo_venv/bin/activate +RUN . ~/cairo_venv/bin/activate ENV PATH="/root/cairo_venv/bin:${PATH}" # Install cairo-lang RUN pip install cairo-lang +# install Scarb +RUN curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | bash +ENV PATH="/root/.local/bin:${PATH}" + # Set the working directory WORKDIR /app @@ -38,7 +42,9 @@ COPY . . # RUN cd cairo; git checkout v1.0.0-alpha.6 # Or if you chose to copy the whole repo # RUN git submodule update --init -RUN cd cairo; cargo build --bin starknet-compile; cargo build --bin starknet-sierra-compile + +#RUN cd cairo; cargo build --bin starknet-compile; cargo build --bin starknet-sierra-compile +RUN cd cairo_compilers; chmod +x build.sh; ./build.sh RUN cargo build --release EXPOSE 8000:80 diff --git a/api/cairo_compilers/build.sh b/api/cairo_compilers/build.sh new file mode 100755 index 00000000..3be6e0db --- /dev/null +++ b/api/cairo_compilers/build.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +echo "Building cairo compilers" + +directories=$(ls -d */) + +for dir in $directories +do + echo "Building $dir" + + if [[ ! -f "$dir/Cargo.toml" ]] || [[ ! "$dir" =~ ^v[0-9]+\.[0-9]+\.[0-9]+/$ ]]; then + echo "Invalid cairo version provided $dir" + exit 1 + fi + + cd "$dir" || exit 1 + + cargo build --bin starknet-compile --release + cargo build --bin starknet-sierra-compile --release + + cd .. + + echo "Done building $dir" +done \ No newline at end of file diff --git a/api/src/handlers/cairo_version.rs b/api/src/handlers/cairo_version.rs index dc9f38a4..a662e37d 100644 --- a/api/src/handlers/cairo_version.rs +++ b/api/src/handlers/cairo_version.rs @@ -1,6 +1,6 @@ use crate::handlers::process::{do_process_command, fetch_process_result}; use crate::handlers::types::{ApiCommand, ApiCommandResult}; -use crate::utils::lib::CAIRO_DIR; +use crate::utils::lib::DEFAULT_CAIRO_DIR; use crate::worker::WorkerEngine; use rocket::State; use std::process::{Command, Stdio}; @@ -34,9 +34,11 @@ pub async fn get_cairo_version_result(process_id: String, engine: &State Result { let mut version_caller = Command::new("cargo"); - version_caller.current_dir(CAIRO_DIR); + version_caller.current_dir(DEFAULT_CAIRO_DIR); match String::from_utf8( version_caller .arg("run") @@ -48,7 +50,7 @@ pub fn do_cairo_version() -> Result { .arg("--version") .stdout(Stdio::piped()) .spawn() - .expect("Failed to execute cairo-compile") + .map_err(|e| format!("Failed to get cairo version: {:?}", e))? .wait_with_output() .map_err(|e| format!("Failed to get cairo version: {:?}", e))? .stdout, diff --git a/api/src/handlers/cairo_versions.rs b/api/src/handlers/cairo_versions.rs new file mode 100644 index 00000000..b9e421f1 --- /dev/null +++ b/api/src/handlers/cairo_versions.rs @@ -0,0 +1,29 @@ +use crate::utils::lib::CAIRO_COMPILERS_DIR; +use rocket::tokio::fs::read_dir; +use std::path::Path; +use tracing::instrument; + +#[instrument] +#[get("/cairo_versions")] +pub async fn cairo_versions() -> String { + do_cairo_versions().await.unwrap_or_else(|e| e) +} + +/// Get cairo versions +pub async fn do_cairo_versions() -> Result { + let path = Path::new(CAIRO_COMPILERS_DIR); + + let mut dir = read_dir(path).await.unwrap(); + let mut result = vec![]; + + while let Ok(Some(entry)) = dir.next_entry().await { + let entry = entry; + let path = entry.path(); + if path.is_dir() { + println!("{:?}", entry.file_name()); + result.push(entry.file_name().to_string_lossy().to_string()); + } + } + + Ok(format!("{:?}", result)) +} diff --git a/api/src/handlers/compile_casm.rs b/api/src/handlers/compile_casm.rs index 8c4161c0..980fc710 100644 --- a/api/src/handlers/compile_casm.rs +++ b/api/src/handlers/compile_casm.rs @@ -1,6 +1,6 @@ use crate::handlers::process::{do_process_command, fetch_process_result}; use crate::handlers::types::{ApiCommand, ApiCommandResult, CompileResponse}; -use crate::utils::lib::{get_file_ext, get_file_path, CAIRO_DIR, CASM_ROOT}; +use crate::utils::lib::{get_file_ext, get_file_path, CAIRO_COMPILERS_DIR, CASM_ROOT}; use crate::worker::WorkerEngine; use rocket::fs::NamedFile; use rocket::serde::json; @@ -12,21 +12,36 @@ use std::process::{Command, Stdio}; use tracing::info; use tracing::instrument; -#[instrument] -#[get("/compile-to-casm/")] -pub async fn compile_to_casm(remix_file_path: PathBuf) -> Json { +#[get("/compile-to-casm//")] +pub async fn compile_to_casm(version: String, remix_file_path: PathBuf) -> Json { info!("/compile-to-casm/{:?}", remix_file_path); - do_compile_to_casm(remix_file_path).await + do_compile_to_casm(version.clone(), remix_file_path) + .await + .unwrap_or_else(|e| { + Json(CompileResponse { + file_content: "".to_string(), + message: e, + status: "CompilationFailed".to_string(), + cairo_version: version, + }) + }) } #[instrument] -#[get("/compile-to-casm-async/")] +#[get("/compile-to-casm-async//")] pub async fn compile_to_casm_async( + version: String, remix_file_path: PathBuf, engine: &State, ) -> String { info!("/compile-to-casm-async/{:?}", remix_file_path); - do_process_command(ApiCommand::CasmCompile(remix_file_path), engine) + do_process_command( + ApiCommand::CasmCompile { + remix_file_path, + version, + }, + engine, + ) } #[instrument] @@ -34,22 +49,28 @@ pub async fn compile_to_casm_async( pub async fn compile_to_casm_result(process_id: String, engine: &State) -> String { info!("/compile-to-casm-result/{:?}", process_id); fetch_process_result(process_id, engine, |result| match result { - ApiCommandResult::CasmCompile(casm_result) => json::to_string(&casm_result).unwrap(), + ApiCommandResult::CasmCompile(casm_result) => { + json::to_string(&casm_result).unwrap_or("Failed to fetch result".to_string()) + } _ => String::from("Result not available"), }) } /// Compile source file to CASM /// -pub async fn do_compile_to_casm(remix_file_path: PathBuf) -> Json { +pub async fn do_compile_to_casm( + version: String, + remix_file_path: PathBuf, +) -> Result, String> { let remix_file_path = match remix_file_path.to_str() { Some(path) => path.to_string(), None => { - return Json(CompileResponse { + return Ok(Json(CompileResponse { file_content: "".to_string(), message: "File path not found".to_string(), status: "FileNotFound".to_string(), - }); + cairo_version: version, + })); } }; @@ -60,11 +81,12 @@ pub async fn do_compile_to_casm(remix_file_path: PathBuf) -> Json { debug!("LOG: File extension not supported"); - return Json(CompileResponse { + return Ok(Json(CompileResponse { file_content: "".to_string(), message: "File extension not supported".to_string(), status: "FileExtensionNotSupported".to_string(), - }); + cairo_version: version, + })); } } @@ -73,7 +95,19 @@ pub async fn do_compile_to_casm(remix_file_path: PathBuf) -> Json Json match file.path().to_str() { Some(path) => match fs::read_to_string(path.to_string()).await { @@ -129,13 +175,26 @@ pub async fn do_compile_to_casm(remix_file_path: PathBuf) -> Json "".to_string(), }, message: String::from_utf8(output.stderr) - .unwrap() - .replace(&file_path.to_str().unwrap().to_string(), &remix_file_path) - .replace(&casm_path.to_str().unwrap().to_string(), &casm_remix_path), + .map_err(|e| format!("Failed to read stderr: {:?}", e))? + .replace( + &file_path + .to_str() + .ok_or("Failed to parse string".to_string())? + .to_string(), + &remix_file_path, + ) + .replace( + &casm_path + .to_str() + .ok_or("Failed to parse string".to_string())? + .to_string(), + &casm_remix_path, + ), status: match output.status.code() { Some(0) => "Success".to_string(), Some(_) => "SierraCompilationFailed".to_string(), None => "UnknownError".to_string(), }, - }) + cairo_version: version, + })) } diff --git a/api/src/handlers/compile_sierra.rs b/api/src/handlers/compile_sierra.rs index fbe9d354..5728aa1d 100644 --- a/api/src/handlers/compile_sierra.rs +++ b/api/src/handlers/compile_sierra.rs @@ -1,6 +1,6 @@ use crate::handlers::process::{do_process_command, fetch_process_result}; use crate::handlers::types::{ApiCommand, ApiCommandResult, CompileResponse}; -use crate::utils::lib::{get_file_ext, get_file_path, CAIRO_DIR, SIERRA_ROOT}; +use crate::utils::lib::{get_file_ext, get_file_path, CAIRO_COMPILERS_DIR, SIERRA_ROOT}; use crate::worker::WorkerEngine; use rocket::fs::NamedFile; use rocket::serde::json; @@ -12,26 +12,38 @@ use std::process::{Command, Stdio}; use tracing::{debug, instrument}; #[instrument] -#[get("/compile-to-sierra/")] -pub async fn compile_to_sierra(remix_file_path: PathBuf) -> Json { +#[get("/compile-to-sierra//")] +pub async fn compile_to_sierra(version: String, remix_file_path: PathBuf) -> Json { info!("/compile-to-sierra"); - do_compile_to_sierra(remix_file_path) - .await - .unwrap_or(Json::from(CompileResponse { - message: "Error compiling to sierra".to_string(), - status: "error".to_string(), + + let res = do_compile_to_sierra(version.clone(), remix_file_path).await; + + match res { + Ok(res) => res, + Err(e) => Json(CompileResponse { file_content: "".to_string(), - })) + message: e, + status: "CompilationFailed".to_string(), + cairo_version: version, + }), + } } #[instrument] -#[get("/compile-to-sierra-async/")] +#[get("/compile-to-sierra-async//")] pub async fn compile_to_siera_async( + version: String, remix_file_path: PathBuf, engine: &State, ) -> String { info!("/compile-to-sierra-async"); - do_process_command(ApiCommand::SierraCompile(remix_file_path), engine) + do_process_command( + ApiCommand::SierraCompile { + version, + remix_file_path, + }, + engine, + ) } #[instrument] @@ -39,7 +51,9 @@ pub async fn compile_to_siera_async( pub async fn get_siera_compile_result(process_id: String, engine: &State) -> String { info!("/compile-to-sierra-result"); fetch_process_result(process_id, engine, |result| match result { - ApiCommandResult::SierraCompile(sierra_result) => json::to_string(&sierra_result).unwrap(), + ApiCommandResult::SierraCompile(sierra_result) => { + json::to_string(&sierra_result).unwrap_or("Failed to fetch result".to_string()) + } _ => String::from("Result not available"), }) } @@ -47,6 +61,7 @@ pub async fn get_siera_compile_result(process_id: String, engine: &State Result, String> { let remix_file_path = match remix_file_path.to_str() { @@ -56,6 +71,7 @@ pub async fn do_compile_to_sierra( file_content: "".to_string(), message: "File path not found".to_string(), status: "FileNotFound".to_string(), + cairo_version: version, })); } }; @@ -71,6 +87,7 @@ pub async fn do_compile_to_sierra( file_content: "".to_string(), message: "File extension not supported".to_string(), status: "FileExtensionNotSupported".to_string(), + cairo_version: version, })); } } @@ -80,7 +97,13 @@ pub async fn do_compile_to_sierra( let sierra_remix_path = remix_file_path.replace(&get_file_ext(&remix_file_path), "sierra"); let mut compile = Command::new("cargo"); - compile.current_dir(CAIRO_DIR); + + let path_to_cairo_compiler = Path::new(CAIRO_COMPILERS_DIR).join(&version); + if path_to_cairo_compiler.exists() { + compile.current_dir(path_to_cairo_compiler); + } else { + return Err(format!("Cairo compiler with version {} not found", version)); + } // replace .cairo with let sierra_path = Path::new(SIERRA_ROOT).join(&sierra_remix_path); @@ -116,7 +139,9 @@ pub async fn do_compile_to_sierra( debug!("LOG: ran command:{:?}", compile); - let output = result.wait_with_output().expect("Failed to wait on child"); + let output = result + .wait_with_output() + .map_err(|e| format!("Failed to wait on child: {:?}", e))?; Ok(Json(CompileResponse { file_content: match NamedFile::open(&sierra_path).await.ok() { @@ -130,10 +155,19 @@ pub async fn do_compile_to_sierra( None => "".to_string(), }, message: String::from_utf8(output.stderr) - .unwrap() - .replace(&file_path.to_str().unwrap().to_string(), &remix_file_path) + .map_err(|e| format!("Failed to read stderr: {:?}", e))? + .replace( + &file_path + .to_str() + .ok_or(format!("Formation of filepath failed"))? + .to_string(), + &remix_file_path, + ) .replace( - &sierra_path.to_str().unwrap().to_string(), + &sierra_path + .to_str() + .ok_or(format!("Formation of filepath failed"))? + .to_string(), &sierra_remix_path, ), status: match output.status.code() { @@ -141,5 +175,6 @@ pub async fn do_compile_to_sierra( Some(_) => "CompilationFailed".to_string(), None => "UnknownError".to_string(), }, + cairo_version: version, })) } diff --git a/api/src/handlers/mod.rs b/api/src/handlers/mod.rs index 0b8f788a..5f4b76f0 100644 --- a/api/src/handlers/mod.rs +++ b/api/src/handlers/mod.rs @@ -1,4 +1,5 @@ pub mod cairo_version; +pub mod cairo_versions; pub mod compile_casm; pub mod compile_sierra; pub mod process; @@ -12,8 +13,8 @@ use crate::handlers::compile_sierra::do_compile_to_sierra; use crate::handlers::scarb_compile::do_scarb_compile; use crate::handlers::types::{ApiCommand, ApiCommandResult, FileContentMap}; use rocket::serde::json::Json; -use tracing::info; use std::path::Path; +use tracing::info; use tracing::instrument; #[instrument] @@ -36,39 +37,50 @@ pub async fn dispatch_command(command: ApiCommand) -> Result Ok(ApiCommandResult::CairoVersion(result)), Err(e) => Err(e), }, - ApiCommand::ScarbCompile(remix_file_path) => { + ApiCommand::ScarbCompile { remix_file_path } => { match do_scarb_compile(remix_file_path).await { Ok(result) => Ok(ApiCommandResult::ScarbCompile(result.into_inner())), Err(e) => Err(e), } } - ApiCommand::SierraCompile(remix_file_path) => { - match do_compile_to_sierra(remix_file_path).await { - Ok(compile_response) => Ok(ApiCommandResult::SierraCompile( - compile_response.into_inner(), - )), - Err(e) => Err(e), - } - } - ApiCommand::CasmCompile(remix_file_path) => { - match do_compile_to_casm(remix_file_path).await { - Json(compile_response) => Ok(ApiCommandResult::CasmCompile(compile_response)), - } - } + ApiCommand::SierraCompile { + remix_file_path, + version, + } => match do_compile_to_sierra(version, remix_file_path).await { + Ok(compile_response) => Ok(ApiCommandResult::SierraCompile( + compile_response.into_inner(), + )), + Err(e) => Err(e), + }, + ApiCommand::CasmCompile { + remix_file_path, + version, + } => match do_compile_to_casm(version, remix_file_path).await { + Ok(Json(compile_response)) => Ok(ApiCommandResult::CasmCompile(compile_response)), + Err(e) => Err(e), + }, ApiCommand::Shutdown => Ok(ApiCommandResult::Shutdown), } } -fn get_files_recursive(base_path: &Path) -> Vec { +fn get_files_recursive(base_path: &Path) -> Result, String> { let mut file_content_map_array: Vec = Vec::new(); if base_path.is_dir() { - for entry in base_path.read_dir().unwrap().flatten() { + for entry in base_path + .read_dir() + .map_err(|e| format!("Error while reading dir {:?}", e))? + .flatten() + { let path = entry.path(); if path.is_dir() { - file_content_map_array.extend(get_files_recursive(&path)); + file_content_map_array.extend(get_files_recursive(&path)?); } else if let Ok(content) = std::fs::read_to_string(&path) { - let file_name = path.file_name().unwrap().to_string_lossy().to_string(); + let file_name = path + .file_name() + .ok_or(format!("Error while reading file name"))? + .to_string_lossy() + .to_string(); let file_content = content; let file_content_map = FileContentMap { file_name, @@ -79,5 +91,5 @@ fn get_files_recursive(base_path: &Path) -> Vec { } } - file_content_map_array + Ok(file_content_map_array) } diff --git a/api/src/handlers/save_code.rs b/api/src/handlers/save_code.rs index 9c3fee38..a4a73f77 100644 --- a/api/src/handlers/save_code.rs +++ b/api/src/handlers/save_code.rs @@ -2,8 +2,8 @@ use crate::utils::lib::get_file_path; use rocket::data::ToByteUnit; use rocket::tokio::fs; use rocket::Data; -use tracing::info; use std::path::PathBuf; +use tracing::info; #[post("/save_code/", data = "")] pub async fn save_code(file: Data<'_>, remix_file_path: PathBuf) -> String { diff --git a/api/src/handlers/scarb_compile.rs b/api/src/handlers/scarb_compile.rs index f395b2f0..743d9950 100644 --- a/api/src/handlers/scarb_compile.rs +++ b/api/src/handlers/scarb_compile.rs @@ -21,7 +21,7 @@ pub async fn scarb_compile(remix_file_path: PathBuf) -> Json")] pub async fn scarb_compile_async(remix_file_path: PathBuf, engine: &State) -> String { info!("/compile-scarb-async/{:?}", remix_file_path); - do_process_command(ApiCommand::ScarbCompile(remix_file_path), engine) + do_process_command(ApiCommand::ScarbCompile { remix_file_path }, engine) } #[instrument] @@ -64,15 +64,17 @@ pub async fn do_scarb_compile( debug!("LOG: ran command:{:?}", compile); - let output = result.wait_with_output().expect("Failed to wait on child"); + let output = result + .wait_with_output() + .map_err(|e| format!("Failed to wait: {:?}", e))?; Ok(Json(ScarbCompileResponse { - file_content_map_array: get_files_recursive(&file_path.join("target/dev")), + file_content_map_array: get_files_recursive(&file_path.join("target/dev"))?, message: String::from_utf8(output.stdout) - .unwrap() + .map_err(|e| format!("Failed to read stdout: {:?}", e))? .replace(&file_path.to_str().unwrap().to_string(), &remix_file_path) + &String::from_utf8(output.stderr) - .unwrap() + .map_err(|e| format!("Failed to read stderr: {:?}", e))? .replace(&file_path.to_str().unwrap().to_string(), &remix_file_path), status: match output.status.code() { Some(0) => "Success".to_string(), diff --git a/api/src/handlers/types.rs b/api/src/handlers/types.rs index 476a4a4a..223e58fa 100644 --- a/api/src/handlers/types.rs +++ b/api/src/handlers/types.rs @@ -7,6 +7,7 @@ pub struct CompileResponse { pub status: String, pub message: String, pub file_content: String, + pub cairo_version: String, } #[derive(Debug, Serialize, Deserialize)] @@ -25,9 +26,17 @@ pub struct ScarbCompileResponse { #[derive(Debug)] pub enum ApiCommand { CairoVersion, - SierraCompile(PathBuf), - CasmCompile(PathBuf), - ScarbCompile(PathBuf), + SierraCompile { + remix_file_path: PathBuf, + version: String, + }, + CasmCompile { + remix_file_path: PathBuf, + version: String, + }, + ScarbCompile { + remix_file_path: PathBuf, + }, #[allow(dead_code)] Shutdown, } diff --git a/api/src/main.rs b/api/src/main.rs index 59dffad3..d391dec4 100644 --- a/api/src/main.rs +++ b/api/src/main.rs @@ -11,6 +11,7 @@ use crate::cors::CORS; use crate::tracing_log::init_logger; use crate::worker::WorkerEngine; use handlers::cairo_version::{cairo_version, cairo_version_async, get_cairo_version_result}; +use handlers::cairo_versions::cairo_versions; use handlers::compile_casm::{compile_to_casm, compile_to_casm_async, compile_to_casm_result}; use handlers::compile_sierra::{ compile_to_siera_async, compile_to_sierra, get_siera_compile_result, @@ -28,18 +29,12 @@ async fn rocket() -> _ { } let number_of_workers = match std::env::var("WORKER_THREADS") { - Ok(v) => match v.parse::() { - Ok(v) => v, - Err(_) => 2u32, - }, + Ok(v) => v.parse::().unwrap_or(2u32), Err(_) => 2u32, }; let queue_size = match std::env::var("QUEUE_SIZE") { - Ok(v) => match v.parse::() { - Ok(v) => v, - Err(_) => 1_000, - }, + Ok(v) => v.parse::().unwrap_or(1_000), Err(_) => 1_000, }; @@ -66,6 +61,7 @@ async fn rocket() -> _ { scarb_compile_async, get_scarb_compile_result, save_code, + cairo_versions, cairo_version, cairo_version_async, get_cairo_version_result, diff --git a/api/src/tracing_log.rs b/api/src/tracing_log.rs index 4f592f9c..58eac161 100644 --- a/api/src/tracing_log.rs +++ b/api/src/tracing_log.rs @@ -1,4 +1,3 @@ - use tracing_appender::rolling; use tracing_subscriber::fmt::writer::MakeWriterExt; @@ -7,10 +6,8 @@ use tracing_subscriber::{prelude::*, EnvFilter}; use tracing_subscriber::field::MakeExt; - - +use rocket::yansi::Paint; use tracing_subscriber::Layer; -use yansi::Paint; pub enum LogType { Formatted, @@ -81,14 +78,14 @@ pub enum LogLevel { impl From<&str> for LogLevel { fn from(s: &str) -> Self { - return match &*s.to_ascii_lowercase() { + match &*s.to_ascii_lowercase() { "critical" => LogLevel::Critical, "support" => LogLevel::Support, "normal" => LogLevel::Normal, "debug" => LogLevel::Debug, "off" => LogLevel::Off, _ => panic!("a log level (off, debug, normal, support, critical)"), - }; + } } } diff --git a/api/src/utils/lib.rs b/api/src/utils/lib.rs index 63b763cf..0364296d 100644 --- a/api/src/utils/lib.rs +++ b/api/src/utils/lib.rs @@ -4,10 +4,18 @@ pub const CAIRO_ROOT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/", "upload/te pub const SIERRA_ROOT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/", "sierra/temp/"); pub const CASM_ROOT: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/", "casm/temp/"); -pub const CAIRO_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/", "cairo/"); +pub const DEFAULT_CAIRO_DIR: &str = concat!( + env!("CARGO_MANIFEST_DIR"), + "/", + "cairo_compilers/", + "v2.2.0" +); +pub const CAIRO_COMPILERS_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/", "cairo_compilers/"); #[allow(dead_code)] pub const TEMP_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/", "temp/"); +pub const DEFAULT_CAIRO_VERSION: &str = "v2.2.0"; + pub fn get_file_ext(file_path: &str) -> String { match file_path.split('.').last() { Some(ext) => ext.to_string(), diff --git a/plugin/src/App.tsx b/plugin/src/App.tsx index da6ebcc7..b01865ae 100644 --- a/plugin/src/App.tsx +++ b/plugin/src/App.tsx @@ -52,8 +52,6 @@ const App: React.FC = () => { let fileContent: string = file?.content ?? '' - console.log('kljkljl', file?.fileName) - if (file != null && file.fileName === 'Scarb.toml') { fileContent = fileContent.concat('\ncasm = true') } diff --git a/plugin/src/contexts/CairoVersion.ts b/plugin/src/contexts/CairoVersion.ts new file mode 100644 index 00000000..30871ca3 --- /dev/null +++ b/plugin/src/contexts/CairoVersion.ts @@ -0,0 +1,9 @@ +import type React from 'react' +import { createContext } from 'react' + +const CairoVersion = createContext({ + version: '0.0.0' as string, + setVersion: ((_: string) => {}) as React.Dispatch>, +}) + +export default CairoVersion diff --git a/plugin/src/features/CairoVersion/index.tsx b/plugin/src/features/CairoVersion/index.tsx index 247dd5dc..fbaf1f2b 100644 --- a/plugin/src/features/CairoVersion/index.tsx +++ b/plugin/src/features/CairoVersion/index.tsx @@ -1,82 +1,96 @@ -import * as D from '../../ui_components/Dropdown' -import React, { useContext, useEffect, useState } from 'react' -import { apiUrl } from '../../utils/network' -import { RemixClientContext } from '../../contexts/RemixClientContext' -// import { BsChevronDown } from 'react-icons/bs' -import Nethermind from '../../components/NM' -import './style.css' -import {asyncFetch} from "../../utils/async_fetch"; +import * as D from '../../ui_components/Dropdown'; +import React, {useContext, useEffect, useState} from 'react'; +import { apiUrl } from '../../utils/network'; +import { RemixClientContext } from '../../contexts/RemixClientContext'; +import CairoVersionContext from '../../contexts/CairoVersion'; +import { BsChevronDown } from 'react-icons/bs'; +import Nethermind from '../../components/NM'; +import './style.css'; const CairoVersion: React.FC = () => { - const [cairoVersion, setCairoVersion] = useState('cairo-compile 2.2.0') - const remixClient = useContext(RemixClientContext) + const { version: cairoVersion, setVersion: setCairoVersion } = useContext(CairoVersionContext); + const remixClient = useContext(RemixClientContext); - const [versions] = useState([ - 'cairo-compile 2.2.0' - ]) - const pluginVersion = import.meta.env.VITE_VERSION !== undefined ? `v${import.meta.env.VITE_VERSION}` : 'v0.2.0' + const pluginVersion = import.meta.env.VITE_VERSION !== undefined ? `v${import.meta.env.VITE_VERSION}` : 'v0.2.0'; + + // Hard-coded versions for the example + const [getVersions, setVersions] = useState([]); useEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-misused-promises - const id = setTimeout(async () => { + const fetchCairoVersions = async () => { try { if (apiUrl !== undefined) { - const version = await asyncFetch('cairo_version_async', 'cairo_version_result') - setCairoVersion(version) + const response = await fetch( + `${apiUrl}/cairo_versions`, + { + method: 'GET', + headers: { + 'Content-Type': 'application/octet-stream' + }, + redirect: 'follow' + } + ); + const versions = JSON.parse(await response.text()); + setVersions(versions); } } catch (e) { - await remixClient.call( - 'notification' as any, - 'toast', - '🔴 Failed to fetch cairo version from the compilation server' - ) - console.error(e) - await remixClient.terminal.log(`🔴 Failed to fetch cairo version from the compilation server ${e}` as any) + await remixClient.call('notification' as any, 'toast', '🔴 Failed to fetch cairo versions from the compilation server'); + console.error(e); + await remixClient.terminal.log(`🔴 Failed to fetch cairo versions from the compilation server ${e}` as any); + } + } + + setTimeout(async () => { + await fetchCairoVersions(); + + if (getVersions.length > 0) { + setCairoVersion(getVersions[0]) } - }, 100) - return () => { - clearInterval(id) + }, 10000); + }, [remixClient]); + + useEffect(() => { + if (getVersions.length > 0) { + setCairoVersion(getVersions[0]) } - }, [remixClient]) + }, [remixClient, getVersions]); return ( -
-
- - - - - - - {versions.map((v, i) => { - return ( - { - setCairoVersion(v) - }} - > - {v} - - ) - })} - - - -
-
- - +
+
+ + + + + + + {getVersions.map((v, i) => ( + { + setCairoVersion(v); + }} + > + {v} + + ))} + + + +
+
+ + +
-
- ) + ); } -export default CairoVersion +export default CairoVersion; diff --git a/plugin/src/features/Compilation/index.tsx b/plugin/src/features/Compilation/index.tsx index bce7c3f2..c0228b91 100644 --- a/plugin/src/features/Compilation/index.tsx +++ b/plugin/src/features/Compilation/index.tsx @@ -21,6 +21,7 @@ import * as D from '../../ui_components/Dropdown' import { BsChevronDown } from 'react-icons/bs' import { type Contract } from '../../types/contracts' import { asyncFetch } from '../../utils/async_fetch' +import CairoVersionContext from "../../contexts/CairoVersion"; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface CompilationProps { @@ -29,6 +30,7 @@ interface CompilationProps { const Compilation: React.FC = ({ setAccordian }) => { const remixClient = useContext(RemixClientContext) + const { version: cairoVersion, setVersion: setCairoVersion } = useContext(CairoVersionContext); const { contracts, selectedContract, setContracts, setSelectedContract } = useContext( CompiledContractsContext @@ -361,7 +363,7 @@ const Compilation: React.FC = ({ setAccordian }) => { setStatus('Compiling to sierra...') const compileToSierraResponse = await asyncFetch( - `compile-to-sierra-async/${hashDir}/${currentFilePath}`, + `compile-to-sierra-async/${cairoVersion}/${hashDir}/${currentFilePath}`, 'compile-to-sierra-result' ) @@ -427,7 +429,7 @@ const Compilation: React.FC = ({ setAccordian }) => { setStatus('Compiling to casm...') const compileToCasmResponse = await asyncFetch( - `compile-to-casm-async/${hashDir}/${currentFilePath.replaceAll(getFileExtension(currentFilePath), 'sierra')}`, + `compile-to-casm-async/${cairoVersion}/${hashDir}/${currentFilePath.replaceAll(getFileExtension(currentFilePath), 'sierra')}`, 'compile-to-casm-result' ) diff --git a/plugin/src/features/Plugin/index.tsx b/plugin/src/features/Plugin/index.tsx index 8793c94e..1ce4c057 100644 --- a/plugin/src/features/Plugin/index.tsx +++ b/plugin/src/features/Plugin/index.tsx @@ -39,7 +39,7 @@ import BackgroundNotices from '../../components/BackgroundNotices' import ExplorerSelector, { useCurrentExplorer } from '../../components/ExplorerSelector' - +import CairoVersionContext from '../../contexts/CairoVersion' export type AccordianTabs = | 'compile' | 'deploy' @@ -108,6 +108,8 @@ const Plugin: React.FC = () => { const [currentAccordian, setCurrentAccordian] = useState('compile') + const [cairoVersion, setCairoVersion] = useState('version is loading...') + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type const handleTabView = (clicked: AccordianTabs) => { if (currentAccordian === clicked) { @@ -155,171 +157,178 @@ const Plugin: React.FC = () => { setAccount }} > - -
- - + - - - { - handleTabView('compile') - }} - > - -

Compile

- -
-
- - - -
-
- - - { - handleTabView('deploy') +
+ + + - -

Deploy

- -
- - - - - - - { - handleTabView('interaction') + + { + handleTabView('compile') + }} + > + +

Compile

+ +
+
+ + + +
+
+ - + { + handleTabView('deploy') + }} + > + +

Deploy

+ +
+
+ + + + + + { + handleTabView('interaction') + }} + > + +

Interact

+ +
+
+ + + +
+
+ + { + handleTabView('transactions') + }} > -

Interact

- - -
- - - -
- - - { - handleTabView('transactions') + +

Transactions

+ +
+
+ + + +
+
+
+ +
+
+
+ - -

Transactions

- -
- - - - - - -
- -
-
-
- - - -
-
+ + +
+
+