hypercall_runtime_api/boundary/
read_models.rs1use 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#[derive(Debug, Clone)]
84pub struct PortfolioSummary {
85 pub positions: HashMap<String, PositionSummary>,
86 pub margin_info: Option<MarginInfo>,
87}
88
89#[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#[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}