1use crate::{folio::FolioMessage, orderflow::*, MaybeSecret, OrderId};
2use chrono::{DateTime, Utc};
3#[cfg(feature = "netidx")]
4use derive::FromValue;
5#[cfg(feature = "netidx")]
6use netidx_derive::Pack;
7use rust_decimal::Decimal;
8use schemars::JsonSchema;
9use serde_derive::{Deserialize, Serialize};
10use std::ops::Deref;
11
12#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)]
13pub struct KalshiCredentials {
14 pub api_key: String,
16 pub api_private_key: MaybeSecret<String>,
18}
19
20#[derive(Debug, Clone, Copy, Serialize, Deserialize, JsonSchema)]
21#[cfg_attr(feature = "netidx", derive(Pack))]
22pub struct KalshiOrder {
23 #[serde(flatten)]
24 pub order: Order,
25}
26
27impl Deref for KalshiOrder {
28 type Target = Order;
29
30 fn deref(&self) -> &Self::Target {
31 &self.order
32 }
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
36#[cfg_attr(feature = "netidx", derive(Pack))]
37pub struct KalshiTrade {
38 pub order_id: OrderId,
39 pub exec_id: String,
40 pub scaled_price: i64,
41 pub qty: Decimal,
42 pub time: DateTime<Utc>,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, JsonSchema)]
46#[cfg_attr(feature = "netidx", derive(Pack))]
47pub enum KalshiOrderStatus {
48 Canceled,
49 Executed,
50 Resting,
51 Pending,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
55#[cfg_attr(feature = "netidx", derive(Pack))]
56pub struct KalshiOrderState {
57 pub internal_order_id: OrderId,
58 pub last_update_time: Option<DateTime<Utc>>,
59 pub status: KalshiOrderStatus,
60 pub fills: Vec<Result<Fill, AberrantFill>>,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
64#[cfg_attr(feature = "netidx", derive(Pack))]
65#[cfg_attr(feature = "netidx", derive(FromValue))]
66pub enum KalshiMessage {
67 Order(KalshiOrder),
68 Cancel(Cancel),
69 CancelAll,
70 Ack(Ack),
71 Out(Out),
72 Fill(Result<Fill, AberrantFill>),
73 Reject(Reject),
74 Folio(FolioMessage),
75 PollOrders,
76 ExchangeAck { order_id: OrderId, kalshi_order_id: String },
77 ExchangeOrderState(KalshiOrderState),
78}
79
80impl TryInto<OrderflowMessage> for &KalshiMessage {
81 type Error = ();
82
83 fn try_into(self) -> Result<OrderflowMessage, ()> {
84 match self {
85 KalshiMessage::Order(o) => Ok(OrderflowMessage::Order(**o)),
86 KalshiMessage::Cancel(c) => Ok(OrderflowMessage::Cancel(*c)),
87 KalshiMessage::CancelAll => {
88 Ok(OrderflowMessage::CancelAll(CancelAll { venue_id: None }))
89 }
90 KalshiMessage::Ack(a) => Ok(OrderflowMessage::Ack(*a)),
91 KalshiMessage::Out(o) => Ok(OrderflowMessage::Out(*o)),
92 KalshiMessage::Fill(f) => Ok(OrderflowMessage::Fill(*f)),
93 KalshiMessage::Reject(r) => Ok(OrderflowMessage::Reject(r.clone())),
94 KalshiMessage::Folio(_)
95 | KalshiMessage::PollOrders
96 | KalshiMessage::ExchangeAck { .. }
97 | KalshiMessage::ExchangeOrderState(_) => Err(()),
98 }
99 }
100}
101
102impl TryInto<KalshiMessage> for &OrderflowMessage {
103 type Error = ();
104
105 fn try_into(self) -> Result<KalshiMessage, ()> {
106 match self {
107 OrderflowMessage::Order(o) => {
108 Ok(KalshiMessage::Order(KalshiOrder { order: *o }))
109 }
110 OrderflowMessage::Cancel(c) => Ok(KalshiMessage::Cancel(*c)),
111 OrderflowMessage::CancelAll(_) => Ok(KalshiMessage::CancelAll),
112 OrderflowMessage::Ack(a) => Ok(KalshiMessage::Ack(*a)),
113 OrderflowMessage::Out(o) => Ok(KalshiMessage::Out(*o)),
114 OrderflowMessage::Reject(r) => Ok(KalshiMessage::Reject(r.clone())),
115 OrderflowMessage::Fill(f) => Ok(KalshiMessage::Fill(*f)),
116 }
117 }
118}
119
120impl TryInto<FolioMessage> for &KalshiMessage {
121 type Error = ();
122
123 fn try_into(self) -> Result<FolioMessage, ()> {
124 match self {
125 KalshiMessage::Folio(f) => Ok(f.clone()),
126 _ => Err(()),
127 }
128 }
129}
130
131impl TryFrom<&FolioMessage> for KalshiMessage {
132 type Error = ();
133
134 fn try_from(f: &FolioMessage) -> Result<Self, ()> {
135 Ok(Self::Folio(f.clone()))
136 }
137}