Skip to main content

hypercall_runtime_api/boundary/
read_models.rs

1use std::collections::HashMap;
2
3use hypercall_db::{MmpConfigRecord, UserTierRecord, UserTierUpdate};
4use hypercall_margin::{ExtendedRiskGrid, MarginDetails, ScenarioPnl};
5use hypercall_types::api_models::{Portfolio, TradingLimits, UserTierData};
6use hypercall_types::ws_protocol::PortfolioUpdate;
7use hypercall_types::{EngineMessage, WalletAddress};
8use rust_decimal::Decimal;
9use serde::{Deserialize, Serialize};
10use tokio::sync::mpsc;
11
12#[async_trait::async_trait]
13pub trait TierCacheApi: Send + Sync {
14    async fn get_tier(&self, wallet: &WalletAddress) -> Option<UserTierData>;
15    async fn get_tier_record(
16        &self,
17        wallet: &WalletAddress,
18    ) -> anyhow::Result<Option<UserTierRecord>>;
19    async fn get_existing_margin_mode(
20        &self,
21        wallet: &WalletAddress,
22    ) -> anyhow::Result<Option<hypercall_types::MarginMode>>;
23    async fn restore_tier_record(
24        &self,
25        wallet: &WalletAddress,
26        previous_tier: Option<&UserTierRecord>,
27    ) -> anyhow::Result<()>;
28    async fn set_tier(&self, new_tier: UserTierUpdate) -> anyhow::Result<()>;
29    async fn delete_tier(&self, wallet: &WalletAddress) -> anyhow::Result<()>;
30    async fn get_margin_mode(
31        &self,
32        wallet: &WalletAddress,
33    ) -> anyhow::Result<hypercall_types::MarginMode>;
34    fn get_margin_mode_sync(
35        &self,
36        wallet: &WalletAddress,
37    ) -> anyhow::Result<hypercall_types::MarginMode>;
38    async fn set_margin_mode(
39        &self,
40        wallet: &WalletAddress,
41        mode: hypercall_types::MarginMode,
42    ) -> anyhow::Result<i64>;
43    async fn apply_margin_mode_update(
44        &self,
45        wallet: WalletAddress,
46        margin_mode: hypercall_types::MarginMode,
47        version: i64,
48    );
49    fn get_trading_limits(&self, wallet: &WalletAddress) -> TradingLimits;
50    async fn get_trading_limits_async(&self, wallet: &WalletAddress) -> TradingLimits;
51}
52
53#[async_trait::async_trait]
54pub trait MmpCacheApi: Send + Sync {
55    async fn set_config(&self, config: MmpConfigRecord) -> anyhow::Result<()>;
56    async fn get_config(&self, wallet: &WalletAddress, currency: &str) -> Option<MmpConfigRecord>;
57    async fn get_configs_for_wallet(&self, wallet: &WalletAddress) -> Vec<MmpConfigRecord>;
58    async fn delete_config(&self, wallet: &WalletAddress, currency: &str) -> anyhow::Result<()>;
59    async fn reset_mmp(&self, wallet: &WalletAddress, currency: &str);
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct WalletMarginSnapshot {
64    pub mode: hypercall_types::MarginMode,
65    pub span_margin: hypercall_types::api_models::SpanMarginSummary,
66    pub margin_summary: hypercall_types::api_models::MarginSummary,
67    pub total_margin_used: Decimal,
68    pub available_balance: Decimal,
69    pub standard_position_contributions:
70        Option<HashMap<String, hypercall_margin::PositionMarginContribution>>,
71    pub standard_option_marks: Option<HashMap<String, Decimal>>,
72}
73
74#[derive(Debug, Clone)]
75pub struct PmRiskGridData {
76    pub margin_details: MarginDetails,
77    pub position_details: MarginDetails,
78    pub scenario_pnls: Vec<ScenarioPnl>,
79    pub extended_grid: ExtendedRiskGrid,
80}
81
82/// Summary of a portfolio for metrics collection.
83#[derive(Debug, Clone)]
84pub struct PortfolioSummary {
85    pub positions: HashMap<String, PositionSummary>,
86    pub margin_info: Option<MarginInfo>,
87}
88
89/// Summary of a position for metrics collection.
90#[derive(Debug, Clone)]
91pub struct PositionSummary {
92    pub symbol: String,
93    pub amount: Decimal,
94    pub entry_price: Decimal,
95    pub realized_pnl: Decimal,
96    pub unrealized_pnl: Decimal,
97}
98
99/// Summary of margin info for metrics collection.
100#[derive(Debug, Clone)]
101pub struct MarginInfo {
102    pub equity: Decimal,
103    pub initial_margin: Decimal,
104    pub maintenance_margin: Decimal,
105}
106
107#[async_trait::async_trait]
108pub trait PortfolioCacheApi: Send + Sync {
109    async fn compute_wallet_margin_snapshot(
110        &self,
111        wallet: &WalletAddress,
112    ) -> anyhow::Result<WalletMarginSnapshot>;
113    async fn get_portfolio(&self, account: &WalletAddress) -> anyhow::Result<Portfolio>;
114    async fn get_portfolio_fail_closed_pm(
115        &self,
116        account: &WalletAddress,
117    ) -> anyhow::Result<Portfolio>;
118    async fn compute_pm_risk_grid_data(
119        &self,
120        wallet: &WalletAddress,
121    ) -> anyhow::Result<PmRiskGridData>;
122    async fn open_position_count(&self, wallet: &WalletAddress) -> usize;
123    async fn has_live_position_symbol(&self, wallet: &WalletAddress, symbol: &str) -> bool;
124    async fn get_all_portfolios(&self) -> HashMap<WalletAddress, PortfolioSummary>;
125    async fn subscribe(
126        &self,
127        wallet: WalletAddress,
128    ) -> (u64, mpsc::UnboundedReceiver<PortfolioUpdate>);
129    async fn unsubscribe(&self, wallet: &WalletAddress, subscriber_id: u64);
130    async fn handle_engine_message(&self, message: EngineMessage, sequence: i64);
131    async fn handle_hypercore_position_update(
132        &self,
133        update: hypercall_types::HypercorePositionUpdate,
134    );
135    async fn publish_margin_update(&self, wallet: &WalletAddress);
136}
137
138#[async_trait::async_trait]
139pub trait BalanceProvider: Send + Sync {
140    async fn get_balance(&self, wallet: &WalletAddress) -> anyhow::Result<Decimal>;
141}
142
143#[derive(Debug, Clone)]
144pub struct BalanceLedgerSyncSnapshot {
145    pub balances: HashMap<WalletAddress, Decimal>,
146    pub balance_update_seq: u64,
147    pub balance_update_stream_required: bool,
148    pub latest_acked_balance_stream_sequence: Option<u64>,
149    pub latest_acked_balance_update_seq: Option<u64>,
150}
151
152#[async_trait::async_trait]
153pub trait EngineBalanceSnapshotProvider: Send + Sync {
154    fn balance_ledger_sync_snapshot(&self) -> BalanceLedgerSyncSnapshot;
155}