kalshi_rust/lib.rs
1//! An HTTPS and Websocket wrapper that allows users to write trading bots for the [Kalshi events trading platform](https://kalshi.com).
2//!
3//! kalshi-rust is asynchronous, performant, and succint. Dash past verbose and annoying HTTPS requests
4//! and use this wrapper to quickly write blazingly fast trading bots in Rust!
5//!
6//! As of version 0.9.0, HTTPS features are fully complete but websocket support and advanced API access features are not complete.
7//! If you'd like to keep up on kalshi-rust's development, report bugs, or view a sample trading script,
8//! feel free to visit the [github](https://github.com/dpeachpeach/kalshi-rust)!
9//! A star would also be greatly appreciated, I'm a student developer writing this for free and any recognition is incredibly helpful!
10//!
11//! ## The Kalshi Struct
12//!
13//! The [`Kalshi`] struct is the central component of this crate.
14//! All authentication, order routing, market requests, and position snapshots are handled through the struct and its methods.
15//!
16//! For more details, see [`Kalshi`].
17//!
18//! For a quick tutorial / beginners guide, jump [here](#quick-start-guide).
19//!
20//! ### Initializing the Kalshi struct in demo mode.
21//! ```
22//! use kalshi::Kalshi;
23//! use kalshi::TradingEnvironment;
24//!
25//! let kalshi_instance = Kalshi::new(TradingEnvironment::DemoMode, "your-key-id", "path/to/private.pem").await?;
26//! ```
27//!
28//! ## Quick Start Guide
29//!
30//! First, list the Kalshi struct as a dependency in your crate.
31//!
32//! ```toml
33//! kalshi = { version = "0.9"}
34//! ```
35//!
36//! Initialize the Kalshi Struct with key-based authentication:
37//! - **IMPORTANT**: The authentication is handled automatically when creating a new instance.
38//! - Store your key ID and private key file securely, an implementation of extracting these from local environmental variables
39//! is available [here](https://github.com/dpeachpeach/kalshi-rust/blob/main/sample_bot/src/main.rs#L12)
40//! ```
41//! use kalshi::Kalshi;
42//! use kalshi::TradingEnvironment;
43//!
44//! let key_id = "your-key-id";
45//! let pem_path = "path/to/private.pem";
46//!
47//! let kalshi_instance = Kalshi::new(TradingEnvironment::DemoMode, key_id, pem_path).await?;
48//! ```
49//!
50//! After logging in, you can call any method present in the crate without issue.
51//! Here is a script that buys a 'yes' contract on November 13th's New York temperature
52//! market.
53//!
54//! ```
55//! let new_york_ticker = "HIGHNY-23NOV13-T51".to_string();
56//!
57//! let bought_order = kalshi_instance
58//! .create_order(
59//! kalshi::Action::Buy,
60//! None,
61//! 1,
62//! kalshi::Side::Yes,
63//! new_york_ticker,
64//! kalshi::OrderType::Limit,
65//! None,
66//! None,
67//! None,
68//! None,
69//! Some(5)).await.unwrap();
70//! ```
71//!
72//! Refer to the rest of the documentation for details on all other methods!
73//!
74//! ## Returned Values
75//!
76//! Whenever a user makes a method call using the kalshi struct, data is typically returned
77//! in structs that encapsulate the json fields returned by the server. All data
78//! in the structs is owned so a user can access the attributes without issue.
79//!
80//! ### Examples:
81//!
82//! #### Obtaining the Exchange's current status
83//! Returns a struct that represents whether trading or the exchange are currently active.
84//! ```
85//! use kalshi::Kalshi;
86//! use kalshi::TradingEnvironment;
87//! let kalshi_instance = Kalshi::new(TradingEnvironment::DemoMode, "your-key-id", "path/to/private.pem").await?;
88//!
89//! kalshi_instance.get_exchange_status().await.unwrap();
90//! ```
91//!
92//! #### Obtaining 5 miscellaneous market events
93//! Returns a vector of 'event' structs and a cursor.
94//! ```
95//! use kalshi::Kalshi;
96//! use kalshi::TradingEnvironment;
97//! let kalshi_instance = Kalshi::new(TradingEnvironment::DemoMode, "your-key-id", "path/to/private.pem").await?;
98//!
99//! kalshi_instance.get_multiple_events(Some(5), None, None, None, None).await.unwrap();
100//! ```
101//! #### Checking the User's balance
102//! Returns an i64 representing the user's balance in cents.
103//! ```
104//! use kalshi::Kalshi;
105//! use kalshi::TradingEnvironment;
106//! let kalshi_instance = Kalshi::new(TradingEnvironment::DemoMode, "your-key-id", "path/to/private.pem").await?;
107//!
108//! kalshi_instance.get_balance();
109//! ```
110//!
111
112#[macro_use]
113mod utils;
114mod api_keys;
115mod auth;
116mod collection;
117mod communications;
118mod events;
119mod exchange;
120mod fcm;
121mod incentive_programs;
122mod kalshi_error;
123mod live_data;
124mod market;
125mod milestone;
126mod portfolio;
127mod search;
128mod structured_targets;
129mod websocket;
130
131// pub use auth::*; // Unused import
132pub use api_keys::*;
133pub use collection::*;
134pub use communications::*;
135pub use events::*;
136pub use exchange::*;
137pub use fcm::FcmPosition; // Only export the specific type, not all
138pub use incentive_programs::*;
139pub use kalshi_error::*;
140pub use live_data::*;
141pub use market::*;
142pub use milestone::*;
143pub use portfolio::*;
144pub use search::*;
145pub use structured_targets::*;
146pub use websocket::*;
147
148// imports
149use openssl::pkey::{PKey, Private};
150use std::fs;
151use std::path::Path;
152
153/// The Kalshi struct is the core of the kalshi-crate. It acts as the interface
154/// between the user and the market, abstracting away the meat of requests
155/// by encapsulating authentication information and the client itself.
156///
157/// ## Creating a new `Kalshi` instance for demo mode:
158///
159/// ```
160/// use kalshi::Kalshi;
161/// use kalshi::TradingEnvironment;
162///
163/// let kalshi_instance = Kalshi::new(TradingEnvironment::DemoMode, "your-key-id", "path/to/private.pem").await?;
164/// ```
165///
166///
167#[derive(Debug, Clone)]
168
169pub struct Kalshi {
170 /// - `base_url`: The base URL for the API, determined by the trading environment.
171 base_url: String,
172 /// - `key_id`: Key ID for key-based authentication
173 key_id: String,
174 /// - `private_key`: Private key for key-based authentication
175 private_key: PKey<Private>,
176 /// - `client`: The HTTP client used for making requests to the marketplace.
177 client: reqwest::Client,
178}
179
180impl Kalshi {
181 /// Creates a new instance of Kalshi with the specified trading environment and authenticates immediately.
182 /// This environment determines the base URL used for API requests.
183 ///
184 /// # Arguments
185 ///
186 /// * `trading_env` - The trading environment to be used (ProdMode: Trading with real money. DemoMode: Paper Trading).
187 /// * `key_id` - The UUID shown next to the key in your Kalshi UI
188 /// * `pem_path` - Path to the private key file you downloaded
189 ///
190 /// # Example
191 ///
192 /// ## Creating a Demo instance with authentication.
193 /// ```
194 /// use kalshi::{Kalshi, TradingEnvironment};
195 /// let kalshi = Kalshi::new(TradingEnvironment::DemoMode, "your-key-id", "path/to/private.pem").await?;
196 /// ```
197 ///
198 /// ## Creating a Live Trading instance with authentication (Warning, you're using real money!)
199 /// ```
200 /// use kalshi::{Kalshi, TradingEnvironment};
201 /// let kalshi = Kalshi::new(TradingEnvironment::ProdMode, "your-key-id", "path/to/private.pem").await?;
202 /// ```
203 ///
204 pub async fn new(
205 trading_env: TradingEnvironment,
206 key_id: &str,
207 pem_path: &str,
208 ) -> Result<Self, crate::kalshi_error::KalshiError> {
209 println!("Loading private key from: {}", pem_path);
210
211 // Load the private key first
212 let pem = match fs::read(Path::new(pem_path)) {
213 Ok(pem) => {
214 println!("Successfully read private key file");
215 pem
216 }
217 Err(e) => {
218 eprintln!("Failed to read private key file: {:?}", e);
219 return Err(e.into());
220 }
221 };
222
223 let private_key = match PKey::private_key_from_pem(&pem) {
224 Ok(key) => {
225 println!("Successfully parsed private key");
226 key
227 }
228 Err(e) => {
229 eprintln!("Failed to parse private key: {:?}", e);
230 return Err(e.into());
231 }
232 };
233
234 let base_url = utils::build_base_url(trading_env).to_string();
235 let kalshi = Self {
236 base_url,
237 key_id: key_id.to_string(),
238 private_key,
239 client: reqwest::Client::new(),
240 };
241
242 // Verify authentication by hitting an authenticated endpoint (balance)
243 println!("Verifying authentication with balance endpoint...");
244 match kalshi.get_balance().await {
245 Ok(balance) => {
246 println!(
247 "Authentication successful! Account balance: {} cents",
248 balance
249 );
250 Ok(kalshi)
251 }
252 Err(e) => {
253 eprintln!("Authentication failed: {:?}", e);
254 eprintln!("Please check your API key and private key file");
255 Err(e)
256 }
257 }
258 }
259
260 /// Creates a new WebSocket client using the same credentials.
261 pub fn websocket(&self) -> websocket::KalshiWebSocket {
262 websocket::KalshiWebSocket::new(self.trading_env(), &self.key_id, self.private_key.clone())
263 }
264
265 /// Returns the current trading environment.
266 pub fn trading_env(&self) -> TradingEnvironment {
267 if self.base_url.contains("demo") {
268 TradingEnvironment::DemoMode
269 } else {
270 TradingEnvironment::ProdMode
271 }
272 }
273}
274
275// GENERAL ENUMS
276// -----------------------------------------------
277
278/// Defines the trading environment for the Kalshi exchange.
279///
280/// This enum is used to specify whether the interaction with the Kalshi API should be in a demo (simulated) environment
281/// or in the live market with real financial transactions.
282///
283#[derive(Debug, Clone, Copy, PartialEq)]
284pub enum TradingEnvironment {
285 /// The demo mode represents a simulated environment where trades do not involve real money.
286 /// This mode is typically used for testing and practice purposes.
287 DemoMode,
288
289 /// The live market mode is the real trading environment where all transactions involve actual financial stakes.
290 /// Use this mode for actual trading activities with real money.
291 ProdMode,
292}