Skip to main content

perpcity_sdk/
types.rs

1//! Client-facing types for the PerpCity SDK.
2//!
3//! These types use `f64` for human-readable values (prices, USDC amounts,
4//! leverage) and Alloy's [`Address`] / [`B256`] for on-chain identifiers.
5//! They are the public API surface — users construct these, and the SDK
6//! converts them to wire-format contract types internally.
7//!
8//! Following the [hyperliquid-rust-sdk] pattern: client types are **not**
9//! serializable. Serialization belongs on wire types only.
10
11use alloy::primitives::{Address, B256, U256};
12
13/// Deployed contract addresses for a PerpCity instance.
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct Deployments {
16    /// PerpManager proxy address.
17    pub perp_manager: Address,
18    /// USDC token address.
19    pub usdc: Address,
20    /// Fees module address (if registered).
21    pub fees_module: Option<Address>,
22    /// Margin ratios module address (if registered).
23    pub margin_ratios_module: Option<Address>,
24    /// Lockup period module address (if registered).
25    pub lockup_period_module: Option<Address>,
26    /// Sqrt-price impact limit module address (if registered).
27    pub sqrt_price_impact_limit_module: Option<Address>,
28}
29
30/// Metadata about a perpetual market.
31#[derive(Debug, Clone, PartialEq)]
32pub struct PerpData {
33    /// Unique perp identifier (`PoolId` / `bytes32` on-chain).
34    pub id: B256,
35    /// Tick spacing for the underlying Uniswap V4 pool.
36    pub tick_spacing: i32,
37    /// Current mark price in human-readable units (e.g. `1.05`).
38    pub mark: f64,
39    /// Beacon contract address.
40    pub beacon: Address,
41    /// Leverage and margin constraints.
42    pub bounds: Bounds,
43    /// Fee structure.
44    pub fees: Fees,
45}
46
47/// Leverage and margin constraints for a perpetual market.
48///
49/// All values are human-readable: leverage as a multiplier (e.g. `10.0`),
50/// margin in USDC (e.g. `5.0`), and ratios as fractions (e.g. `0.005`).
51#[derive(Debug, Clone, Copy, PartialEq)]
52pub struct Bounds {
53    /// Minimum margin to open a position, in USDC (e.g. `5.0`).
54    pub min_margin: f64,
55    /// Minimum taker leverage (e.g. `1.0`).
56    pub min_taker_leverage: f64,
57    /// Maximum taker leverage (e.g. `100.0`).
58    pub max_taker_leverage: f64,
59    /// Margin ratio at which taker liquidation occurs, as a fraction
60    /// (e.g. `0.005` = 0.5%).
61    pub liquidation_taker_ratio: f64,
62}
63
64/// Fee percentages for a perpetual market, expressed as fractions of 1.
65///
66/// For example, `0.001` means 0.1% (which is `1_000` on-chain at 1e6 scale).
67#[derive(Debug, Clone, Copy, PartialEq)]
68pub struct Fees {
69    /// Fee paid to the perp creator.
70    pub creator_fee: f64,
71    /// Fee that goes to the insurance fund.
72    pub insurance_fee: f64,
73    /// Fee earned by liquidity providers.
74    pub lp_fee: f64,
75    /// Fee charged on liquidations.
76    pub liquidation_fee: f64,
77}
78
79/// Real-time position metrics, typically from a `quoteClosePosition` call.
80///
81/// All USDC values are human-readable (e.g. `12.50` not `12_500_000`).
82#[derive(Debug, Clone, Copy, PartialEq)]
83pub struct LiveDetails {
84    /// Unrealized PnL in USDC.
85    pub pnl: f64,
86    /// Accumulated funding payment in USDC (positive = received).
87    pub funding_payment: f64,
88    /// Current effective margin in USDC.
89    pub effective_margin: f64,
90    /// Whether this position would be liquidated at the current price.
91    pub is_liquidatable: bool,
92}
93
94/// Taker open interest for a perp market, in USDC.
95#[derive(Debug, Clone, Copy, PartialEq)]
96pub struct OpenInterest {
97    /// Total long open interest in USDC.
98    pub long_oi: f64,
99    /// Total short open interest in USDC.
100    pub short_oi: f64,
101}
102
103/// Client-facing parameters for opening a taker (long/short) position.
104///
105/// The SDK converts these to contract types automatically:
106/// - `margin` → scaled to 6 decimals
107/// - `leverage` → converted to margin ratio via `1e6 / leverage`
108#[derive(Debug, Clone, Copy, PartialEq)]
109pub struct OpenTakerParams {
110    /// `true` for long, `false` for short.
111    pub is_long: bool,
112    /// Margin in USDC (e.g. `100.0` for 100 USDC).
113    pub margin: f64,
114    /// Leverage multiplier (e.g. `10.0` for 10×).
115    pub leverage: f64,
116    /// Slippage protection: max unspecified token amount. `0` = no limit.
117    pub unspecified_amount_limit: u128,
118}
119
120/// Client-facing parameters for opening a maker (LP) position.
121///
122/// The SDK converts these to contract types automatically:
123/// - `margin` → scaled to 6 decimals
124/// - `price_lower` / `price_upper` → converted to ticks
125#[derive(Debug, Clone, Copy, PartialEq)]
126pub struct OpenMakerParams {
127    /// Margin in USDC (e.g. `1000.0`).
128    pub margin: f64,
129    /// Lower bound of the price range.
130    pub price_lower: f64,
131    /// Upper bound of the price range.
132    pub price_upper: f64,
133    /// Liquidity amount to provide.
134    pub liquidity: u128,
135    /// Maximum amount of token0 willing to deposit.
136    pub max_amt0_in: u128,
137    /// Maximum amount of token1 willing to deposit.
138    pub max_amt1_in: u128,
139}
140
141/// Client-facing parameters for closing a position.
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
143pub struct CloseParams {
144    /// Minimum amount of token0 to receive (slippage protection).
145    pub min_amt0_out: u128,
146    /// Minimum amount of token1 to receive (slippage protection).
147    pub min_amt1_out: u128,
148    /// Maximum amount of token1 willing to pay.
149    pub max_amt1_in: u128,
150}
151
152/// Result of closing a position.
153#[derive(Debug, Clone, Copy, PartialEq, Eq)]
154pub struct CloseResult {
155    /// Transaction hash.
156    pub tx_hash: B256,
157    /// If the close was partial, the remaining position's NFT token ID.
158    /// `None` means the position was fully closed.
159    pub remaining_position_id: Option<U256>,
160}