Skip to main content

bot_cli/
config.rs

1//! Bot CLI configuration types - V2 format.
2//!
3//! Strategy config structs (`GridConfigJson`, `MMConfigJson`, etc.) are defined
4//! once in `bot-engine` and re-exported here. Only CLI/schema-specific types
5//! (`BotConfig`, `MarketConfig`, `Hip3ConfigJson`, `InstrumentMetaConfig`) live here.
6//!
7//! This avoids duplication: adding a new strategy config means adding it once
8//! in `bot-engine/src/config.rs` — it's automatically available here.
9
10use schemars::JsonSchema;
11use serde::{Deserialize, Serialize};
12
13// Re-export strategy config structs from bot-engine (single source of truth)
14pub use bot_engine::{
15    ArbitrageConfigJson, BuilderFeeConfig, DCAConfigJson, GridConfigJson, MMConfigJson,
16    OrchestratorConfigJson, SyncConfigJson,
17};
18
19/// V2 Bot configuration - the full config format for all strategies.
20///
21/// This is the **schema-generation** version of BotConfig. It uses flat
22/// `MarketConfig` structs (for clean JSON Schema output), unlike the engine's
23/// `BotConfig` which uses typed `bot_core::Market` enums for runtime parsing.
24#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
25pub struct BotConfig {
26    /// Environment: "testnet" or "mainnet"
27    pub environment: String,
28
29    /// Private key (hex, with or without 0x prefix)
30    pub private_key: String,
31
32    /// Wallet address
33    pub address: String,
34
35    /// Optional vault address
36    #[serde(default)]
37    pub vault_address: Option<String>,
38
39    /// Optional Hyperliquid base URL override.
40    /// When set, both /info and /exchange requests use this gateway.
41    #[serde(default)]
42    pub base_url_override: Option<String>,
43
44    /// Strategy type: "grid", "mm", "dca", "arbitrage", or "orchestrator"
45    pub strategy_type: String,
46
47    /// Markets to trade on (V2 format)
48    #[serde(default)]
49    pub markets: Vec<MarketConfig>,
50
51    /// Polling delay in milliseconds
52    #[serde(default = "default_poll_delay_ms")]
53    pub poll_delay_ms: u64,
54
55    // -------------------------------------------------------------------------
56    // Strategy-specific config objects (only one should be set)
57    // -------------------------------------------------------------------------
58    /// Grid strategy configuration
59    #[serde(default)]
60    pub grid: Option<GridConfigJson>,
61
62    /// Market Maker strategy configuration
63    #[serde(default)]
64    pub mm: Option<MMConfigJson>,
65
66    /// DCA strategy configuration
67    #[serde(default)]
68    pub dca: Option<DCAConfigJson>,
69
70    /// Arbitrage strategy configuration
71    #[serde(default)]
72    pub arbitrage: Option<ArbitrageConfigJson>,
73
74    /// Orchestrator strategy configuration
75    #[serde(default)]
76    pub orchestrator: Option<OrchestratorConfigJson>,
77
78    // -------------------------------------------------------------------------
79    // Common config
80    // -------------------------------------------------------------------------
81    /// Builder fee configuration
82    #[serde(default)]
83    pub builder_fee: Option<BuilderFeeConfig>,
84
85    /// HIP-3 configuration
86    #[serde(default)]
87    pub hip3: Option<Hip3ConfigJson>,
88
89    /// Trade sync configuration
90    #[serde(default)]
91    pub sync: Option<SyncConfigJson>,
92}
93
94// =============================================================================
95// CLI-specific types (not in bot-engine)
96// =============================================================================
97
98/// Market configuration (V2 format) — flat representation for JSON Schema.
99///
100/// The engine uses `bot_core::Market` (tagged enum) instead. This flat struct
101/// exists so the generated JSON Schema is clean for external consumers.
102#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
103pub struct MarketConfig {
104    /// Exchange name (e.g., "hyperliquid")
105    pub exchange: String,
106
107    /// Market type: "perp", "spot", "hip3", or "outcome"
108    #[serde(rename = "type")]
109    pub market_type: String,
110
111    /// Base asset (e.g., "BTC")
112    pub base: String,
113
114    /// Quote asset (e.g., "USDC")
115    #[serde(default)]
116    pub quote: Option<String>,
117
118    /// Market index
119    #[serde(default)]
120    pub index: Option<u32>,
121
122    /// DEX name (for HIP-3)
123    #[serde(default)]
124    pub dex: Option<String>,
125
126    /// Human-readable outcome name (for prediction markets)
127    #[serde(default)]
128    pub name: Option<String>,
129
130    /// Outcome ID from outcomeMeta (for prediction markets)
131    #[serde(default)]
132    pub outcome_id: Option<u32>,
133
134    /// Outcome side: 0 = Yes, 1 = No
135    #[serde(default)]
136    pub side: Option<u8>,
137
138    /// Instrument metadata
139    #[serde(default)]
140    pub instrument_meta: Option<InstrumentMetaConfig>,
141}
142
143/// HIP-3 configuration
144#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
145pub struct Hip3ConfigJson {
146    /// The HIP-3 DEX name
147    pub dex_name: String,
148
149    /// The index of the DEX
150    pub dex_index: u32,
151
152    /// Quote currency: "USDC" or "USDH"
153    #[serde(default = "default_quote_currency")]
154    pub quote_currency: String,
155
156    /// Asset index within the DEX
157    #[serde(default)]
158    pub asset_index: u32,
159}
160
161/// Instrument metadata configuration
162#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
163pub struct InstrumentMetaConfig {
164    /// Tick size (price precision)
165    pub tick_size: String,
166
167    /// Lot size (quantity precision)
168    pub lot_size: String,
169
170    /// Minimum order quantity
171    #[serde(default)]
172    pub min_qty: Option<String>,
173
174    /// Minimum notional value
175    #[serde(default)]
176    pub min_notional: Option<String>,
177}
178
179// =============================================================================
180// Default value functions (only for CLI-specific types)
181// =============================================================================
182
183fn default_poll_delay_ms() -> u64 {
184    500
185}
186
187fn default_quote_currency() -> String {
188    "USDC".to_string()
189}