1pub use crate::cli::theme::{ColorPalette, ColorSchemeExt};
4use serde::{Deserialize, Serialize};
5use std::time::Instant;
6
7pub use scope::config::{
9 AlertConfig, ColorScheme, DEFAULT_MONITOR_REFRESH_SECS, ExportConfig, LayoutPreset,
10 MonitorConfig, ScaleMode, WidgetVisibility,
11};
12
13pub(crate) const MAX_DATA_AGE_SECS: f64 = 24.0 * 3600.0; pub(crate) const CACHE_FILE_PREFIX: &str = "bcc_monitor_";
21
22pub(crate) const DEFAULT_REFRESH_SECS: u64 = DEFAULT_MONITOR_REFRESH_SECS;
24
25pub(crate) const MIN_REFRESH_SECS: u64 = 1;
27
28pub(crate) const MAX_REFRESH_SECS: u64 = 60;
30
31#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
33pub struct DataPoint {
34 pub timestamp: f64,
36 pub value: f64,
38 pub is_real: bool,
40}
41
42#[derive(Debug, Clone, Copy)]
44pub struct OhlcCandle {
45 pub timestamp: f64,
47 pub open: f64,
49 pub high: f64,
51 pub low: f64,
53 pub close: f64,
55 pub is_bullish: bool,
57}
58
59impl OhlcCandle {
60 pub fn new(timestamp: f64, price: f64) -> Self {
62 Self {
63 timestamp,
64 open: price,
65 high: price,
66 low: price,
67 close: price,
68 is_bullish: true,
69 }
70 }
71
72 pub fn update(&mut self, price: f64) {
74 self.high = self.high.max(price);
75 self.low = self.low.min(price);
76 self.close = price;
77 self.is_bullish = self.close >= self.open;
78 }
79}
80
81#[derive(Debug, Serialize, Deserialize)]
83pub(crate) struct CachedMonitorData {
84 pub(crate) token_address: String,
86 pub(crate) chain: String,
88 pub(crate) price_history: Vec<DataPoint>,
90 pub(crate) volume_history: Vec<DataPoint>,
92 pub(crate) saved_at: f64,
94}
95
96#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub enum TimePeriod {
99 Min1,
101 Min5,
103 Min15,
105 Hour1,
107 Hour4,
109 Day1,
111}
112
113impl TimePeriod {
114 pub fn duration_secs(&self) -> i64 {
116 match self {
117 TimePeriod::Min1 => 60,
118 TimePeriod::Min5 => 5 * 60,
119 TimePeriod::Min15 => 15 * 60,
120 TimePeriod::Hour1 => 3600,
121 TimePeriod::Hour4 => 4 * 3600,
122 TimePeriod::Day1 => 24 * 3600,
123 }
124 }
125
126 pub fn label(&self) -> &'static str {
128 match self {
129 TimePeriod::Min1 => "1m",
130 TimePeriod::Min5 => "5m",
131 TimePeriod::Min15 => "15m",
132 TimePeriod::Hour1 => "1h",
133 TimePeriod::Hour4 => "4h",
134 TimePeriod::Day1 => "1d",
135 }
136 }
137
138 pub fn index(&self) -> usize {
140 match self {
141 TimePeriod::Min1 => 0,
142 TimePeriod::Min5 => 1,
143 TimePeriod::Min15 => 2,
144 TimePeriod::Hour1 => 3,
145 TimePeriod::Hour4 => 4,
146 TimePeriod::Day1 => 5,
147 }
148 }
149
150 pub fn exchange_interval(&self) -> &'static str {
152 match self {
153 TimePeriod::Min1 => "1m",
154 TimePeriod::Min5 => "5m",
155 TimePeriod::Min15 => "15m",
156 TimePeriod::Hour1 => "1h",
157 TimePeriod::Hour4 => "4h",
158 TimePeriod::Day1 => "1d",
159 }
160 }
161
162 pub fn next(&self) -> Self {
164 match self {
165 TimePeriod::Min1 => TimePeriod::Min5,
166 TimePeriod::Min5 => TimePeriod::Min15,
167 TimePeriod::Min15 => TimePeriod::Hour1,
168 TimePeriod::Hour1 => TimePeriod::Hour4,
169 TimePeriod::Hour4 => TimePeriod::Day1,
170 TimePeriod::Day1 => TimePeriod::Min1,
171 }
172 }
173}
174
175impl std::fmt::Display for TimePeriod {
176 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
177 write!(f, "{}", self.label())
178 }
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
183pub enum ChartMode {
184 #[default]
186 Line,
187 Candlestick,
189 VolumeProfile,
191}
192
193impl ChartMode {
194 pub fn next(&self) -> Self {
196 match self {
197 ChartMode::Line => ChartMode::Candlestick,
198 ChartMode::Candlestick => ChartMode::VolumeProfile,
199 ChartMode::VolumeProfile => ChartMode::Line,
200 }
201 }
202
203 pub fn label(&self) -> &'static str {
205 match self {
206 ChartMode::Line => "Line",
207 ChartMode::Candlestick => "Candle",
208 ChartMode::VolumeProfile => "VolPro",
209 }
210 }
211}
212
213#[derive(Debug, Clone)]
215pub struct ActiveAlert {
216 pub message: String,
218 pub triggered_at: Instant,
220}