Skip to main content

hypercall_db/traits/
catalog.rs

1//! Catalog management traits for instrument lifecycle.
2//!
3//! Used by the CatalogManager to discover instruments from oracles,
4//! manage trading modes, and coordinate settlement state.
5
6use anyhow::Result;
7use rust_decimal::Decimal;
8
9/// Catalog state for a market (one row per underlying + expiry).
10#[derive(Debug, Clone)]
11pub struct MarketCatalogState {
12    pub underlying: String,
13    pub expiry: i64,
14    pub ref_price_at_listing: Decimal,
15    pub listed_at: i64,
16    pub listing_policy_version: i32,
17    pub last_extension_at: Option<i64>,
18    pub last_extension_ref_price: Option<Decimal>,
19}
20
21/// Instrument summary for catalog settlement processing.
22#[derive(Debug, Clone)]
23pub struct CatalogInstrument {
24    pub id: String,
25    pub underlying: String,
26    pub strike: Decimal,
27    pub expiry: i64,
28    pub option_type: String,
29}
30
31/// Read-only catalog queries.
32#[async_trait::async_trait]
33pub trait CatalogReader: Send + Sync {
34    /// Get catalog state for a market (keyed by underlying + expiry).
35    async fn get_market_catalog_state(
36        &self,
37        underlying: &str,
38        expiry: i64,
39    ) -> Result<Option<MarketCatalogState>>;
40
41    /// Get all instruments for a given underlying and expiry (for settlement).
42    async fn get_instruments_for_settlement(
43        &self,
44        underlying: &str,
45        expiry: i64,
46    ) -> Result<Vec<CatalogInstrument>>;
47
48    /// Get distinct strike prices for an underlying and expiry.
49    async fn get_distinct_strikes(&self, underlying: &str, expiry: i64) -> Result<Vec<Decimal>>;
50
51    /// Get all markets (underlying, expiry) for an underlying.
52    async fn get_markets_for_underlying(&self, underlying: &str) -> Result<Vec<(String, i64)>>;
53
54    /// Count existing instruments for a market.
55    async fn get_instruments_count(&self, underlying: &str, expiry: i64) -> Result<i32>;
56
57    /// Check if a market exists (underlying + expiry).
58    async fn market_exists(&self, underlying: &str, expiry: i64) -> Result<bool>;
59
60    /// Check whether an instrument exists by symbol.
61    async fn instrument_exists(&self, symbol: &str) -> Result<bool>;
62}
63
64/// Catalog write operations.
65#[async_trait::async_trait]
66pub trait CatalogWriter: CatalogReader {
67    /// Insert or update market catalog state. On conflict (market already exists),
68    /// only `last_extension_at` and `last_extension_ref_price` are updated -- the
69    /// initial listing fields (`ref_price_at_listing`, `listed_at`,
70    /// `listing_policy_version`) are immutable after creation.
71    async fn upsert_market_catalog_state(&self, state: &MarketCatalogState) -> Result<()>;
72
73    /// Update trading mode for all instruments of an underlying.
74    async fn update_trading_mode_for_underlying(
75        &self,
76        underlying: &str,
77        trading_mode: &str,
78    ) -> Result<()>;
79}