Jelajahi Sumber

more linting fixes

Berke 1 tahun lalu
induk
melakukan
8fefaf9716

+ 15 - 15
src/charts/custom_line.rs

@@ -6,7 +6,7 @@ use iced::{
 use iced::widget::{Column, Row, Container, Text};
 use crate::{market_data::Kline, Timeframe};
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Copy)]
 pub enum Message {
     Translated(Vector),
     Scaled(f32, Option<Vector>),
@@ -87,7 +87,7 @@ impl CustomLine {
         }
     }
 
-    pub fn insert_datapoint(&mut self, kline: Kline) {
+    pub fn insert_datapoint(&mut self, kline: &Kline) {
         let time = match Utc.timestamp_opt(kline.time as i64 / 1000, 0) {
             LocalResult::Single(dt) => dt,
             _ => return, 
@@ -148,26 +148,26 @@ impl CustomLine {
         self.crosshair_cache.clear();
     }
 
-    pub fn update(&mut self, message: Message) {
+    pub fn update(&mut self, message: &Message) {
         match message {
             Message::Translated(translation) => {
                 if self.autoscale {
                     self.translation.x = translation.x;
                 } else {
-                    self.translation = translation;
+                    self.translation = *translation;
                 }
                 self.crosshair_position = Point::new(0.0, 0.0);
 
                 self.render_start();
             }
             Message::Scaled(scaling, translation) => {
-                self.scaling = scaling;
+                self.scaling = *scaling;
                 
                 if let Some(translation) = translation {
                     if self.autoscale {
                         self.translation.x = translation.x;
                     } else {
-                        self.translation = translation;
+                        self.translation = *translation;
                     }
                 }
                 self.crosshair_position = Point::new(0.0, 0.0);
@@ -175,7 +175,7 @@ impl CustomLine {
                 self.render_start();
             }
             Message::ChartBounds(bounds) => {
-                self.bounds = bounds;
+                self.bounds = *bounds;
             }
             Message::AutoscaleToggle => {
                 self.autoscale = !self.autoscale;
@@ -184,7 +184,7 @@ impl CustomLine {
                 self.crosshair = !self.crosshair;
             }
             Message::CrosshairMoved(position) => {
-                self.crosshair_position = position;
+                self.crosshair_position = *position;
                 if self.crosshair {
                     self.crosshair_cache.clear();
                     self.y_croshair_cache.clear();
@@ -237,7 +237,7 @@ impl CustomLine {
             .width(Length::Fill)
             .height(Length::Fill)
             .on_press(Message::AutoscaleToggle)
-            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, &_status, self.autoscale));
+            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, _status, self.autoscale));
         let crosshair_button = button(
             Text::new("+")
                 .size(12)
@@ -246,7 +246,7 @@ impl CustomLine {
             .width(Length::Fill)
             .height(Length::Fill)
             .on_press(Message::CrosshairToggle)
-            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, &_status, self.crosshair));
+            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, _status, self.crosshair));
     
         let chart_controls = Container::new(
             Row::new()
@@ -274,7 +274,7 @@ impl CustomLine {
     }
 }
 
-fn chart_button(_theme: &Theme, _status: &button::Status, is_active: bool) -> button::Style {
+fn chart_button(_theme: &Theme, _status: button::Status, is_active: bool) -> button::Style {
     button::Style {
         background: Some(Color::from_rgba8(20, 20, 20, 1.0).into()),
         border: Border {
@@ -499,7 +499,7 @@ impl canvas::Program<Message> for CustomLine {
                             Point::new(x_position as f32, bounds.height)
                         );
                         frame.stroke(&line, Stroke::default().with_color(Color::from_rgba8(27, 27, 27, 1.0)).with_width(1.0))
-                    }
+                    };
                     
                     time += time_step;
                 }
@@ -863,10 +863,10 @@ impl canvas::Program<Message> for AxisLabelYCanvas<'_> {
                     let y_position = candlesticks_area_height - ((y - self.min) / y_range * candlesticks_area_height);
 
                     let text_size = 12.0;
-                    let decimal_places = if step.fract() == 0.0 { 0 } else { 1 };
+                    let decimal_places = i32::from(step.fract() != 0.0);
                     let label_content = match decimal_places {
-                        0 => format!("{:.0}", y),
-                        _ => format!("{:.1}", y),
+                        0 => format!("{y:.0}"),
+                        _ => format!("{y:.1}"),
                     };
                     let label = canvas::Text {
                         content: label_content,

+ 15 - 15
src/charts/footprint.rs

@@ -6,7 +6,7 @@ use iced::{
 use iced::widget::{Column, Row, Container, Text};
 use crate::data_providers::binance::market_data::{Kline, Trade};
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Copy)]
 pub enum Message {
     Translated(Vector),
     Scaled(f32, Option<Vector>),
@@ -134,7 +134,7 @@ impl Footprint {
         let mut new_data_points = BTreeMap::new();
         let aggregate_time = 1000 * 60 * self.timeframe as i64;
 
-        for (time, (_, kline_values)) in self.data_points.iter() {
+        for (time, (_, kline_values)) in &self.data_points {
             new_data_points.entry(*time).or_insert((HashMap::new(), *kline_values));
         }
 
@@ -163,7 +163,7 @@ impl Footprint {
         self.tick_size = new_tick_size;
     }
 
-    pub fn update_latest_kline(&mut self, kline: Kline) {
+    pub fn update_latest_kline(&mut self, kline: &Kline) {
         if let Some((_, kline_value)) = self.data_points.get_mut(&(kline.time as i64)) {
             kline_value.0 = kline.open;
             kline_value.1 = kline.high;
@@ -216,26 +216,26 @@ impl Footprint {
         self.heatmap_cache.clear();     
     }
 
-    pub fn update(&mut self, message: Message) {
+    pub fn update(&mut self, message: &Message) {
         match message {
             Message::Translated(translation) => {
                 if self.autoscale {
                     self.translation.x = translation.x;
                 } else {
-                    self.translation = translation;
+                    self.translation = *translation;
                 }
                 self.crosshair_position = Point::new(0.0, 0.0);
 
                 self.render_start();
             }
             Message::Scaled(scaling, translation) => {
-                self.scaling = scaling;
+                self.scaling = *scaling;
                 
                 if let Some(translation) = translation {
                     if self.autoscale {
                         self.translation.x = translation.x;
                     } else {
-                        self.translation = translation;
+                        self.translation = *translation;
                     }
                 }
                 self.crosshair_position = Point::new(0.0, 0.0);
@@ -243,7 +243,7 @@ impl Footprint {
                 self.render_start();
             }
             Message::ChartBounds(bounds) => {
-                self.bounds = bounds;
+                self.bounds = *bounds;
             }
             Message::AutoscaleToggle => {
                 self.autoscale = !self.autoscale;
@@ -252,7 +252,7 @@ impl Footprint {
                 self.crosshair = !self.crosshair;
             }
             Message::CrosshairMoved(position) => {
-                self.crosshair_position = position;
+                self.crosshair_position = *position;
                 if self.crosshair {
                     self.crosshair_cache.clear();
                     self.y_croshair_cache.clear();
@@ -300,7 +300,7 @@ impl Footprint {
             .width(Length::Fill)
             .height(Length::Fill)
             .on_press(Message::AutoscaleToggle)
-            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, &_status, self.autoscale));
+            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, _status, self.autoscale));
         let crosshair_button = button(
             Text::new("+")
                 .size(12)
@@ -309,7 +309,7 @@ impl Footprint {
             .width(Length::Fill)
             .height(Length::Fill)
             .on_press(Message::CrosshairToggle)
-            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, &_status, self.crosshair));
+            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, _status, self.crosshair));
     
         let chart_controls = Container::new(
             Row::new()
@@ -337,7 +337,7 @@ impl Footprint {
     }
 }
 
-fn chart_button(_theme: &Theme, _status: &button::Status, is_active: bool) -> button::Style {
+fn chart_button(_theme: &Theme, _status: button::Status, is_active: bool) -> button::Style {
     button::Style {
         background: Some(Color::from_rgba8(20, 20, 20, 1.0).into()),
         border: Border {
@@ -593,7 +593,7 @@ impl canvas::Program<Message> for Footprint {
             } 
             
             let text_size = 9.0;
-            let text_content = format!("{:.2}", max_volume);
+            let text_content = format!("{max_volume:.2}");
             let text_width = (text_content.len() as f32 * text_size) / 1.5;
 
             let text_position = Point::new(bounds.width - text_width, bounds.height - volume_area_height);
@@ -949,8 +949,8 @@ impl canvas::Program<Message> for AxisLabelYCanvas<'_> {
                     let y_position = candlesticks_area_height - ((y - self.min) / y_range * candlesticks_area_height);
 
                     let text_size = 12.0;
-                    let decimal_places = if step < 0.5 { 2 } else if step < 1.0 { 1 } else { 0 };
-                    let label_content = format!("{:.*}", decimal_places, y);
+                    let decimal_places = if step < 0.5 { 2 } else { usize::from(step < 1.0) };
+                    let label_content = format!("{y:.decimal_places$}");
                     let label = canvas::Text {
                         content: label_content,
                         position: Point::new(10.0, y_position - text_size / 2.0),

+ 22 - 23
src/charts/heatmap.rs

@@ -6,7 +6,7 @@ use iced::{
 use iced::widget::{Column, Row, Container, Text};
 use crate::data_providers::binance::market_data::{Trade, Depth};
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Copy)]
 pub enum Message {
     Translated(Vector),
     Scaled(f32, Option<Vector>),
@@ -97,7 +97,7 @@ impl Heatmap {
     pub fn get_raw_trades(&mut self) -> Vec<Trade> {
         let mut trades_source = vec![];
 
-        for (_, (_, trades, _)) in self.data_points.iter() {
+        for (_, (_, trades, _)) in &self.data_points {
             trades_source.extend(trades.iter().cloned());
         }
 
@@ -140,26 +140,26 @@ impl Heatmap {
         self.crosshair_cache.clear();        
     }
 
-    pub fn update(&mut self, message: Message) {
+    pub fn update(&mut self, message: &Message) {
         match message {
             Message::Translated(translation) => {
                 if self.autoscale {
                     self.translation.x = translation.x;
                 } else {
-                    self.translation = translation;
+                    self.translation = *translation;
                 }
                 self.crosshair_position = Point::new(0.0, 0.0);
 
                 self.render_start();
             }
             Message::Scaled(scaling, translation) => {
-                self.scaling = scaling;
+                self.scaling = *scaling;
                 
                 if let Some(translation) = translation {
                     if self.autoscale {
                         self.translation.x = translation.x;
                     } else {
-                        self.translation = translation;
+                        self.translation = *translation;
                     }
                 }
                 self.crosshair_position = Point::new(0.0, 0.0);
@@ -167,7 +167,7 @@ impl Heatmap {
                 self.render_start();
             }
             Message::ChartBounds(bounds) => {
-                self.bounds = bounds;
+                self.bounds = *bounds;
             }
             Message::AutoscaleToggle => {
                 self.autoscale = !self.autoscale;
@@ -176,7 +176,7 @@ impl Heatmap {
                 self.crosshair = !self.crosshair;
             }
             Message::CrosshairMoved(position) => {
-                self.crosshair_position = position;
+                self.crosshair_position = *position;
                 if self.crosshair {
                     self.crosshair_cache.clear();
                     self.y_croshair_cache.clear();
@@ -223,7 +223,7 @@ impl Heatmap {
             .width(Length::Fill)
             .height(Length::Fill)
             .on_press(Message::AutoscaleToggle)
-            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, &_status, self.autoscale));
+            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, _status, self.autoscale));
         let crosshair_button = button(
             Text::new("+")
                 .size(12)
@@ -232,7 +232,7 @@ impl Heatmap {
             .width(Length::Fill)
             .height(Length::Fill)
             .on_press(Message::CrosshairToggle)
-            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, &_status, self.crosshair));
+            .style(|_theme: &Theme, _status: iced::widget::button::Status| chart_button(_theme, _status, self.crosshair));
     
         let chart_controls = Container::new(
             Row::new()
@@ -260,7 +260,7 @@ impl Heatmap {
     }
 }
 
-fn chart_button(_theme: &Theme, _status: &button::Status, is_active: bool) -> button::Style {
+fn chart_button(_theme: &Theme, _status: button::Status, is_active: bool) -> button::Style {
     button::Style {
         background: Some(Color::from_rgba8(20, 20, 20, 1.0).into()),
         border: Border {
@@ -472,10 +472,9 @@ impl canvas::Program<Message> for Heatmap {
                                 Color::from_rgba8(81, 205, 160, 1.0)
                             };
 
-                            let radius: f32 = if max_trade_qty != min_trade_qty {
-                                1.0 + (trade.qty - min_trade_qty) * (35.0 - 1.0) / (max_trade_qty - min_trade_qty)
-                            } else {
-                                1.0
+                            let radius: f32 = match max_trade_qty == min_trade_qty {
+                                true => 1.0,
+                                false => 1.0 + (trade.qty - min_trade_qty) * (35.0 - 1.0) / (max_trade_qty - min_trade_qty),
                             };
 
                             let circle = Path::circle(Point::new(x_position as f32, y_position), radius);
@@ -528,7 +527,7 @@ impl canvas::Program<Message> for Heatmap {
 
                 let x_position = ((latest_timestamp - earliest) as f32 / (latest - earliest) as f32) * bounds.width;
 
-                for (price, qty) in latest_bids.iter() {     
+                for (price, qty) in &latest_bids {     
                     let y_position = heatmap_area_height - ((price - lowest) / y_range * heatmap_area_height);
 
                     let bar_width = (qty / max_qty) * depth_area_width;
@@ -538,7 +537,7 @@ impl canvas::Program<Message> for Heatmap {
                     );
                     frame.fill(&bar, Color::from_rgba8(0, 144, 144, 0.5));
                 }
-                for (price, qty) in latest_asks.iter() {
+                for (price, qty) in &latest_asks {
                     let y_position = heatmap_area_height - ((price - lowest) / y_range * heatmap_area_height);
 
                     let bar_width = (qty / max_qty) * depth_area_width; 
@@ -556,7 +555,7 @@ impl canvas::Program<Message> for Heatmap {
                 frame.stroke(&line, Stroke::default().with_color(Color::from_rgba8(100, 100, 100, 0.1)).with_width(1.0));
 
                 let text_size = 9.0;
-                let text_content = format!("{:.2}", max_qty);
+                let text_content = format!("{max_qty:.2}");
                 let text_position = Point::new(x_position + depth_area_width, 0.0);
                 frame.fill_text(canvas::Text {
                     content: text_content,
@@ -566,7 +565,7 @@ impl canvas::Program<Message> for Heatmap {
                     ..canvas::Text::default()
                 });
 
-                let text_content = format!("{:.2}", max_volume);
+                let text_content = format!("{max_volume:.2}");
                 if x_position > bounds.width {      
                     let text_width = (text_content.len() as f32 * text_size) / 1.5;
 
@@ -694,7 +693,7 @@ fn calculate_time_step(earliest: i64, latest: i64, labels_can_fit: i32) -> (i64,
     let duration = latest - earliest;
 
     let mut selected_step = TIME_STEPS[0];
-    for &step in TIME_STEPS.iter() {
+    for &step in &TIME_STEPS {
         if duration / step >= labels_can_fit as i64 {
             selected_step = step;
             break;
@@ -790,7 +789,7 @@ impl canvas::Program<Message> for AxisLabelXCanvas<'_> {
                 let snap_x = snap_ratio * bounds.width as f64;
 
                 let text_size = 12.0;
-                let text_content = crosshair_time.format("%M:%S:%3f").to_string().replace(".", "");
+                let text_content = crosshair_time.format("%M:%S:%3f").to_string().replace('.', "");
                 let growth_amount = 6.0; 
                 let rectangle_position = Point::new(snap_x as f32 - 26.0 - growth_amount, bounds.height - 20.0);
                 let text_position = Point::new(snap_x as f32 - 26.0, bounds.height - 20.0);
@@ -881,8 +880,8 @@ impl canvas::Program<Message> for AxisLabelYCanvas<'_> {
                     let y_position = candlesticks_area_height - ((y - self.min) / y_range * candlesticks_area_height);
 
                     let text_size = 12.0;
-                    let decimal_places = if step < 0.5 { 2 } else if step < 1.0 { 1 } else { 0 };
-                    let label_content = format!("{:.*}", decimal_places, y);
+                    let decimal_places = if step < 0.5 { 2 } else { usize::from(step < 1.0) };
+                    let label_content = format!("{y:.decimal_places$}");
                     let label = canvas::Text {
                         content: label_content,
                         position: Point::new(10.0, y_position - text_size / 2.0),

+ 22 - 36
src/data_providers/binance/market_data.rs

@@ -48,30 +48,23 @@ pub fn connect_market_stream(selected_ticker: Ticker) -> Subscription<Event> {
                 Ticker::LTCUSDT => "ltcusdt",
             };
 
-            let stream_1 = format!("{}@aggTrade", symbol_str);
-            let stream_2 = format!("{}@depth20@100ms", symbol_str);
+            let stream_1 = format!("{symbol_str}@aggTrade");
+            let stream_2 = format!("{symbol_str}@depth20@100ms");
             
             loop {
                 match &mut state {
                     State::Disconnected => {        
-                        let websocket_server = format!("wss://fstream.binance.com/stream?streams={}/{}", stream_1, stream_2);
+                        let websocket_server = format!("wss://fstream.binance.com/stream?streams={stream_1}/{stream_2}");
 
-                        match async_tungstenite::tokio::connect_async(
+                        if let Ok((websocket, _)) = async_tungstenite::tokio::connect_async(
                             websocket_server,
                         )
-                        .await
-                        {
-                            Ok((websocket, _)) => {
-                                state = State::Connected(websocket);
-                            }
-                            Err(_) => {
-                                tokio::time::sleep(
-                                    tokio::time::Duration::from_secs(1),
-                                )
-                                .await;
-
-                                let _ = output.send(Event::Disconnected).await;
-                            }
+                        .await {
+                           state = State::Connected(websocket);
+                        } else {
+                            tokio::time::sleep(tokio::time::Duration::from_secs(1))
+                           .await;
+                           let _ = output.send(Event::Disconnected).await;
                         }
                     }
                     State::Connected(websocket) => {
@@ -81,7 +74,7 @@ pub fn connect_market_stream(selected_ticker: Ticker) -> Subscription<Event> {
                             received = fused_websocket.select_next_some() => {
                                 match received {
                                     Ok(tungstenite::Message::Text(message)) => {
-                                        let stream: Stream = serde_json::from_str(&message).unwrap_or(Stream { stream: "".to_string() });
+                                        let stream: Stream = serde_json::from_str(&message).unwrap_or(Stream { stream: String::new() });
                                         if stream.stream == stream_1 {
                                             let agg_trade: AggTrade = serde_json::from_str(&message).unwrap();
                                             trades_buffer.push(agg_trade.data);
@@ -140,30 +133,23 @@ pub fn connect_kline_stream(vec: Vec<(Ticker, Timeframe)>) -> Subscription<Event
                     Timeframe::M15 => "15m",
                     Timeframe::M30 => "30m",
                 };
-                format!("{}@kline_{}", symbol_str, timeframe_str)
+                format!("{symbol_str}@kline_{timeframe_str}")
             }).collect::<Vec<String>>().join("/");
  
             loop {
                 match &mut state {
                     State::Disconnected => {
-                        let websocket_server = format!("wss://fstream.binance.com/stream?streams={}", stream_str);
+                        let websocket_server = format!("wss://fstream.binance.com/stream?streams={stream_str}");
                         
-                        match async_tungstenite::tokio::connect_async(
+                        if let Ok((websocket, _)) = async_tungstenite::tokio::connect_async(
                             websocket_server,
                         )
-                        .await
-                        {
-                            Ok((websocket, _)) => {
-                                state = State::Connected(websocket);
-                            }
-                            Err(_) => {
-                                tokio::time::sleep(
-                                    tokio::time::Duration::from_secs(1),
-                                )
-                                .await;
-
-                                let _ = output.send(Event::Disconnected).await;
-                            }
+                        .await {
+                           state = State::Connected(websocket);
+                        } else {
+                            tokio::time::sleep(tokio::time::Duration::from_secs(1))
+                           .await;
+                           let _ = output.send(Event::Disconnected).await;
                         }
                     }
                     State::Connected(websocket) => {
@@ -274,7 +260,7 @@ impl<'de> Deserialize<'de> for Order {
     }
 }
 
-#[derive(Deserialize, Debug, Clone)]
+#[derive(Deserialize, Debug, Clone, Copy)]
 pub struct Kline {
     #[serde(rename = "t")]
     pub time: u64,
@@ -334,7 +320,7 @@ pub async fn fetch_klines(ticker: Ticker, timeframe: Timeframe) -> Result<Vec<Kl
         Timeframe::M30 => "30m",
     };
 
-    let url = format!("https://fapi.binance.com/fapi/v1/klines?symbol={}&interval={}&limit=720", symbol_str, timeframe_str);
+    let url = format!("https://fapi.binance.com/fapi/v1/klines?symbol={symbol_str}&interval={timeframe_str}&limit=720");
 
     let response = reqwest::get(&url).await?;
     let text = response.text().await?;

+ 18 - 24
src/data_providers/binance/user_data.rs

@@ -68,23 +68,17 @@ pub fn connect_user_stream(listen_key: String) -> Subscription<Event> {
                             listen_key
                         );
         
-                        match async_tungstenite::tokio::connect_async(
+                        if let Ok((websocket, _)) = async_tungstenite::tokio::connect_async(
                             websocket_server,
                         )
-                        .await
-                        {
-                            Ok((websocket, _)) => {
-                                state = State::Connected(websocket);
-                                dbg!("Connected to user stream");
-                            }
-                            Err(_) => {
-                                tokio::time::sleep(
-                                    tokio::time::Duration::from_secs(1),
-                                )
-                                .await;
-                                dbg!("Failed to connect to user stream");
-                                let _ = output.send(Event::Disconnected).await;
-                            }
+                        .await {
+                            state = State::Connected(websocket);
+                            dbg!("Connected to user stream");
+                        } else {
+                            tokio::time::sleep(tokio::time::Duration::from_secs(1))
+                            .await;
+                            dbg!("Failed to connect to user stream");
+                            let _ = output.send(Event::Disconnected).await;
                         }
                     }
                     State::Connected(websocket) => {
@@ -102,7 +96,7 @@ pub fn connect_user_stream(listen_key: String) -> Subscription<Event> {
                                                     if let Some(account_update) = data["a"].as_object() {
                                                         let account_update: AccountUpdate = serde_json::from_value(json!(account_update)).unwrap();
                                                         if account_update.event_type == "ORDER" {
-                                                            event = Event::NewPositions(account_update.positions)
+                                                            event = Event::NewPositions(account_update.positions);
                                                         } else {
                                                             event = Event::TestEvent("Account Update".to_string());
                                                         }
@@ -173,7 +167,7 @@ pub fn fetch_user_stream(api_key: &str, secret_key: &str) -> Subscription<Event>
                             let _ = output.send(Event::FetchedPositions(positions)).await;
                         }
                         Err(e) => {
-                            eprintln!("Error fetching positions: {:?}", e);
+                            eprintln!("Error fetching positions: {e:?}");
                         }
                     }
 
@@ -182,7 +176,7 @@ pub fn fetch_user_stream(api_key: &str, secret_key: &str) -> Subscription<Event>
                             let _ = output.send(Event::FetchedBalance(balance)).await;
                         }
                         Err(e) => {
-                            eprintln!("Error fetching balance: {:?}", e);
+                            eprintln!("Error fetching balance: {e:?}");
                         }
                     }
 
@@ -368,7 +362,7 @@ pub async fn create_market_order (side: String, qty: String, api_key: &str, secr
     let params = format!("symbol=BTCUSDT&side={}&type=MARKET&quantity={}&timestamp={}", side, qty, Utc::now().timestamp_millis());
     let signature = sign_params(&params, secret_key);
 
-    let url = format!("https://testnet.binancefuture.com/fapi/v1/order?{}&signature={}", params, signature);
+    let url = format!("https://testnet.binancefuture.com/fapi/v1/order?{params}&signature={signature}");
 
     let mut headers = HeaderMap::new();
     headers.insert("X-MBX-APIKEY", HeaderValue::from_str(api_key).unwrap());
@@ -389,7 +383,7 @@ pub async fn cancel_order(order_id: String, api_key: &str, secret_key: &str) ->
     let params = format!("symbol=BTCUSDT&orderId={}&timestamp={}", order_id, Utc::now().timestamp_millis());
     let signature = sign_params(&params, secret_key);
 
-    let url = format!("https://testnet.binancefuture.com/fapi/v1/order?{}&signature={}", params, signature);
+    let url = format!("https://testnet.binancefuture.com/fapi/v1/order?{params}&signature={signature}");
 
     let mut headers = HeaderMap::new();
     headers.insert("X-MBX-APIKEY", HeaderValue::from_str(api_key).unwrap());
@@ -409,7 +403,7 @@ pub async fn fetch_open_orders(symbol: String, api_key: &str, secret_key: &str)
     let params = format!("timestamp={}&symbol={}", Utc::now().timestamp_millis(), symbol);
     let signature = sign_params(&params, secret_key);
 
-    let url = format!("https://testnet.binancefuture.com/fapi/v1/openOrders?{}&signature={}", params, signature);
+    let url = format!("https://testnet.binancefuture.com/fapi/v1/openOrders?{params}&signature={signature}");
 
     let mut headers = HeaderMap::new();
     headers.insert("X-MBX-APIKEY", HeaderValue::from_str(api_key).unwrap());
@@ -425,7 +419,7 @@ pub async fn fetch_open_positions(api_key: &str, secret_key: &str) -> Result<Vec
     let params = format!("timestamp={}", Utc::now().timestamp_millis());
     let signature = sign_params(&params, secret_key);
 
-    let url = format!("https://testnet.binancefuture.com/fapi/v2/positionRisk?{}&signature={}", params, signature);
+    let url = format!("https://testnet.binancefuture.com/fapi/v2/positionRisk?{params}&signature={signature}");
 
     let mut headers = HeaderMap::new();
     headers.insert("X-MBX-APIKEY", HeaderValue::from_str(api_key).unwrap());
@@ -442,7 +436,7 @@ pub async fn fetch_acc_balance(api_key: &str, secret_key: &str) -> Result<Vec<Fe
     let params = format!("timestamp={}", Utc::now().timestamp_millis());
     let signature = sign_params(&params, secret_key);
 
-    let url = format!("https://testnet.binancefuture.com/fapi/v2/balance?{}&signature={}", params, signature);
+    let url = format!("https://testnet.binancefuture.com/fapi/v2/balance?{params}&signature={signature}");
 
     let mut headers = HeaderMap::new();
     headers.insert("X-MBX-APIKEY", HeaderValue::from_str(api_key).unwrap());
@@ -458,7 +452,7 @@ pub async fn get_listen_key(api_key: &str, secret_key: &str) -> Result<String, B
     let params = format!("timestamp={}", Utc::now().timestamp_millis());
     let signature = sign_params(&params, secret_key);
 
-    let url = format!("https://testnet.binancefuture.com/fapi/v1/listenKey?{}&signature={}", params, signature);
+    let url = format!("https://testnet.binancefuture.com/fapi/v1/listenKey?{params}&signature={signature}");
 
     let mut headers = HeaderMap::new();
     headers.insert("X-MBX-APIKEY", HeaderValue::from_str(api_key).unwrap());

+ 36 - 44
src/main.rs

@@ -344,25 +344,25 @@ impl Application for State {
         match message {
             Message::CustomLine(message) => {
                 if let Some(custom_line) = &mut self.custom_line {
-                    custom_line.update(message);
+                    custom_line.update(&message);
                 }
                 Command::none()
             },
             Message::Candlestick(message) => {
                 if let Some(candlesticks) = &mut self.candlestick_chart {
-                    candlesticks.update(message);
+                    candlesticks.update(&message);
                 }
                 Command::none()
             },
             Message::Heatmap(message) => {
                 if let Some(heatmap) = &mut self.heatmap_chart {
-                    heatmap.update(message);
+                    heatmap.update(&message);
                 }
                 Command::none()
             },
             Message::Footprint(message) => {
                 if let Some(footprint) = &mut self.footprint_chart {
-                    footprint.update(message);
+                    footprint.update(&message);
                 }
                 Command::none()
             },
@@ -383,13 +383,11 @@ impl Application for State {
                     return Command::none();
                 }
 
-                let selected_ticker = match &self.selected_ticker {
-                    Some(ticker) => ticker,
-                    None => {
-                        eprintln!("No ticker selected");
-                        return Command::none();
-                    }
+                let Some(selected_ticker) = &self.selected_ticker else {
+                    eprintln!("No ticker selected");
+                    return Command::none();
                 };
+
                 self.kline_stream = false;
                 
                 let mut commands = vec![];
@@ -402,7 +400,7 @@ impl Application for State {
                         let pane_id = pane.id;
                         let fetch_klines = Command::perform(
                         market_data::fetch_klines(*selected_ticker, timeframe)
-                            .map_err(|err| format!("{}", err)), 
+                            .map_err(|err| format!("{err}")), 
                         move |klines| {
                             Message::FetchEvent(klines, pane_id)
                         });
@@ -418,7 +416,7 @@ impl Application for State {
                     async {
                         tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
                     },
-                    move |_| Message::CutTheKlineStream
+                    move |()| Message::CutTheKlineStream
                 );
                 commands.push(remove_active_stream);
 
@@ -460,25 +458,21 @@ impl Application for State {
                         }
 
                         let selected_ticker = match stream_type {
-                            Some(StreamType::DepthAndTrades(ticker)) => ticker,
-                            Some(StreamType::Klines(ticker, _)) => ticker,
+                            Some(StreamType::Klines(ticker, _)) | Some(StreamType::DepthAndTrades(ticker)) => ticker,
                             _ => {
                                 dbg!("No ticker selected", pane_id);
                                 continue; 
                             }
                         };
-                        let selected_timeframe = match stream_type {
-                            Some(StreamType::Klines(_, timeframe)) => timeframe,
-                            _ => {
-                                dbg!("No timeframe selected", pane_id);
-                                continue;   
-                            }
+                        let Some(StreamType::Klines(_, selected_timeframe)) = stream_type else {
+                            dbg!("No timeframe selected", pane_id);
+                            continue;  
                         };
 
                         let pane_id = *pane_id;
                         let fetch_klines = Command::perform(
                             market_data::fetch_klines(*selected_ticker, *selected_timeframe)
-                                .map_err(|err| format!("{}", err)), 
+                                .map_err(|err| format!("{err}")), 
                             move |klines| {
                                 Message::FetchEvent(klines, pane_id)
                             }
@@ -523,7 +517,7 @@ impl Application for State {
                                         }
 
                                         // get the latest 20 klines
-                                        let copied_klines = klines_raw.iter().rev().take(20).rev().cloned().collect::<Vec<(i64, f32, f32, f32, f32, f32, f32)>>();
+                                        let copied_klines = klines_raw.iter().rev().take(20).rev().copied().collect::<Vec<(i64, f32, f32, f32, f32, f32, f32)>>();
 
                                         let timeframe_u16: u16 = match timeframe {
                                             Timeframe::M1 => 1,
@@ -541,7 +535,7 @@ impl Application for State {
                         }
                     },
                     Err(err) => {
-                        eprintln!("Error fetching klines: {}", err);
+                        eprintln!("Error fetching klines: {err}");
                         self.candlestick_chart = Some(CustomLine::new(vec![], Timeframe::M1)); 
                     },
                 }
@@ -576,17 +570,17 @@ impl Application for State {
                                     match pane_id {
                                         PaneId::CandlestickChart => {
                                             if let Some(candlestick_chart) = &mut self.candlestick_chart {
-                                                candlestick_chart.insert_datapoint(kline.clone());
+                                                candlestick_chart.insert_datapoint(&kline);
                                             }
                                         },
                                         PaneId::CustomChart => {
                                             if let Some(custom_line) = &mut self.custom_line {
-                                                custom_line.insert_datapoint(kline.clone());
+                                                custom_line.insert_datapoint(&kline);
                                             }
                                         },
                                         PaneId::FootprintChart => {
                                             if let Some(footprint_chart) = &mut self.footprint_chart {
-                                                footprint_chart.update_latest_kline(kline.clone());
+                                                footprint_chart.update_latest_kline(&kline);
                                             }
                                         },
                                         _ => {}
@@ -624,13 +618,10 @@ impl Application for State {
                 if Some(focus_pane).is_some() {
                     self.focus = focus_pane;
 
-                    let selected_ticker = match &self.selected_ticker {
-                        Some(ticker) => ticker,
-                        None => {
+                    let Some(selected_ticker) = &self.selected_ticker else {
                             eprintln!("No ticker selected");
                             return Command::none();
-                        }
-                    };
+                        };
                     
                     if pane_id == PaneId::TimeAndSales {
                         self.time_and_sales = Some(TimeAndSales::new());
@@ -718,7 +709,7 @@ impl Application for State {
             },
 
             Message::Debug(msg) => {
-                println!("{}", msg);
+                println!("{msg}");
                 Command::none()
             },
             Message::FontLoaded(_) => {
@@ -914,7 +905,10 @@ impl Application for State {
             .align_items(Alignment::Center)
             .push(ws_button);
 
-        if !self.ws_running {
+        if self.ws_running {
+            ws_controls = ws_controls.push(
+                Text::new(self.selected_ticker.unwrap_or_else(|| { dbg!("No ticker found"); Ticker::BTCUSDT } ).to_string()).size(20));
+        } else {
             let symbol_pick_list = pick_list(
                 &Ticker::ALL[..],
                 self.selected_ticker,
@@ -926,14 +920,10 @@ impl Application for State {
                 self.selected_exchange,
                 Message::ExchangeSelected,
             ).placeholder("Choose an exchange...");
-        
+
             ws_controls = ws_controls
                 .push(exchange_selector)
-                .push(symbol_pick_list)
-                
-        } else {
-            ws_controls = ws_controls.push(
-                Text::new(self.selected_ticker.unwrap_or_else(|| { dbg!("No ticker found"); Ticker::BTCUSDT } ).to_string()).size(20));
+                .push(symbol_pick_list);
         }
 
         let content = Column::new()
@@ -1125,7 +1115,7 @@ fn view_content<'a, 'b: 'a>(
                                         .step(500.0)
                                 )
                                 .push(
-                                    Text::new(format!("${}", size_filter_heatmap)).size(16)
+                                    Text::new(format!("${size_filter_heatmap}")).size(16)
                                 )
                         )
                         .push( 
@@ -1197,11 +1187,13 @@ fn view_content<'a, 'b: 'a>(
         },
         
         PaneId::TimeAndSales => { 
-            let underlay = time_and_sales.as_ref().map(TimeAndSales::view)
-                .unwrap_or_else(|| Text::new("No data")
+            let underlay = time_and_sales.as_ref().map_or_else(
+                || Text::new("No data")
                     .width(Length::Fill)
                     .height(Length::Fill)
-                    .into()); 
+                    .into(),
+                TimeAndSales::view
+            );
 
             if show_modal {
                 let signup = container(
@@ -1221,7 +1213,7 @@ fn view_content<'a, 'b: 'a>(
                                         .step(500.0)
                                 )
                                 .push(
-                                    Text::new(format!("${}", size_filter_timesales)).size(16)
+                                    Text::new(format!("${size_filter_timesales}")).size(16)
                                 )
                                 .push(
                                     checkbox("Sync Heatmap with", sync_heatmap)