diff --git a/Cargo.lock b/Cargo.lock index 50d78660d..322447769 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1053,6 +1053,33 @@ dependencies = [ "tracing", ] +[[package]] +name = "calimero-cli" +version = "0.1.0" +dependencies = [ + "calimero-application", + "calimero-network", + "calimero-node", + "calimero-node-primitives", + "calimero-primitives", + "calimero-server", + "calimero-store", + "camino", + "clap 4.5.4", + "color-eyre", + "dirs", + "eyre", + "hex", + "libp2p", + "multiaddr", + "serde", + "sha2 0.10.8", + "tokio", + "toml 0.8.12", + "tracing", + "tracing-subscriber", +] + [[package]] name = "calimero-identity" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 0172531f7..62df77366 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ license = "MIT OR Apache-2.0" resolver = "2" members = [ "./crates/application", + "./crates/cli", "./crates/identity", "./crates/network", "./crates/node", diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml new file mode 100644 index 000000000..ecb966160 --- /dev/null +++ b/crates/cli/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "calimero-cli" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +repository.workspace = true +license.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +camino = { workspace = true, features = ["serde1"] } +clap = { workspace = true, features = ["env", "derive"] } +tracing-subscriber = { workspace = true, features = ["env-filter"] } +color-eyre.workspace = true +libp2p.workspace = true +dirs.workspace = true +eyre.workspace = true +tokio = { workspace = true, features = ["io-std", "macros"] } +multiaddr.workspace = true +serde = { workspace = true, features = ["derive"] } +sha2.workspace = true +toml.workspace = true +tracing.workspace = true +hex.workspace = true + +calimero-node = { path = "../node" } +calimero-network = { path = "../network" } +calimero-application = { path = "../application" } +calimero-node-primitives = { path = "../node-primitives" } +calimero-primitives = { path = "../primitives" } +calimero-server = { path = "../server", features = ["jsonrpc", "websocket", "admin"] } +calimero-store = { path = "../store" } diff --git a/crates/node/src/cli.rs b/crates/cli/src/cli.rs similarity index 56% rename from crates/node/src/cli.rs rename to crates/cli/src/cli.rs index 6becb0e0f..825415256 100644 --- a/crates/node/src/cli.rs +++ b/crates/cli/src/cli.rs @@ -1,38 +1,45 @@ -use calimero_node::config; use clap::{Parser, Subcommand}; +use crate::config; + mod init; +mod link; mod run; - +mod setup; #[derive(Debug, Parser)] -#[clap(author, about, version)] +#[command(author, about, version)] pub struct RootCommand { - #[clap(flatten)] + #[command(flatten)] pub args: RootArgs, - #[clap(subcommand)] + #[command(subcommand)] pub action: SubCommands, } #[derive(Debug, Subcommand)] pub enum SubCommands { Init(init::InitCommand), + Setup(setup::SetupCommand), Run(run::RunCommand), + Link(link::LinkCommand), } #[derive(Debug, Parser)] pub struct RootArgs { /// Directory for config and data - #[clap(long, value_name = "PATH", default_value_t = config::default_chat_dir())] - #[clap(env = "CALIMERO_CHAT_HOME", hide_env_values = true)] + #[arg(long, value_name = "PATH", default_value_t = config::default_chat_dir())] + #[arg(env = "CALIMERO_HOME", hide_env_values = true)] pub home: camino::Utf8PathBuf, } impl RootCommand { pub async fn run(self) -> eyre::Result<()> { + let _c = RootCommand::parse(); match self.action { SubCommands::Init(init) => return init.run(self.args), + SubCommands::Setup(setup) => return setup.run(self.args), SubCommands::Run(run) => return run.run(self.args).await, + SubCommands::Link(link) => link.run(self.args), } } } diff --git a/crates/cli/src/cli/init.rs b/crates/cli/src/cli/init.rs new file mode 100644 index 000000000..3797c914c --- /dev/null +++ b/crates/cli/src/cli/init.rs @@ -0,0 +1,83 @@ +use std::fs; + +use clap::Parser; +use eyre::WrapErr; +use libp2p::identity; +use tracing::{info, warn}; + +use crate::cli; +use crate::config::{ConfigFile, ConfigImpl, InitFile}; + +/// Initialize node and it's identity +#[derive(Debug, Parser)] +pub struct InitCommand { + /// Name of node + #[arg(short, long, value_name = "NAME")] + pub node_name: camino::Utf8PathBuf, + + /// Force initialization even if the directory already exists + #[clap(short, long)] + pub force: bool, +} + +impl InitCommand { + pub fn run(self, root_args: cli::RootArgs) -> eyre::Result<()> { + let path = root_args.home.join(&self.node_name); + + fs::create_dir_all(&path) + .wrap_err_with(|| format!("failed to create directory {:?}", &path))?; + + if InitFile::exists(&path) { + match ConfigFile::load(&path) { + Ok(config) => { + if self.force { + warn!( + "Overriding config.toml file for {}, keeping identity", + self.node_name + ); + let config_new = InitFile { + identity: config.identity, + }; + config_new.save(&path)?; + return Ok(()); + } else { + eyre::bail!( + "Node {} is already initialized in {:?}", + self.node_name, + path + ); + } + } + Err(_err) => match InitFile::load(&path) { + Ok(_config) => { + if self.force { + eyre::bail!( + "Node {} is already initialized in {:?}\nCan not override node identity", + self.node_name, + path + ); + } else { + eyre::bail!( + "Node {} is already initialized in {:?}", + self.node_name, + path + ); + } + } + Err(err) => eyre::bail!("failed to load existing configuration: {}", err), + }, + } + } + let identity = identity::Keypair::generate_ed25519(); + info!("Generated identity: {:?}", identity.public().to_peer_id()); + + let config = InitFile { + identity: identity.clone(), + }; + + config.save(&path)?; + + println!("{:?}", path); + Ok(()) + } +} diff --git a/crates/cli/src/cli/link.rs b/crates/cli/src/cli/link.rs new file mode 100644 index 000000000..030a185c3 --- /dev/null +++ b/crates/cli/src/cli/link.rs @@ -0,0 +1,91 @@ +use std::fs; +#[cfg(unix)] +use std::os::unix::fs::symlink; +#[cfg(windows)] +use std::os::windows::fs::symlink_file as symlink; + +use clap::Parser; +use eyre::WrapErr; +use sha2::{Digest, Sha256}; +use tracing::info; + +use crate::cli; +use crate::config::{ConfigFile, ConfigImpl}; + +/// Setup symlink to application in the node +#[derive(Debug, Parser)] +pub struct LinkCommand { + /// Name of node + #[arg(short, long, value_name = "NAME")] + pub node_name: camino::Utf8PathBuf, + + /// Path to original file + #[clap(short, long)] + pub path: camino::Utf8PathBuf, + + /// Name of application + #[clap(short, long)] + pub app_name: camino::Utf8PathBuf, + + /// Version + #[clap(short, long, value_parser = validate_version, default_value = "1.0.0")] + pub version: String, +} + +fn validate_version(v: &str) -> Result { + let parts: Vec<&str> = v.split('.').collect(); + if parts.len() != 3 { + return Err(String::from("Version must have exactly three parts")); + } + + for part in parts { + match part.parse::() { + Ok(_) => {} + Err(e) => return Err(format!("Invalid version number: {}", e)), + } + } + + Ok(v.to_string()) +} + +impl LinkCommand { + pub fn run(self, root_args: cli::RootArgs) -> eyre::Result<()> { + let path_to_node = root_args.home.join(&self.node_name); + if ConfigFile::exists(&path_to_node) { + match ConfigFile::load(&path_to_node) { + Ok(config) => { + let id = format!("{}:{}", self.node_name, self.app_name); + let mut hasher = Sha256::new(); + hasher.update(id.as_bytes()); + let hash_string = hex::encode(hasher.finalize()); + + let app_path = path_to_node + .join(config.application.path) + .join(hash_string) + .join(self.version); + + fs::create_dir_all(&app_path) + .wrap_err_with(|| format!("failed to create directory {:?}", &app_path))?; + info!("Linking original file to: {:?}", app_path); + + match symlink(self.path, app_path.join("binary.wasm")) { + Ok(_) => {} + Err(err) => eyre::bail!("Symlinking failed: {}", err), + } + info!( + "Application {} linked to node {}\nPath to linked file at {}", + self.app_name, + self.node_name, + app_path.join("binary.wasm") + ); + return Ok(()); + } + Err(err) => { + eyre::bail!("failed to load existing configuration: {}", err); + } + } + } else { + eyre::bail!("You have to initialize the node first \nRun command node init -n "); + } + } +} diff --git a/crates/node/src/cli/run.rs b/crates/cli/src/cli/run.rs similarity index 80% rename from crates/node/src/cli/run.rs rename to crates/cli/src/cli/run.rs index b14818672..d3953ebcd 100644 --- a/crates/node/src/cli/run.rs +++ b/crates/cli/src/cli/run.rs @@ -1,11 +1,15 @@ -use calimero_node::config::ConfigFile; use clap::{Parser, ValueEnum}; use crate::cli; +use crate::config::{ConfigFile, ConfigImpl}; /// Run a node #[derive(Debug, Parser)] pub struct RunCommand { + /// Name of node + #[arg(short, long, value_name = "NAME")] + pub node_name: camino::Utf8PathBuf, + #[clap(long, value_name = "TYPE")] #[clap(value_enum, default_value_t)] pub node_type: NodeType, @@ -29,21 +33,22 @@ impl From for calimero_node_primitives::NodeType { impl RunCommand { pub async fn run(self, root_args: cli::RootArgs) -> eyre::Result<()> { - if !ConfigFile::exists(&root_args.home) { - eyre::bail!("chat node is not initialized in {:?}", root_args.home); + let path = root_args.home.join(self.node_name); + if !ConfigFile::exists(&path) { + eyre::bail!("chat node is not initialized in {:?}", path); } - let config = ConfigFile::load(&root_args.home)?; + let config = ConfigFile::load(&path)?; calimero_node::start(calimero_node::NodeConfig { - home: root_args.home.clone(), + home: path.clone(), node_type: self.node_type.into(), identity: config.identity.clone(), store: calimero_store::config::StoreConfig { - path: root_args.home.join(config.store.path), + path: path.join(config.store.path), }, application: calimero_application::config::ApplicationConfig { - dir: root_args.home.join(config.application.path), + dir: path.join(config.application.path), }, network: calimero_network::config::NetworkConfig { identity: config.identity.clone(), diff --git a/crates/cli/src/cli/setup.rs b/crates/cli/src/cli/setup.rs new file mode 100644 index 000000000..500b104e1 --- /dev/null +++ b/crates/cli/src/cli/setup.rs @@ -0,0 +1,223 @@ +use std::net::IpAddr; + +use calimero_network::config::{BootstrapConfig, BootstrapNodes, DiscoveryConfig, SwarmConfig}; +use camino::Utf8PathBuf; +use clap::parser::ValueSource; +use clap::{ArgMatches, CommandFactory, Parser, ValueEnum}; +use multiaddr::Multiaddr; +use tracing::info; + +use crate::cli; +use crate::config::{ + ApplicationConfig, ConfigFile, ConfigImpl, InitFile, NetworkConfig, ServerConfig, StoreConfig, +}; + +/// Initialize node configuration +#[derive(Debug, Parser)] +pub struct SetupCommand { + /// Name of node + #[arg(short, long, value_name = "NAME")] + pub node_name: Utf8PathBuf, + + /// List of bootstrap nodes + #[arg(long, value_name = "ADDR")] + pub boot_nodes: Vec, + + /// Use nodes from a known network + #[arg(long, value_name = "NETWORK", default_value = "calimero-dev")] + pub boot_network: Option, + + /// Host to listen on + #[arg( + long, + value_name = "HOST", + default_value = "0.0.0.0,::", + use_value_delimiter = true + )] + pub swarm_host: Vec, + + /// Port to listen on + #[arg(long, value_name = "PORT", default_value_t = calimero_network::config::DEFAULT_PORT)] + pub swarm_port: u16, + + /// Host to listen on for RPC + #[arg( + long, + value_name = "HOST", + default_value = "127.0.0.1,::1", + use_value_delimiter = true + )] + pub server_host: Vec, + + /// Port to listen on for RPC + #[arg(long, value_name = "PORT", default_value_t = calimero_server::config::DEFAULT_PORT)] + pub server_port: u16, + + /// Enable mDNS discovery + #[arg(long, default_value_t = true, overrides_with("no_mdns"))] + pub mdns: bool, + + #[arg(long, hide = true, overrides_with("mdns"))] + pub no_mdns: bool, + + /// Force edit even if the argument already exists + #[arg(long, short)] + pub force: bool, + + /// Print the config file + #[arg(long, short)] + pub print: bool, +} + +#[derive(Clone, Debug, ValueEnum)] +pub enum BootstrapNetwork { + CalimeroDev, + Ipfs, +} + +impl SetupCommand { + pub fn run(mut self, root_args: cli::RootArgs) -> eyre::Result<()> { + let path = root_args.home.join(&self.node_name); + + let matches = cli::RootCommand::command().get_matches(); // get matches for value_source + + // Extract subcommand matches for SetupCommand + let setup_matches = matches.subcommand_matches("setup").unwrap(); + + let mut boot_network_provided = check_if_provided(&setup_matches, "boot_network"); + let swarm_host_provided = check_if_provided(&setup_matches, "swarm_host"); + let swarm_port_provided = check_if_provided(&setup_matches, "swarm_port"); + let server_host_provided = check_if_provided(&setup_matches, "server_host"); + let server_port_provided = check_if_provided(&setup_matches, "server_port"); + let mdns_provided = check_if_provided(&setup_matches, "mdns"); + + let identity; + let mut swarm_listen = None; + let mut server_listen = None; + + if InitFile::exists(&path) { + if let Ok(config_identity) = InitFile::load(&path) { + identity = config_identity.identity; + } else { + eyre::bail!("Failed to open identity for node \nRun command node init -n "); + } + if let Ok(config) = ConfigFile::load(&path) { + if self.print { + println!("{}", toml::to_string_pretty(&config)?); + return Ok(()); + } + if !self.force { + eyre::bail!( + "The config for the node is already initialized \nYou can override a setting by adding the -f flag" + ); + } else { + if !boot_network_provided { + self.boot_nodes = config.network.bootstrap.nodes.list; + } + if !swarm_host_provided && !swarm_port_provided { + swarm_listen = Some(config.network.swarm.listen); + } + if !server_host_provided && !server_port_provided { + server_listen = Some(config.network.server.listen); + } + if !mdns_provided { + self.mdns = config.network.discovery.mdns; + } + } + } else { + boot_network_provided = true; + } + } else { + eyre::bail!("You have to initialize the node first \nRun command node init -n "); + } + + let mdns = self.mdns && !self.no_mdns; + + let mut listen: Vec = vec![]; + + match swarm_listen { + Some(data) => listen.extend(data), + None => { + for host in self.swarm_host { + let host = format!( + "/{}/{}", + match host { + std::net::IpAddr::V4(_) => "ip4", + std::net::IpAddr::V6(_) => "ip6", + }, + host, + ); + listen.push(format!("{}/tcp/{}", host, self.swarm_port).parse()?); + listen.push(format!("{}/udp/{}/quic-v1", host, self.swarm_port).parse()?); + } + } + } + + let mut boot_nodes = vec![]; + if boot_network_provided { + if let Some(network) = self.boot_network { + match network { + BootstrapNetwork::CalimeroDev => { + boot_nodes.extend(BootstrapNodes::calimero_dev().list) + } + BootstrapNetwork::Ipfs => boot_nodes.extend(BootstrapNodes::ipfs().list), + } + } + } else { + boot_nodes = self.boot_nodes; + } + + let config_new = ConfigFile { + identity, + store: StoreConfig { + path: "data".into(), + }, + application: ApplicationConfig { + path: "apps".into(), + }, + network: NetworkConfig { + swarm: SwarmConfig { listen }, + bootstrap: BootstrapConfig { + nodes: BootstrapNodes { list: boot_nodes }, + }, + discovery: DiscoveryConfig { + mdns, + rendezvous: Default::default(), + }, + server: ServerConfig { + listen: match server_listen { + Some(data) => data, + None => self + .server_host + .into_iter() + .map(|host| { + Multiaddr::from(host) + .with(multiaddr::Protocol::Tcp(self.server_port)) + }) + .collect(), + }, + admin: Some(calimero_server::admin::service::AdminConfig { enabled: true }), + jsonrpc: Some(calimero_server::jsonrpc::JsonRpcConfig { enabled: true }), + websocket: Some(calimero_server::ws::WsConfig { enabled: true }), + }, + }, + }; + + config_new.save(&path)?; + + calimero_store::Store::open(&calimero_store::config::StoreConfig { + path: path.join(config_new.store.path), + })?; + + info!("Initialized confing for a node in {:?}", root_args.home); + + Ok(()) + } +} + +fn check_if_provided(matches: &ArgMatches, arg_name: &str) -> bool { + if let Some(ValueSource::CommandLine) = matches.value_source(arg_name) { + return true; + } + false +} diff --git a/crates/node/src/config.rs b/crates/cli/src/config.rs similarity index 76% rename from crates/node/src/config.rs rename to crates/cli/src/config.rs index 851eca039..ca27a25a7 100644 --- a/crates/node/src/config.rs +++ b/crates/cli/src/config.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; const CONFIG_FILE: &str = "config.toml"; -pub const DEFAULT_CALIMERO_CHAT_HOME: &str = ".calimero/experiments/chat-p0c"; +pub(crate) const DEFAULT_CALIMERO_HOME: &str = "Documents/core/data"; //this has to be changed, find path to /core #[derive(Debug, Serialize, Deserialize)] pub struct ConfigFile { @@ -56,17 +56,27 @@ pub struct StoreConfig { pub path: camino::Utf8PathBuf, } +#[derive(Debug, Serialize, Deserialize)] +pub struct InitFile { + #[serde(with = "calimero_primitives::identity::serde_identity")] + pub identity: identity::Keypair, +} + #[derive(Debug, Serialize, Deserialize)] pub struct ApplicationConfig { pub path: camino::Utf8PathBuf, } -impl ConfigFile { - pub fn exists(dir: &camino::Utf8Path) -> bool { +pub trait ConfigImpl { + fn exists(dir: &camino::Utf8Path) -> bool { dir.join(CONFIG_FILE).is_file() } - pub fn load(dir: &camino::Utf8Path) -> eyre::Result { + fn load(dir: &camino::Utf8Path) -> eyre::Result + where + Self: Sized, + for<'de> Self: Deserialize<'de>, + { let path = dir.join(CONFIG_FILE); let content = fs::read_to_string(&path).wrap_err_with(|| { format!( @@ -78,7 +88,10 @@ impl ConfigFile { toml::from_str(&content).map_err(Into::into) } - pub fn save(&self, dir: &camino::Utf8Path) -> eyre::Result<()> { + fn save(&self, dir: &camino::Utf8Path) -> eyre::Result<()> + where + Self: Serialize, + { let path = dir.join(CONFIG_FILE); let content = toml::to_string_pretty(self)?; @@ -93,10 +106,13 @@ impl ConfigFile { } } +impl ConfigImpl for ConfigFile {} +impl ConfigImpl for InitFile {} + pub fn default_chat_dir() -> camino::Utf8PathBuf { if let Some(home) = dirs::home_dir() { let home = camino::Utf8Path::from_path(&home).expect("invalid home directory"); - return home.join(DEFAULT_CALIMERO_CHAT_HOME); + return home.join(DEFAULT_CALIMERO_HOME); } Default::default() diff --git a/crates/node/src/main.rs b/crates/cli/src/main.rs similarity index 98% rename from crates/node/src/main.rs rename to crates/cli/src/main.rs index 5cf6c72ce..fd4eb03bb 100644 --- a/crates/node/src/main.rs +++ b/crates/cli/src/main.rs @@ -3,6 +3,7 @@ use tracing_subscriber::prelude::*; use tracing_subscriber::EnvFilter; mod cli; +mod config; #[tokio::main] async fn main() -> eyre::Result<()> { diff --git a/crates/node/src/cli/init.rs b/crates/node/src/cli/init.rs deleted file mode 100644 index 0bd837891..000000000 --- a/crates/node/src/cli/init.rs +++ /dev/null @@ -1,170 +0,0 @@ -use std::fs; -use std::net::IpAddr; - -use calimero_network::config::{BootstrapConfig, BootstrapNodes, DiscoveryConfig, SwarmConfig}; -use calimero_node::config::{self, ApplicationConfig, ConfigFile, NetworkConfig, StoreConfig}; -use clap::{Parser, ValueEnum}; -use eyre::WrapErr; -use libp2p::identity; -use multiaddr::Multiaddr; -use tracing::{info, warn}; - -use crate::cli; - -/// Initialize node configuration -#[derive(Debug, Parser)] -// todo! simplify this, by splitting the steps -// todo! $ calimero node init -// todo! $ calimero node config 'swarm.listen:=["", ""]' discovery.mdns:=false -// todo! $ calimero node config discovery.mdns -pub struct InitCommand { - /// List of bootstrap nodes - #[clap(long, value_name = "ADDR")] - pub boot_nodes: Vec, - - /// Use nodes from a known network - #[clap(long, value_name = "NETWORK", default_value = "calimero-dev")] - pub boot_network: Option, - - /// Host to listen on - #[clap(long, value_name = "HOST")] - #[clap(default_value = "0.0.0.0,::")] - #[clap(use_value_delimiter = true)] - pub swarm_host: Vec, - - /// Port to listen on - #[clap(long, value_name = "PORT")] - #[clap(default_value_t = calimero_network::config::DEFAULT_PORT)] - pub swarm_port: u16, - - /// Host to listen on for RPC - #[clap(long, value_name = "HOST")] - #[clap(default_value = "127.0.0.1,::1")] - #[clap(use_value_delimiter = true)] - pub server_host: Vec, - - /// Port to listen on for RPC - #[clap(long, value_name = "PORT")] - #[clap(default_value_t = calimero_server::config::DEFAULT_PORT)] - pub server_port: u16, - - /// Enable mDNS discovery - #[clap(long, default_value_t = true)] - #[clap(overrides_with("no_mdns"))] - pub mdns: bool, - - #[clap(long, hide = true)] - #[clap(overrides_with("mdns"))] - pub no_mdns: bool, - - /// Force initialization even if the directory already exists - #[clap(long)] - pub force: bool, -} - -#[derive(Clone, Debug, ValueEnum)] -pub enum BootstrapNetwork { - CalimeroDev, - Ipfs, -} - -impl InitCommand { - pub fn run(self, root_args: cli::RootArgs) -> eyre::Result<()> { - let mdns = self.mdns && !self.no_mdns; - - if !root_args.home.exists() { - if root_args.home == config::default_chat_dir() { - fs::create_dir_all(&root_args.home) - } else { - fs::create_dir(&root_args.home) - } - .wrap_err_with(|| format!("failed to create directory {:?}", root_args.home))?; - } - - if ConfigFile::exists(&root_args.home) { - if let Err(err) = ConfigFile::load(&root_args.home) { - if self.force { - warn!( - "Failed to load existing configuration, overwriting: {}", - err - ); - } else { - eyre::bail!("failed to load existing configuration: {}", err); - } - } - if !self.force { - eyre::bail!("chat node is already initialized in {:?}", root_args.home); - } - } - - let identity = identity::Keypair::generate_ed25519(); - info!("Generated identity: {:?}", identity.public().to_peer_id()); - - let mut listen: Vec = vec![]; - - for host in self.swarm_host { - let host = format!( - "/{}/{}", - match host { - std::net::IpAddr::V4(_) => "ip4", - std::net::IpAddr::V6(_) => "ip6", - }, - host, - ); - listen.push(format!("{}/tcp/{}", host, self.swarm_port).parse()?); - listen.push(format!("{}/udp/{}/quic-v1", host, self.swarm_port).parse()?); - } - - let mut boot_nodes = self.boot_nodes; - if let Some(network) = self.boot_network { - match network { - BootstrapNetwork::CalimeroDev => { - boot_nodes.extend(BootstrapNodes::calimero_dev().list) - } - BootstrapNetwork::Ipfs => boot_nodes.extend(BootstrapNodes::ipfs().list), - } - } - - let config = ConfigFile { - identity: identity.clone(), - store: StoreConfig { - path: "data".into(), - }, - application: ApplicationConfig { - path: "apps".into(), - }, - network: NetworkConfig { - swarm: SwarmConfig { listen }, - bootstrap: BootstrapConfig { - nodes: BootstrapNodes { list: boot_nodes }, - }, - discovery: DiscoveryConfig { - mdns, - rendezvous: Default::default(), - }, - server: calimero_node::config::ServerConfig { - listen: self - .server_host - .into_iter() - .map(|host| { - Multiaddr::from(host).with(multiaddr::Protocol::Tcp(self.server_port)) - }) - .collect(), - admin: Some(calimero_server::admin::service::AdminConfig { enabled: true }), - jsonrpc: Some(calimero_server::jsonrpc::JsonRpcConfig { enabled: true }), - websocket: Some(calimero_server::ws::WsConfig { enabled: true }), - }, - }, - }; - - config.save(&root_args.home)?; - - calimero_store::Store::open(&calimero_store::config::StoreConfig { - path: root_args.home.join(config.store.path), - })?; - - info!("Initialized a chat node in {:?}", root_args.home); - - Ok(()) - } -} diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs index eb380f682..16e973be7 100644 --- a/crates/node/src/lib.rs +++ b/crates/node/src/lib.rs @@ -9,7 +9,6 @@ use tokio::io::AsyncBufReadExt; use tokio::sync::{broadcast, mpsc, oneshot}; use tracing::{error, info}; -pub mod config; pub mod temporal_runtime_store; pub mod transaction_pool; pub mod types;