use clmm_lp_execution::prelude::{
CircuitBreaker, LifecycleTracker, PositionMonitor, StrategyExecutor, TransactionManager,
};
use clmm_lp_protocols::prelude::{RpcConfig, RpcProvider};
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::{RwLock, broadcast};
#[derive(Clone)]
pub struct AppState {
pub provider: Arc<RpcProvider>,
pub monitor: Arc<PositionMonitor>,
pub tx_manager: Arc<TransactionManager>,
pub circuit_breaker: Arc<CircuitBreaker>,
pub lifecycle: Arc<LifecycleTracker>,
pub strategies: Arc<RwLock<HashMap<String, StrategyState>>>,
pub position_updates: broadcast::Sender<PositionUpdate>,
pub alert_updates: broadcast::Sender<AlertUpdate>,
pub config: ApiConfig,
pub executors: Arc<RwLock<HashMap<String, Arc<RwLock<StrategyExecutor>>>>>,
pub dry_run: bool,
}
impl AppState {
pub fn new(rpc_config: RpcConfig, api_config: ApiConfig) -> Self {
let provider = Arc::new(RpcProvider::new(rpc_config));
let monitor = Arc::new(PositionMonitor::new(
provider.clone(),
clmm_lp_execution::prelude::MonitorConfig::default(),
));
let tx_manager = Arc::new(TransactionManager::new(
provider.clone(),
clmm_lp_execution::prelude::TransactionConfig::default(),
));
let circuit_breaker = Arc::new(CircuitBreaker::default());
let lifecycle = Arc::new(LifecycleTracker::new());
let (position_tx, _) = broadcast::channel(1000);
let (alert_tx, _) = broadcast::channel(1000);
Self {
provider,
monitor,
tx_manager,
circuit_breaker,
lifecycle,
strategies: Arc::new(RwLock::new(HashMap::new())),
position_updates: position_tx,
alert_updates: alert_tx,
config: api_config,
executors: Arc::new(RwLock::new(HashMap::new())),
dry_run: true, }
}
pub fn set_dry_run(&mut self, dry_run: bool) {
self.dry_run = dry_run;
}
pub fn broadcast_position_update(&self, update: PositionUpdate) {
let _ = self.position_updates.send(update);
}
pub fn broadcast_alert(&self, alert: AlertUpdate) {
let _ = self.alert_updates.send(alert);
}
pub fn subscribe_positions(&self) -> broadcast::Receiver<PositionUpdate> {
self.position_updates.subscribe()
}
pub fn subscribe_alerts(&self) -> broadcast::Receiver<AlertUpdate> {
self.alert_updates.subscribe()
}
}
#[derive(Debug, Clone)]
pub struct ApiConfig {
pub host: String,
pub port: u16,
pub api_keys: Vec<String>,
pub enable_cors: bool,
pub request_timeout_secs: u64,
pub rate_limit_per_minute: u32,
}
impl Default for ApiConfig {
fn default() -> Self {
Self {
host: "0.0.0.0".to_string(),
port: 8080,
api_keys: vec![],
enable_cors: true,
request_timeout_secs: 30,
rate_limit_per_minute: 100,
}
}
}
#[derive(Debug, Clone)]
pub struct StrategyState {
pub id: String,
pub name: String,
pub running: bool,
pub config: serde_json::Value,
pub created_at: chrono::DateTime<chrono::Utc>,
pub updated_at: chrono::DateTime<chrono::Utc>,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct PositionUpdate {
pub update_type: String,
pub position_address: String,
pub timestamp: chrono::DateTime<chrono::Utc>,
pub data: serde_json::Value,
}
#[derive(Debug, Clone, serde::Serialize)]
pub struct AlertUpdate {
pub level: String,
pub message: String,
pub timestamp: chrono::DateTime<chrono::Utc>,
pub position_address: Option<String>,
}