Config presets
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use crate::{engine::Engine, store::config::Config};
|
||||
use crate::{engine::Engine, store::config::ConfigManager};
|
||||
|
||||
use pulse_sdk::prelude::*;
|
||||
use toml::Value;
|
||||
@@ -21,7 +21,7 @@ impl Engine {
|
||||
|
||||
match args[0] {
|
||||
"reload" => {
|
||||
*self.config.lock().await = Config::new().await?;
|
||||
*self.config.lock().await = ConfigManager::new().await?;
|
||||
self.terminal_server
|
||||
.info("engine::config", "successfully reloaded")
|
||||
.await?;
|
||||
@@ -50,17 +50,11 @@ impl Engine {
|
||||
if args.len() == 3 {
|
||||
match args[1] {
|
||||
"watchlist" | "watch" | "wl" => {
|
||||
set_cfg!(v, self.config.lock().await.watchlist = v);
|
||||
set_cfg!(v, self.config.lock().await.get_mut()?.watchlist = v);
|
||||
|
||||
self.terminal_server
|
||||
.info("config::set", "watchlist set successfully, use `config save` to persist changes")
|
||||
.await?;
|
||||
|
||||
self.terminal_server
|
||||
.broadcast(TerminalServerMessage::ConfigUpdated(
|
||||
self.get_config_status().await,
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
|
||||
"strategy" | "strat" | "sg" => {
|
||||
@@ -81,30 +75,12 @@ impl Engine {
|
||||
}
|
||||
|
||||
self.strategy_engine.reload(id.as_str()).await?;
|
||||
self.config.lock().await.strategy = id;
|
||||
self.config.lock().await.get_mut()?.strategy = id;
|
||||
});
|
||||
|
||||
self.terminal_server
|
||||
.info("config::set", "strategy set successfully, use `config save` to persist changes")
|
||||
.await?;
|
||||
|
||||
self.terminal_server
|
||||
.broadcast(TerminalServerMessage::ConfigUpdated(
|
||||
self.get_config_status().await,
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
|
||||
"cooldown" | "cool" | "cd" => {
|
||||
set_cfg!(cooldown, {
|
||||
self.config.lock().await.cooldown = cooldown;
|
||||
});
|
||||
|
||||
self.terminal_server
|
||||
.broadcast(TerminalServerMessage::ConfigUpdated(
|
||||
self.get_config_status().await,
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
|
||||
_ => {
|
||||
@@ -113,6 +89,12 @@ impl Engine {
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
self.terminal_server
|
||||
.broadcast(TerminalServerMessage::ConfigUpdated(
|
||||
self.get_config_status().await,
|
||||
))
|
||||
.await?;
|
||||
} else {
|
||||
self.invalid_command_usage("engine::config").await?;
|
||||
}
|
||||
@@ -169,7 +151,7 @@ impl Engine {
|
||||
.terminal_server
|
||||
.error(
|
||||
"engine::account",
|
||||
&format!("Account not found ({new_active})"),
|
||||
&format!("account not found ({new_active})"),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
@@ -179,7 +161,7 @@ impl Engine {
|
||||
self.terminal_server
|
||||
.info(
|
||||
"engine::account",
|
||||
&format!("Account set to {new_active} successfully!"),
|
||||
&format!("account set to {new_active} successfully!"),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
@@ -190,6 +172,80 @@ impl Engine {
|
||||
}
|
||||
}
|
||||
|
||||
"preset" => {
|
||||
if args.len() == 0 {
|
||||
return self.invalid_command_usage("engine::preset").await;
|
||||
}
|
||||
|
||||
match args[0] {
|
||||
"list" | "ls" => {
|
||||
self.terminal_server
|
||||
.info("engine::preset", "PRESET LIST")
|
||||
.await?;
|
||||
|
||||
let config = self.config.lock().await;
|
||||
|
||||
for (name, cfg) in &config.configs {
|
||||
let description = if let Some(desc) = &cfg.description {
|
||||
format!("- {desc}")
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
self.terminal_server
|
||||
.info(
|
||||
"engine::preset",
|
||||
&if name == &config.preset {
|
||||
format!("{name} (active) {description}")
|
||||
} else {
|
||||
format!("{name} {description}")
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
"use" | "set" => {
|
||||
if args.len() < 2 {
|
||||
return self.invalid_command_usage("engine::preset").await;
|
||||
}
|
||||
|
||||
let new_active = args[1];
|
||||
|
||||
let mut config = self.config.lock().await;
|
||||
|
||||
if !config.configs.contains_key(new_active) {
|
||||
return self
|
||||
.terminal_server
|
||||
.error(
|
||||
"engine::preset",
|
||||
&format!("preset not found ({new_active})"),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
config.preset = new_active.to_string();
|
||||
|
||||
self.terminal_server
|
||||
.info(
|
||||
"engine::preset",
|
||||
&format!("preset set to {new_active} successfully!"),
|
||||
)
|
||||
.await?;
|
||||
|
||||
self.terminal_server
|
||||
.broadcast(TerminalServerMessage::ConfigUpdated(
|
||||
self.get_config_status().await,
|
||||
))
|
||||
.await?;
|
||||
}
|
||||
|
||||
_ => {
|
||||
return self.invalid_command_usage("engine::preset").await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"strategy" | "strat" | "sg" => {
|
||||
let Some(strategy_command) = args.drain(0..=0).next() else {
|
||||
return self.invalid_command_usage("strategy").await;
|
||||
@@ -211,7 +267,7 @@ impl Engine {
|
||||
|
||||
_ => {
|
||||
self.terminal_server
|
||||
.error("engine::cmd", &format!("Command '{}' not found", command))
|
||||
.error("engine::cmd", &format!("command '{}' not found", command))
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ pub mod terminal;
|
||||
|
||||
use crate::{
|
||||
engine::{strategy::StrategyEngine, terminal::TerminalServer},
|
||||
store::{accounts::AccountList, config::Config},
|
||||
store::{accounts::AccountList, config::ConfigManager},
|
||||
};
|
||||
use hypersdk::hypercore::ws::ConnectionStream;
|
||||
use pulse_sdk::prelude::*;
|
||||
@@ -26,7 +26,7 @@ pub struct Engine {
|
||||
pub ws_stream: Arc<Mutex<ConnectionStream>>,
|
||||
|
||||
// data
|
||||
pub config: Arc<Mutex<Config>>,
|
||||
pub config: Arc<Mutex<ConfigManager>>,
|
||||
pub accounts: Arc<Mutex<AccountList>>,
|
||||
|
||||
// live data / status
|
||||
@@ -37,11 +37,11 @@ pub struct Engine {
|
||||
|
||||
impl Engine {
|
||||
pub async fn new() -> tokio::io::Result<Arc<Self>> {
|
||||
let config = Config::new().await?;
|
||||
let config = ConfigManager::new().await?;
|
||||
|
||||
let (ws_handle, ws_stream) = hypersdk::hypercore::mainnet_ws().split();
|
||||
|
||||
let strategy = StrategyEngine::new(&config.strategy, ws_handle).await?;
|
||||
let strategy = StrategyEngine::new(&config.get_ref()?.strategy, ws_handle).await?;
|
||||
|
||||
let accounts = Arc::new(Mutex::new(AccountList::new().await?));
|
||||
let config = Arc::new(Mutex::new(config));
|
||||
@@ -91,6 +91,7 @@ impl Engine {
|
||||
|
||||
pub async fn get_config_status(&self) -> EngineConfig {
|
||||
EngineConfig {
|
||||
preset: self.config.lock().await.preset.clone(),
|
||||
strategy: self.strategy_engine.strategy.lock().await.manifest.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,8 +194,11 @@ impl TerminalServer {
|
||||
loop {
|
||||
refresh.tick().await;
|
||||
|
||||
match crate::fetch::fetch_watch_list(&client, &engine.config.lock().await.watchlist)
|
||||
.await
|
||||
match crate::fetch::fetch_watch_list(
|
||||
&client,
|
||||
&engine.config.lock().await.get_ref()?.watchlist,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(watch_list) => {
|
||||
*engine.watch_list.lock().await = watch_list.clone();
|
||||
|
||||
@@ -1,23 +1,60 @@
|
||||
use hypersdk::hypercore::CandleInterval;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct Config {
|
||||
pub description: Option<String>,
|
||||
pub watchlist: Vec<String>,
|
||||
pub strategy: String,
|
||||
pub cooldown: CandleInterval,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct ConfigManager {
|
||||
pub preset: String,
|
||||
|
||||
#[serde(flatten)]
|
||||
pub configs: HashMap<String, Config>,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
description: None,
|
||||
watchlist: vec!["BTC".to_string(), "SOL".to_string(), "ETH".to_string()],
|
||||
strategy: String::new(),
|
||||
cooldown: CandleInterval::ThirtyMinutes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
impl Default for ConfigManager {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
preset: "Main".to_string(),
|
||||
configs: HashMap::from([("Main".to_string(), Config::default())]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigManager {
|
||||
pub fn get_ref(&self) -> tokio::io::Result<&Config> {
|
||||
self.configs.get(&self.preset).ok_or_else(|| {
|
||||
tokio::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
format!("Failed to get preset '{}'", self.preset),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self) -> tokio::io::Result<&mut Config> {
|
||||
self.configs.get_mut(&self.preset).ok_or_else(|| {
|
||||
tokio::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
format!("Failed to get preset '{}'", self.preset),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigManager {
|
||||
pub async fn new() -> tokio::io::Result<Self> {
|
||||
let path = crate::store::pulse_config_file()?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user