use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PredictMarket {
pub id: u64,
pub title: String,
pub question: String,
pub condition_id: String,
pub status: String,
pub category_slug: String,
pub is_neg_risk: bool,
pub is_yield_bearing: bool,
#[serde(default)]
pub fee_rate_bps: u64,
pub outcomes: Vec<PredictOutcome>,
pub created_at: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub start_price: Option<Decimal>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub price_feed_id: Option<String>,
}
impl PredictMarket {
pub fn strike_price(&self) -> Option<Decimal> {
self.start_price
}
pub fn set_strike_price(&mut self, start_price: Decimal, price_feed_id: String) {
self.start_price = Some(start_price);
self.price_feed_id = Some(price_feed_id);
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PredictOutcome {
pub name: String,
pub index_set: u64,
pub on_chain_id: String,
pub status: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PredictOrderBook {
pub market_id: String,
pub best_bid: Option<Decimal>,
pub best_ask: Option<Decimal>,
pub bids: Vec<(Decimal, Decimal)>,
pub asks: Vec<(Decimal, Decimal)>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum OrderStatus {
Open,
Filled,
Expired,
Cancelled,
Invalidated,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PredictOrderData {
pub hash: String,
#[serde(deserialize_with = "string_or_number")]
pub salt: String,
pub maker: String,
pub signer: String,
pub taker: String,
pub token_id: String,
#[serde(deserialize_with = "string_or_number")]
pub maker_amount: String,
#[serde(deserialize_with = "string_or_number")]
pub taker_amount: String,
#[serde(deserialize_with = "string_or_number")]
pub expiration: String,
#[serde(deserialize_with = "string_or_number")]
pub nonce: String,
#[serde(deserialize_with = "string_or_number")]
pub fee_rate_bps: String,
pub side: u8,
pub signature_type: u8,
pub signature: String,
}
fn string_or_number<'de, D>(deserializer: D) -> std::result::Result<String, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de;
struct StringOrNumberVisitor;
impl<'de> de::Visitor<'de> for StringOrNumberVisitor {
type Value = String;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a string or number")
}
fn visit_str<E: de::Error>(self, v: &str) -> std::result::Result<String, E> {
Ok(v.to_string())
}
fn visit_string<E: de::Error>(self, v: String) -> std::result::Result<String, E> {
Ok(v)
}
fn visit_u64<E: de::Error>(self, v: u64) -> std::result::Result<String, E> {
Ok(v.to_string())
}
fn visit_i64<E: de::Error>(self, v: i64) -> std::result::Result<String, E> {
Ok(v.to_string())
}
fn visit_f64<E: de::Error>(self, v: f64) -> std::result::Result<String, E> {
Ok(v.to_string())
}
}
deserializer.deserialize_any(StringOrNumberVisitor)
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PredictOrder {
pub id: String,
#[serde(deserialize_with = "deserialize_market_id")]
pub market_id: u64,
#[serde(default)]
pub currency: Option<String>,
pub amount: String,
pub amount_filled: String,
#[serde(default)]
pub is_neg_risk: bool,
#[serde(default)]
pub is_yield_bearing: bool,
#[serde(default)]
pub strategy: String,
pub status: OrderStatus,
pub order: PredictOrderData,
}
fn deserialize_market_id<'de, D>(deserializer: D) -> std::result::Result<u64, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de;
struct MarketIdVisitor;
impl<'de> de::Visitor<'de> for MarketIdVisitor {
type Value = u64;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a number or string containing a number")
}
fn visit_u64<E: de::Error>(self, v: u64) -> std::result::Result<u64, E> {
Ok(v)
}
fn visit_i64<E: de::Error>(self, v: i64) -> std::result::Result<u64, E> {
Ok(v as u64)
}
fn visit_str<E: de::Error>(self, v: &str) -> std::result::Result<u64, E> {
v.parse::<u64>().map_err(de::Error::custom)
}
}
deserializer.deserialize_any(MarketIdVisitor)
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetOrdersResponse {
pub success: bool,
pub cursor: Option<String>,
pub data: Vec<PredictOrder>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlaceOrderResponse {
pub success: bool,
pub data: Option<PlaceOrderData>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PlaceOrderData {
pub code: Option<String>,
pub order_id: String,
pub order_hash: String,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateOrderRequest {
pub data: CreateOrderData,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateOrderData {
pub order: serde_json::Value,
pub price_per_share: String,
pub strategy: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RemoveOrdersResponse {
pub success: bool,
pub removed: Vec<String>,
pub noop: Vec<String>,
}
#[derive(Debug, Clone, Serialize)]
pub struct RemoveOrdersRequest {
pub data: RemoveOrdersData,
}
#[derive(Debug, Clone, Serialize)]
pub struct RemoveOrdersData {
pub ids: Vec<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AuthMessageResponse {
pub success: bool,
pub data: AuthMessageData,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AuthMessageData {
pub message: String,
}
#[derive(Debug, Clone, Serialize)]
pub struct AuthRequest {
pub signer: String,
pub signature: String,
pub message: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AuthResponse {
pub success: bool,
pub data: AuthResponseData,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AuthResponseData {
pub token: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct GetPositionsResponse {
pub success: bool,
pub cursor: Option<String>,
pub data: Vec<PredictPosition>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PredictPosition {
pub id: String,
pub market: PredictPositionMarket,
pub outcome: PredictPositionOutcome,
pub amount: String,
#[serde(default)]
pub value_usd: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PredictPositionMarket {
pub id: u64,
pub title: String,
#[serde(default)]
pub condition_id: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PredictPositionOutcome {
pub name: String,
pub index_set: u64,
pub on_chain_id: String,
pub status: Option<String>,
}
#[derive(Debug, Clone, Default)]
pub struct WalletEventDetails {
pub price: Option<String>,
pub quantity: Option<String>,
pub quantity_filled: Option<String>,
pub outcome: Option<String>,
pub quote_type: Option<String>,
}
#[derive(Debug, Clone)]
pub enum PredictWalletEvent {
OrderAccepted {
order_hash: String,
order_id: String,
},
OrderNotAccepted {
order_hash: String,
order_id: String,
reason: Option<String>,
},
OrderExpired {
order_hash: String,
order_id: String,
},
OrderCancelled {
order_hash: String,
order_id: String,
},
OrderTransactionSubmitted {
order_hash: String,
order_id: String,
tx_hash: Option<String>,
details: WalletEventDetails,
},
OrderTransactionSuccess {
order_hash: String,
order_id: String,
tx_hash: Option<String>,
details: WalletEventDetails,
},
OrderTransactionFailed {
order_hash: String,
order_id: String,
tx_hash: Option<String>,
details: WalletEventDetails,
},
Unknown {
event_type: String,
data: serde_json::Value,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CategoryResponse {
pub success: bool,
pub data: PredictCategory,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PredictCategory {
pub id: u64,
pub slug: String,
pub title: String,
pub markets: Vec<PredictMarket>,
}