diff --git a/example.rs b/example.rs new file mode 100644 index 0000000..1a8ee8b --- /dev/null +++ b/example.rs @@ -0,0 +1,151 @@ +// This is an example file of how rustygram can be integrated easily into your trading systems. +// This example uses execution on Binance +// In `.env` - `TELEGRAM_BOT_TOKEN` and `TELEGRAM_CHAT_ID` has to be declared first. + +use std::env; + +use chrono::DateTime; +use chrono_tz::Tz; +use dotenv::dotenv; +use rustygram::bot::Bot; + +pub struct TradeSuccessNotification { + pub listing_id: u32, + pub ticker: String, + pub market_buy_qty: f64, + pub market_buy_price: f64, + pub stop_loss_price: f64, + pub take_profit_price: f64, + pub timestamp: DateTime, +} + +impl TradeSuccessNotification { + fn craft_message(&self) -> String { + format!( + "listing ID: {}\nTicker: {}\nMarket Buy at {}qty at ${}\nStop loss: {}\nTake profit: {}\n{}", + self.listing_id, + self.ticker, + self.market_buy_qty, + self.market_buy_price, + self.stop_loss_price, + self.take_profit_price, + self.timestamp + ) + } +} + +pub struct TradeFailureNotification { + pub listing_id: u32, + pub ticker: String, + pub timestamp: DateTime, + pub error: String, +} + +impl TradeFailureNotification { + fn craft_message(&self) -> String { + format!( + "Listing ID: {}\nExecution failed for {} due to Error: {}\n{}", + self.listing_id, self.ticker, self.error, self.timestamp + ) + } +} + +pub async fn send_success_notification(bot: &Bot, message: &TradeSuccessNotification) { + let message = message.craft_message(); + let _ = bot.send_message(&message, None).await; +} + +pub async fn send_failure_notification(bot: &Bot, message: &TradeFailureNotification) { + let message = message.craft_message(); + let _ = bot.send_message(&message, None).await; +} + +pub async fn send_network_client_failure_notification(bot: &Bot, error: &str) { + let message = format!("Network client failed with error: {}", error); + let _ = bot.send_message(&message, None).await; +} + +/// Create a new bot using the Telegram bot token and chat ID from the environment variables. +/// +/// # Example +/// +/// ```no_run +/// use notifications::notifications::create_bot; +/// +/// # fn main() -> Result<(), Box> { +/// // Assuming the environment variables are set +/// let bot = create_bot(); +/// # Ok(()) +/// # } +/// ``` +pub fn create_bot() -> Bot { + dotenv().ok(); + let token = env::var("TELEGRAM_BOT_TOKEN") + .unwrap_or_else(|_| "".to_string()); + let chat_id = env::var("TELEGRAM_CHAT_ID").unwrap_or_else(|_| "".to_string()); + Bot::new(token, chat_id) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_trade_success_notification_craft_message() { + let time = chrono::DateTime::parse_from_rfc3339("2020-12-31T23:59:59.999999999Z").unwrap(); + let singapore_time = time.with_timezone(&chrono_tz::Singapore); + let notification = TradeSuccessNotification { + listing_id: 1, + ticker: "BTC".to_string(), + market_buy_qty: 0.1, + market_buy_price: 10000.0, + stop_loss_price: 9000.0, + take_profit_price: 11000.0, + timestamp: singapore_time, + }; + + let message = notification.craft_message(); + assert_eq!( + message, + "listing ID: 1\nTicker: BTC\nMarket Buy at 0.1qty at $10000\nStop loss: 9000\nTake profit: 11000\n2021-01-01 07:59:59.999999999 +08" + ); + } + + #[test] + fn test_trade_failure_notification_craft_message() { + let time = chrono::DateTime::parse_from_rfc3339("2020-12-31T23:59:59.999999999Z").unwrap(); + let singapore_time = time.with_timezone(&chrono_tz::Singapore); + + let notification = TradeFailureNotification { + listing_id: 1, + ticker: "BTC".to_string(), + timestamp: singapore_time, + error: "Insufficient funds".to_string(), + }; + + let message = notification.craft_message(); + assert_eq!( + message, + "listing ID: 1\nExecution failed for BTC due to Error: Insufficient funds\n2021-01-01 07:59:59.999999999 +08" + ); + } + + #[tokio::test] + #[ignore] + async fn test_send_success_notification() { + let bot = create_bot(); + let time = chrono::DateTime::parse_from_rfc3339("2020-12-31T23:59:59.999999999Z").unwrap(); + let singapore_time = time.with_timezone(&chrono_tz::Singapore); + let notification = TradeSuccessNotification { + listing_id: 1, + ticker: "BTC".to_string(), + market_buy_qty: 0.1, + market_buy_price: 10000.0, + stop_loss_price: 9000.0, + take_profit_price: 11000.0, + timestamp: singapore_time, + }; + + send_success_notification(&bot, ¬ification).await; + } +}