diff --git a/VERSION b/VERSION index c946ee6..1180819 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.6 +0.1.7 diff --git a/chart/keiko/Chart.yaml b/chart/keiko/Chart.yaml index 9d80455..7daab74 100644 --- a/chart/keiko/Chart.yaml +++ b/chart/keiko/Chart.yaml @@ -21,4 +21,4 @@ version: 0.1.0 # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "0.1.6" +appVersion: "0.1.7" diff --git a/server/api/src/handlers/keiko/manifest.rs b/server/api/src/handlers/keiko/manifest.rs index 8a010ab..ed3f616 100644 --- a/server/api/src/handlers/keiko/manifest.rs +++ b/server/api/src/handlers/keiko/manifest.rs @@ -7,14 +7,14 @@ use crate::server_state::ServerState; use std::fs; use std::io::ErrorKind; -pub async fn store_manifest(Path(app_name): Path, Extension(server_state): Extension, Json(manifest): Json, ) -> impl IntoResponse { - let path = &server_state.manifest_directory_path; +pub async fn store_manifest(Path(app_name): Path, Extension(server_state): Extension, Json(manifest): Json) -> impl IntoResponse { + let path = &server_state.manifest_base_dir; if !std::path::Path::new(path).exists() { if let Err(_) = fs::create_dir_all(path) { - return (StatusCode::INTERNAL_SERVER_ERROR, "Server Error") + return (StatusCode::INTERNAL_SERVER_ERROR, "Server Error"); } } - let path = format!("{}/{}.json", &server_state.manifest_directory_path, app_name); + let path = format!("{}/{}.json", &server_state.manifest_base_dir, app_name); match fs::metadata(&path) { Ok(_) => (StatusCode::IM_USED, "Already uploaded"), Err(ref e) if e.kind() == ErrorKind::NotFound => { @@ -23,14 +23,13 @@ pub async fn store_manifest(Path(app_name): Path, Extension(server_state Ok(_) => (StatusCode::CREATED, "Stored manifest"), Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Server error") } - - }, + } Err(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Server error"), } } pub async fn get_manifest(Path(app_name): Path, Extension(server_state): Extension) -> impl IntoResponse { - let path = format!("{}/{}.json", &server_state.manifest_directory_path, app_name); + let path = format!("{}/{}.json", &server_state.manifest_base_dir, app_name); match fs::read_to_string(&path) { Ok(content) => (StatusCode::OK, content), Err(ref e) if e.kind() == ErrorKind::NotFound => (StatusCode::NOT_FOUND, "Not Found".into()), diff --git a/server/api/src/server_state.rs b/server/api/src/server_state.rs index 46fbd70..4e73ba4 100644 --- a/server/api/src/server_state.rs +++ b/server/api/src/server_state.rs @@ -5,6 +5,6 @@ use url::Url; pub struct ServerState { pub json_rpc_client: HttpClient, pub rpc_url: Url, - pub manifest_directory_path: String, + pub manifest_base_dir: String, pub torii_url: Url, } diff --git a/server/src/args.rs b/server/src/args.rs index 858ac1f..d8ab483 100644 --- a/server/src/args.rs +++ b/server/src/args.rs @@ -11,6 +11,33 @@ const LOCAL_TORII: &str = "http://0.0.0.0:8080"; const KATANA_GENESIS_PATH: &str = "config/genesis.json"; const KATANA_DB_PATH: &str = "storage/katana-db"; +#[derive(Debug, Clone)] +pub struct Config { + pub server: ServerOptions, + pub starknet: StarknetOptions, + pub katana: KatanaOptions, + pub world_address: String, +} + + +impl From for Config { + fn from(args: KeikoArgs) -> Self { + Self { + server: args.server, + starknet: args.starknet, + katana: args.katana, + world_address: "".to_string(), + } + } +} + +impl Config { + pub fn new() -> Self { + let keiko_args = KeikoArgs::parse(); + Self::from(keiko_args) + } +} + #[derive(Parser, Debug, Clone)] #[command(author, version, about, long_about = None)] #[command(propagate_version = true)] @@ -159,7 +186,10 @@ pub struct KatanaOptions { } -impl KeikoArgs { +impl Config { + pub fn set_world_address(&mut self, world_address: String) { + self.world_address = world_address; + } /** * gets all katana args to run katana with */ @@ -251,19 +281,12 @@ impl KeikoArgs { * gets the server state */ pub fn server_state(&self) -> server_state::ServerState { - - // add world_address if it is supplied - // let manifest_directory_path = match &self.world.address { - // None => self.server.manifest_directory_path.clone(), - // Some(world_address) => format!("{}/{}", &self.server.manifest_directory_path, world_address) - // }; - // TODO - let manifest_directory_path = "".to_string(); + let manifest_base_dir = format!("storage/{}", self.world_address); server_state::ServerState { json_rpc_client: self.json_rpc_client(), rpc_url: self.rpc_url(), - manifest_directory_path, + manifest_base_dir, torii_url: self.torii_url(), } } diff --git a/server/src/main.rs b/server/src/main.rs index 20b2792..ce9cbd4 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,6 +1,6 @@ use std::env::current_dir; use std::net::SocketAddr; -use crate::args::KeikoArgs; +use crate::args::{Config}; use clap::Parser; use tokio::signal::unix::{signal, SignalKind}; use tokio::task; @@ -11,7 +11,6 @@ use tower_http::add_extension::AddExtensionLayer; use tower_http::services::{ServeDir, ServeFile}; use tower_http::cors::{Any, CorsLayer}; use keiko_api::handlers::{katana, keiko}; -// use crate::utils::run_torii; use std::process::{Command, Stdio}; use std::fs::File; use serde_json::Value; @@ -27,7 +26,7 @@ const CONFIG_MANIFEST: &str = "config/manifest.json"; #[tokio::main] async fn main() { - let config = KeikoArgs::parse(); + let mut config = Config::new(); if config.server.prod { Command::new("npx") @@ -36,22 +35,7 @@ async fn main() { .expect("Failed to build dashboard"); } - // Start Katana if needed - let katana = { - let katana_args = config.get_katana_args(); - let result = task::spawn(async move { - let output = File::create(KATANA_LOG).expect("Failed to create file"); - - Command::new("katana") - .args(katana_args) - .stdout(Stdio::from(output)) - .spawn() - .expect("Failed to start process"); - }); - // Wait until katana is listening on 5050 - utils::wait_for_port("127.0.0.1:5050".parse().unwrap()).await; - result - }; + let katana = start_katana(config.get_katana_args()).await; // Get the world address from the manifest let manifest_json: Value = serde_json::from_reader( @@ -59,37 +43,15 @@ async fn main() { ).expect("Cannot parse config/manifest.json"); let world_address = manifest_json["world"]["address"].as_str().unwrap().to_string(); + config.set_world_address(world_address.to_string()); let rpc_url = "http://localhost:5050"; - + let torii = start_torii(world_address).await; // TODO Modify the Scarb.toml if needed with world address // TODO Deploy Dojo/contracts if needed - // Start Torii if needed - let torii = { - let mut args: Vec = vec![]; - args.push("--world".to_string()); - args.push(world_address.to_string()); - - args.push("--database".to_string()); - args.push(format!("sqlite:///{}/storage/torii.sqlite", current_dir().unwrap().display())); - - let result = task::spawn(async move { - let output = File::create(TORII_LOG).expect("Failed to create file"); - - Command::new("torii") - .stdout(Stdio::from(output)) - .args(args) - .spawn() - .expect("Failed to start torii"); - }); - - utils::wait_for_port("127.0.0.1:8080".parse().unwrap()).await; - - result - }; let cors = CorsLayer::new() // allow `GET` and `POST` when accessing the resource @@ -100,19 +62,11 @@ async fn main() { let mut router = Router::new(); + let addr = SocketAddr::from(([0, 0, 0, 0], config.server.port.clone())); router = router - .route( - "/api/state", - get(katana::state::save_state) - .on(MethodFilter::PUT, katana::state::load_state) - .on(MethodFilter::DELETE, katana::state::reset_state), - ) .route("/api/fund", get(katana::funds::handler)) - .route("/api/block", on(MethodFilter::POST, katana::block::handler)); - - - router = router + .route("/api/block", on(MethodFilter::POST, katana::block::handler)) // .route("/api/accounts", get(katana::account::handler)) .route( "/manifests/:app_name", @@ -125,9 +79,8 @@ async fn main() { .nest_service("/assets", get_service(ServeDir::new(config.server.static_path.join("assets")))) .fallback_service(get_service(ServeFile::new(config.server.static_path.join("index.html")))) .layer(cors) - .layer(AddExtensionLayer::new(config.server_state())); + .layer(AddExtensionLayer::new(config)); - let addr = SocketAddr::from(([0, 0, 0, 0], config.server.port)); let server = axum::Server::bind(&addr) .serve(router.into_make_service_with_connect_info::()); @@ -135,18 +88,49 @@ async fn main() { let mut sigterm = signal(SignalKind::terminate()).unwrap(); tokio::select! { - _ = server => { - // This arm will run if the server shuts down by itself. - println!("Stopping server..."); - - } - _ = sigterm.recv() => { - // This arm will run if a SIGINT signal is received. - println!("sigterm received, stopping server..."); - } + _ = server => println!("Stopping server..."), + _ = sigterm.recv() => println!("sigterm received, stopping server...") } // Close Katana and Torii katana.abort(); torii.abort(); } + +async fn start_katana(katana_args: Vec) -> task::JoinHandle<()> { + let result = task::spawn(async move { + let output = File::create(KATANA_LOG).expect("Failed to create file"); + + Command::new("katana") + .args(katana_args) + .stdout(Stdio::from(output)) + .spawn() + .expect("Failed to start process"); + }); + // TODO get the server/port from args + utils::wait_for_port("127.0.0.1:5050".parse().unwrap()).await; + result +} + +async fn start_torii(world_address: String) -> task::JoinHandle<()> { + let mut args: Vec = vec![ + "--world".to_string(), + world_address, + "--database".to_string(), + format!("sqlite:///{}/storage/torii.sqlite", current_dir().unwrap().display()), + ]; + + let result = task::spawn(async move { + let output = File::create(TORII_LOG).expect("Failed to create file"); + + Command::new("torii") + .stdout(Stdio::from(output)) + .args(args) + .spawn() + .expect("Failed to start torii"); + }); + + utils::wait_for_port("127.0.0.1:8080".parse().unwrap()).await; + + result +} \ No newline at end of file