1use super::{Symbolic, VenueId};
5use crate::{uuid_val, Str};
6use anyhow::Result;
7use bytes::Bytes;
8use chrono::{DateTime, Utc};
9#[cfg(feature = "netidx")]
10use derive::FromValue;
11#[cfg(feature = "netidx")]
12use netidx_derive::Pack;
13use rust_decimal::Decimal;
14use schemars::JsonSchema;
15use serde::{Deserialize, Serialize};
16use std::collections::BTreeMap;
17use uuid::{uuid, Uuid};
18
19static PRODUCT_NS: Uuid = uuid!("bb25a7a7-a61c-485a-ac29-1de369a6a043");
20uuid_val!(ProductId, PRODUCT_NS);
21
22#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
23#[cfg_attr(feature = "netidx", derive(Pack, FromValue))]
24pub struct Product {
25 pub id: ProductId,
26 pub name: Str,
27 pub kind: ProductKind,
28}
29
30impl Product {
31 pub fn new(name: &str, kind: ProductKind) -> Result<Product> {
32 Ok(Product { id: ProductId::from(name), name: Str::try_from(name)?, kind })
33 }
34}
35
36impl Symbolic for Product {
37 type Id = ProductId;
38
39 fn type_name() -> &'static str {
40 "product"
41 }
42
43 fn id(&self) -> Self::Id {
44 self.id
45 }
46
47 fn name(&self) -> Str {
48 self.name
49 }
50}
51
52#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Copy, JsonSchema)]
53#[cfg_attr(feature = "netidx", derive(Pack))]
54#[serde(tag = "type", content = "value")]
55pub enum InstrumentType {
56 Inverse,
57 Linear,
58 Quanto,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
62#[cfg_attr(feature = "netidx", derive(Pack))]
63#[serde(tag = "type", content = "value")]
64pub enum ProductKind {
65 Coin {
67 token_info: BTreeMap<VenueId, TokenInfo>,
68 },
69 Fiat,
70 Equity,
71 Perpetual {
72 underlying: Option<ProductId>,
73 multiplier: Option<Decimal>,
74 instrument_type: Option<InstrumentType>,
75 },
76 Future {
79 underlying: Option<ProductId>,
80 multiplier: Option<Decimal>,
81 expiration: Option<DateTime<Utc>>,
82 instrument_type: Option<InstrumentType>,
83 },
84 FutureSpread {
85 same_side_leg: Option<ProductId>,
86 opp_side_leg: Option<ProductId>,
87 },
88 Option {
91 underlying: Option<ProductId>,
92 multiplier: Option<Decimal>,
93 expiration: Option<DateTime<Utc>>,
94 instrument_type: Option<InstrumentType>,
95 },
96 Index,
97 Commodity,
98 EventSeries {
129 display_name: Option<String>,
130 },
131 Event {
132 series: Option<ProductId>,
133 outcomes: Vec<ProductId>,
134 mutually_exclusive: Option<bool>,
135 expiration: Option<DateTime<Utc>>,
136 display_category: Option<String>,
137 display_name: Option<String>,
138 },
139 EventOutcome {
140 contracts: EventContracts,
141 display_order: Option<u32>,
142 display_name: Option<String>,
143 },
144 EventContract {
148 underlying: Option<ProductId>,
149 expiration: Option<DateTime<Utc>>,
150 },
151 #[cfg_attr(feature = "netidx", pack(other))]
152 #[serde(other)]
153 Unknown,
154}
155
156#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
157#[cfg_attr(feature = "netidx", derive(Pack))]
158pub enum EventContracts {
159 Single { yes: ProductId, yes_alias: Option<Str> },
160 Dual { yes: ProductId, yes_alias: Option<Str>, no: ProductId, no_alias: Option<Str> },
161}
162
163#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
164#[cfg_attr(feature = "juniper", derive(juniper::GraphQLUnion))]
165#[cfg_attr(feature = "netidx", derive(Pack))]
166pub enum TokenInfo {
167 ERC20(ERC20TokenInfo),
168}
169
170#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
171#[cfg_attr(feature = "netidx", derive(Pack))]
172pub struct ERC20TokenInfo {
173 pub address: Bytes,
175 pub decimals: u8,
176}
177
178#[cfg(feature = "juniper")]
179#[cfg_attr(feature = "juniper", juniper::graphql_object)]
180impl ERC20TokenInfo {
181 pub fn decimals(&self) -> crate::utils::graphql_scalars::U8 {
184 self.decimals.into()
185 }
186}