Skip to main content

acta_maker_sdk/http/
types.rs

1use serde::{Deserialize, Serialize};
2
3pub use crate::types::VaultLeg;
4use crate::ws::types::{MarketInfo, TokenInfo};
5
6/// Public `/api/v1/vaults` row. Integers wider than JSON-safe stay decimal strings.
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub struct Vault {
9    pub vault_pda: String,
10    pub vault_id: String,
11    pub governance: String,
12    pub fee_recipient: String,
13    pub primary_delegate: String,
14    pub main_mint: String,
15    pub second_mint: String,
16    pub share_mint: String,
17    pub main_token_program: TokenProgramKind,
18    pub second_token_program: TokenProgramKind,
19    pub main_decimals: u8,
20    pub second_decimals: u8,
21    /// `idle`, `active`, `settling` or `processing_capital`.
22    pub phase: String,
23    /// `normal`, `frozen`, `emergency_unwind`, `withdraw_only` or `closing`.
24    pub safety: String,
25    pub capabilities: u32,
26    pub active_expiry: String,
27    pub open_positions: String,
28    pub total_shares: String,
29    pub share_price: String,
30    pub equity: String,
31    pub capital_generation: String,
32    pub second_leg_generation: String,
33    pub accepting_deposits: bool,
34    pub equity_computed: bool,
35    pub pending_deposit_count: u32,
36    pub pending_withdraw_count: u32,
37    pub pending_deposit_amount: String,
38    pub pending_withdraw_shares: String,
39    pub performance_fee_bps: u16,
40    pub management_fee_bps: u16,
41    pub manager_stake_min_bps: u16,
42    pub share_price_hwm: String,
43    pub last_hwm_update_ts: String,
44    pub last_hwm_reset_ts: String,
45    pub last_settlement_ts: String,
46    pub capacity: VaultCapacity,
47    pub capital_fallback_delay_secs: String,
48    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
49    pub deposit_window_set_ts: Option<String>,
50    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
51    pub main_balance: Option<String>,
52    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
53    pub second_balance: Option<String>,
54    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
55    pub balance_updated_at: Option<String>,
56    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
57    pub live_share_supply: Option<String>,
58    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
59    pub observed_manager_stake_shares: Option<String>,
60    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
61    pub balance_chain_slot: Option<String>,
62
63    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
64    pub staging: Option<VaultStaging>,
65    /// The next stage carries `staged_generation + 1`.
66    pub staged_generation: String,
67    pub policy: VaultPolicy,
68    pub projection: ProjectionCursor,
69
70    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
71    pub created_at: Option<String>,
72
73    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
74    pub generation_started_at: Option<String>,
75    /// Indicative: booked equity at the main mint's USD price, 1e9 scale.
76
77    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
78    pub tvl_usd_1e9: Option<String>,
79
80    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
81    pub price_time: Option<String>,
82
83    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
84    pub premium: Option<Vec<VaultPremium>>,
85
86    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
87    pub fees: Option<VaultFees>,
88
89    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
90    pub depositors_in_generation: Option<u64>,
91
92    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
93    pub performance: Option<VaultPerformance>,
94    /// Display only; `governance` is the authority.
95
96    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
97    pub metadata: Option<VaultMetadata>,
98}
99
100#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
101pub struct VaultMetadata {
102    pub name: String,
103
104    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
105    pub curator: Option<String>,
106
107    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
108    pub strategy: Option<String>,
109
110    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
111    pub description: Option<String>,
112
113    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
114    pub website: Option<String>,
115    /// X handle without `@`.
116
117    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
118    pub twitter: Option<String>,
119
120    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
121    pub logo_url: Option<String>,
122}
123
124/// Leg balance moved into a vault ATA of another mint, pending return to a leg.
125#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
126pub struct VaultStaging {
127    pub mint: String,
128    pub from_leg: VaultLeg,
129    pub amount: String,
130    pub staged_at: String,
131    /// The open slot's generation; an unstage names it.
132    pub generation: String,
133}
134
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
136pub enum TokenProgramKind {
137    #[serde(rename = "legacy_spl")]
138    LegacySpl,
139    #[serde(rename = "token_2022")]
140    Token2022,
141}
142
143#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
144pub struct VaultPolicy {
145    pub max_open_positions: u16,
146    pub max_rebalance_drift_bps: u16,
147    pub min_main_liquidity_bps: u16,
148}
149
150#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
151pub struct ProjectionCursor {
152    pub version: String,
153    pub slot: String,
154    pub transaction_index: u32,
155    pub signature: String,
156    pub event_index: u32,
157}
158
159/// A zero on-chain cap means the vault accepts deposits without a limit.
160#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
161#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
162pub enum VaultCapacity {
163    Unlimited {},
164    Limited {
165        cap_limit: String,
166        remaining: String,
167    },
168}
169
170/// Net premium per quote mint, in quote atoms, for the current cycle and generation.
171#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
172pub struct VaultPremium {
173    pub quote_mint: String,
174    pub cycle: PremiumFlow,
175    pub generation: PremiumFlow,
176}
177
178#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
179pub struct PremiumFlow {
180    pub received: String,
181    /// `None` when a holder leg's market lacks decimals or its open price.
182    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
183    pub paid: Option<String>,
184}
185
186/// Generation totals in main atoms.
187#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
188pub struct VaultFees {
189    pub management_fee_assessed: String,
190    pub performance_fee_assessed: String,
191    pub realized_fee_value: String,
192}
193
194/// Metrics of `capital_generation` as of `computed_at`; all `None` unless `covered`.
195#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
196pub struct VaultPerformance {
197    pub capital_generation: String,
198    pub computed_at: String,
199    pub covered: bool,
200
201    pub returns: VaultReturns,
202
203    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
204    pub apy_30d: Option<f64>,
205
206    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
207    pub apy_90d: Option<f64>,
208
209    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
210    pub max_drawdown_pct: Option<f64>,
211
212    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
213    pub worst_cycle_return_pct: Option<f64>,
214
215    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
216    pub losing_cycles: Option<u64>,
217
218    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
219    pub cycles_completed: Option<u64>,
220}
221
222#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
223pub struct VaultReturns {
224    #[serde(rename = "7d")]
225    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
226    pub d7: Option<WindowReturn>,
227    #[serde(rename = "30d")]
228    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
229    pub d30: Option<WindowReturn>,
230    #[serde(rename = "90d")]
231    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
232    pub d90: Option<WindowReturn>,
233
234    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
235    pub all: Option<WindowReturn>,
236}
237
238/// Net-of-fee booked share price return between two checkpoint times.
239#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
240pub struct WindowReturn {
241    pub return_pct: f64,
242    pub from_time: String,
243    pub to_time: String,
244}
245
246/// Public `/api/v1/vaults/{pda}/positions` row.
247#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
248pub struct VaultPosition {
249    pub vault: String,
250    pub position: String,
251    pub order_id: String,
252    pub role: VaultPositionRole,
253    pub market: String,
254    pub position_type: VaultPositionType,
255    /// The lower strike for spreads.
256    pub strike: String,
257    pub product: VaultPositionProduct,
258    pub quantity: String,
259    pub net_premium: String,
260    pub counterparty: String,
261    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
262    pub funded_amount: Option<String>,
263    pub status: VaultPositionStatus,
264    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
265    pub is_otm: Option<bool>,
266    pub created_at: String,
267    pub acquired_at: String,
268    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
269    pub settled_at: Option<String>,
270    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
271    pub transaction_signature: Option<String>,
272}
273
274/// Physical CC/CSP, or a cash spread with its upper strike and the quote atoms it reserves.
275#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
276#[serde(tag = "kind", rename_all = "snake_case")]
277pub enum VaultPositionProduct {
278    Physical,
279    Spread {
280        upper_strike: String,
281        collateral: String,
282    },
283}
284
285#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
286#[serde(rename_all = "snake_case")]
287pub enum VaultPositionRole {
288    Writer,
289    Holder,
290}
291
292#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
293#[serde(rename_all = "snake_case")]
294pub enum VaultPositionType {
295    CoveredCall,
296    CashSecuredPut,
297    CallSpread,
298    PutSpread,
299    CashPut,
300}
301
302#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
303#[serde(rename_all = "snake_case")]
304pub enum VaultPositionStatus {
305    Open,
306    Funded,
307    Liquidated,
308    Settled,
309}
310
311/// Public `/api/v1/vaults/{pda}/exposure`: outstanding positions at the indicative spot.
312#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
313pub struct VaultExposure {
314    #[serde(deserialize_with = "crate::ws::types::deserialize_required_nullable")]
315    pub next_cursor: Option<String>,
316    pub vault_pda: String,
317    /// Unix seconds the positions were read; never older than 15 s.
318    pub as_of: String,
319    pub positions: Vec<VaultExposurePosition>,
320    pub totals: Vec<VaultExposureTotal>,
321}
322
323/// `intrinsic` is in quote atoms: positive for holder legs, negative for writer legs.
324#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
325pub struct VaultExposurePosition {
326    pub position: String,
327    pub market: String,
328    pub position_type: VaultPositionType,
329    pub role: VaultPositionRole,
330    pub status: VaultPositionStatus,
331    pub strike: String,
332    pub quantity: String,
333    pub expiry: String,
334    pub underlying_mint: String,
335    pub quote_mint: String,
336
337    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
338    pub underlying_decimals: Option<u8>,
339
340    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
341    pub quote_decimals: Option<u8>,
342
343    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
344    pub spot: Option<String>,
345
346    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
347    pub spot_time: Option<String>,
348
349    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
350    pub distance_pct: Option<f64>,
351
352    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
353    pub itm: Option<bool>,
354
355    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
356    pub intrinsic: Option<String>,
357}
358
359/// `None` when any position of the quote mint lacks the value.
360#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
361pub struct VaultExposureTotal {
362    pub quote_mint: String,
363
364    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
365    pub notional_at_strike: Option<String>,
366
367    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
368    pub outstanding_intrinsic: Option<String>,
369}
370
371#[derive(Debug, Clone, Serialize, Deserialize)]
372pub(super) struct VaultPositionsResponse {
373    pub(super) positions: Vec<VaultPosition>,
374    pub(super) next_cursor: Option<String>,
375}
376
377#[derive(Debug, Clone, Serialize, Deserialize)]
378pub(super) struct VaultsResponse {
379    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
380    pub next_cursor: Option<String>,
381    pub(super) vaults: Vec<Vault>,
382}
383
384#[derive(Debug, Clone, Serialize, Deserialize)]
385pub(super) struct MarketsResponse {
386    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
387    pub next_cursor: Option<String>,
388    pub(super) markets: Vec<MarketInfo>,
389}
390
391#[derive(Debug, Clone, Serialize, Deserialize)]
392pub(super) struct TokensResponse {
393    #[serde(deserialize_with = "crate::wire::deserialize_required_option")]
394    pub next_cursor: Option<String>,
395    pub(super) tokens: Vec<TokenInfo>,
396}
397
398/// A configured count bound.
399#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
400#[serde(tag = "type", rename_all = "snake_case", deny_unknown_fields)]
401pub enum CountLimit {
402    Unlimited {},
403    Limited { value: u64 },
404}
405
406/// Public `/api/v1/venue`: limits the server validates against.
407#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
408pub struct Venue {
409    pub protocol_fee_bps_premium: u16,
410    pub protocol_fee_bps_volume: u16,
411    pub program_id: crate::Address32,
412    pub min_quote_validity_seconds: u32,
413    pub settlement_buffer_seconds: u32,
414    pub quote_refresh_lead_seconds: u32,
415    pub min_rfq_timeout_seconds: u32,
416    pub max_rfq_timeout_seconds: u32,
417    pub signature_timeout_seconds: u64,
418    pub max_quotes_per_rfq: CountLimit,
419    pub max_active_rfqs_per_taker: CountLimit,
420    pub pre_expiry_cutoff_seconds: u64,
421}