af_iperps/
lib.rs

1#![cfg_attr(all(doc, not(doctest)), feature(doc_auto_cfg))]
2
3//! Move types for Aftermath's `Perpetuals` package
4
5use af_move_type::otw::Otw;
6use af_sui_pkg_sdk::sui_pkg_sdk;
7use af_sui_types::{Address, IdentStr, SUI_FRAMEWORK_ADDRESS};
8use af_utilities::types::ifixed::IFixed;
9use sui_framework_sdk::balance::Balance;
10use sui_framework_sdk::dynamic_object_field::Wrapper;
11use sui_framework_sdk::object::{ID, UID};
12use sui_framework_sdk::sui::SUI;
13use sui_framework_sdk::{Field, FieldTypeTag};
14
15pub mod errors;
16pub mod event_ext;
17pub mod event_instance;
18#[cfg(feature = "graphql")]
19pub mod graphql;
20pub mod math;
21pub mod order_helpers;
22pub mod order_id;
23#[cfg(feature = "stop-orders")]
24pub mod stop_order_helpers;
25
26pub use self::market::{MarketParams, MarketState};
27pub use self::orderbook::Order;
28pub use self::position::Position;
29
30/// Package IDs of the perpetuals contract versions published on testnet, in order of its versions.
31pub const TESTNET_PACKAGE_VERSIONS: &[Address] = &[Address::from_hex_unwrap(
32    b"0x1fc71972750d0d81567183a8500befef94d7699aac76edffcca253fe541367fd",
33)];
34
35// Convenient aliases since these types will never exist onchain with a type argument other than an
36// OTW.
37pub type AccountCap = self::account::AccountCap<Otw>;
38pub type AccountCapTypeTag = self::account::AccountCapTypeTag<Otw>;
39pub type Account = self::account::Account<Otw>;
40pub type AccountTypeTag = self::account::AccountTypeTag<Otw>;
41pub type StopOrderTicket = self::stop_orders::StopOrderTicket<Otw>;
42pub type StopOrderTicketTypetag = self::stop_orders::StopOrderTicketTypeTag<Otw>;
43pub type ClearingHouse = self::clearing_house::ClearingHouse<Otw>;
44pub type ClearingHouseTypeTag = self::clearing_house::ClearingHouseTypeTag<Otw>;
45pub type Vault = self::clearing_house::Vault<Otw>;
46pub type VaultTypeTag = self::clearing_house::VaultTypeTag<Otw>;
47
48/// Dynamic field storing a [`Position`].
49pub type PositionDf = Field<self::keys::Position, Position>;
50/// Dynamic field storing a leaf in a [`Map`] of [`Order`]s.
51///
52/// [`Map`]: self::ordered_map::Map
53pub type OrderLeafDf = Field<u64, self::ordered_map::Leaf<Order>>;
54/// Dynamic object field wrapper for the [`Orderbook`](orderbook::Orderbook) ID.
55pub type OrderbookDofWrapper = Field<Wrapper<keys::Orderbook>, ID>;
56/// Dynamic object field wrapper for the asks [`Map`](ordered_map::Map) ID.
57pub type AsksMapDofWrapper = Field<Wrapper<keys::AsksMap>, ID>;
58/// Dynamic object field wrapper for the bids [`Map`](ordered_map::Map) ID.
59pub type BidsMapDofWrapper = Field<Wrapper<keys::BidsMap>, ID>;
60
61sui_pkg_sdk!(perpetuals {
62    module account {
63        /// The AccountCap is used to check ownership of `Account` with the same `account_id`.
64        struct AccountCap<!phantom T> has key, store {
65            id: UID,
66            // Account object id
67            account_obj_id: ID,
68            /// Numerical value associated to the account
69            account_id: u64,
70        }
71
72        /// The Account object saves the collateral available to be used in clearing houses.
73        struct Account<!phantom T> has key, store {
74            id: UID,
75            /// Numerical value associated to the account
76            account_id: u64,
77            /// Balance available to be allocated to markets.
78            collateral: Balance<T>,
79        }
80
81        struct IntegratorConfig has store {
82            /// Max **additional** taker fee the user is willing
83            /// to pay for integrator-submitted orders.
84            max_taker_fee: IFixed
85        }
86    }
87
88    module admin {
89        /// Capability object required to perform admin functions.
90        ///
91        /// Minted once when the module is published and transfered to its creator.
92        struct AdminCapability has key, store {
93            id: UID
94        }
95    }
96
97    module clearing_house {
98        /// The central object that owns the market state.
99        ///
100        /// Dynamic fields:
101        /// - [`position::Position`]
102        /// - [`Vault`]
103        ///
104        /// Dynamic objects:
105        /// - [`orderbook::Orderbook`]
106        struct ClearingHouse<!phantom T> has key {
107            id: UID,
108            version: u64,
109            market_params: market::MarketParams,
110            market_state: market::MarketState
111        }
112
113        /// Stores all deposits from traders for collateral T.
114        /// Stores the funds reserved for covering bad debt from untimely
115        /// liquidations.
116        ///
117        /// The Clearing House keeps track of who owns each share of the vault.
118        struct Vault<!phantom T> has store {
119            collateral_balance: Balance<T>,
120            insurance_fund_balance: Balance<T>,
121        }
122
123        /// Stores the proposed parameters for updating margin ratios
124        struct MarginRatioProposal has store {
125            /// Target timestamp at which to apply the proposed updates
126            maturity: u64,
127            /// Proposed IMR
128            margin_ratio_initial: IFixed,
129            /// Proposed MMR
130            margin_ratio_maintenance: IFixed,
131        }
132
133        /// Stores the proposed parameters for a position's custom fees
134        struct PositionFeesProposal has store {
135            /// Proposed IMR
136            maker_fee: IFixed,
137            /// Proposed MMR
138            taker_fee: IFixed,
139        }
140
141        /// Structure that stores the amount of fees collected by an integrator
142        struct IntegratorVault has store {
143            /// Amount of fees collected by this integrator, in collateral units
144            fees: IFixed,
145        }
146
147        struct IntegratorInfo has copy, drop {
148            integrator_address: address,
149            taker_fee: u256,
150        }
151
152        /// Used by clearing house to check margin when placing an order
153        struct SessionHotPotato<!phantom T> {
154            clearing_house: ClearingHouse<T>,
155            orderbook: orderbook::Orderbook,
156            account_id: u64,
157            timestamp_ms: u64,
158            collateral_price: IFixed,
159            index_price: IFixed,
160            gas_price: u64,
161            margin_before: IFixed,
162            min_margin_before: IFixed,
163            position_base_before: IFixed,
164            total_open_interest: IFixed,
165            total_fees: IFixed,
166            maker_events: vector<events::FilledMakerOrder>,
167            liqee_account_id: Option<u64>,
168            liquidator_fees: IFixed,
169            session_summary: SessionSummary
170        }
171
172        struct SessionSummary has drop {
173            base_filled_ask: IFixed,
174            base_filled_bid: IFixed,
175            quote_filled_ask: IFixed,
176            quote_filled_bid: IFixed,
177            base_posted_ask: IFixed,
178            base_posted_bid: IFixed,
179            posted_orders: u64,
180            base_liquidated: IFixed,
181            quote_liquidated: IFixed,
182            is_liqee_long: bool,
183            bad_debt: IFixed
184        }
185    }
186
187    module stop_orders {
188        /// Object that allows to place one order on behalf of the user, used to
189        /// offer stop limit or market orders. A stop order is an order that is placed
190        /// only if the index price respects certain conditions, like being above or
191        /// below a certain price.
192        ///
193        /// Only the `AccountCap` owner can mint this object and can decide who can be
194        /// the executor of the ticket. This allows users to run their
195        /// own stop orders bots eventually, but it's mainly used to allow 3rd parties
196        /// to offer such a service (the user is required to trust such 3rd party).
197        /// The object is shared and the 3rd party is set as `executors`. The ticket
198        /// can be destroyed in any moment only by the user or by the executor.
199        /// The user needs to trust the 3rd party for liveness of the service offered.
200        ///
201        /// The order details are encrypted offchain and the result is stored in the ticket.
202        /// The user needs to share such details with the 3rd party only to allow for execution.
203        ///
204        /// The ticket can be either a shared, owned or party object.
205        /// The permission to execute or cancel it is controlled exclusively through `executors`,
206        /// which can be modified only by the `AccountCap` owner associated with the ticket
207        /// using the function `edit_stop_order_ticket_executors`.
208        struct StopOrderTicket<!phantom T> has key, store {
209            id: UID,
210            /// Addresses allowed to execute the order on behalf of the user.
211            executors: vector<address>,
212            /// Gas coin that must be provided by the user to cover for one stop order cost.
213            /// This amount of gas is going to be sent to the executor of the order.
214            gas: Balance<SUI>,
215            /// User account id
216            account_id: u64,
217            /// Value to indentify the stop order type. Available values can be found in the
218            /// constants module.
219            stop_order_type: u64,
220            /// Vector containing the blake2b hash obtained from offchain on the stop order parameters.
221            /// Depending on the stop order type value, a different set of parameters is expected to be used.
222            ///
223            /// Parameters encoded for a SLTP stop order (stop_order_type code 0):
224            /// - clearing_house_id: ID
225            /// - expire_timestamp: Option<u64>
226            /// - is_limit_order: `true` if limit order, `false` if market order
227            /// - stop_index_price: u256
228            /// - is_stop_loss: `true` if stop loss order, `false` if take profit order
229            /// - position_is_ask: `true` if position is short, `false` if position is long
230            /// - size: u64
231            /// - price: u64 (can be set at random value if `is_limit_order` is false)
232            /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
233            /// - salt: vector<u8>
234            ///
235            /// Parameters encoded for a Standalone stop order (stop_order_type code 1):
236            /// - clearing_house_id: ID
237            /// - expire_timestamp: Option<u64>
238            /// - is_limit_order: `true` if limit order, `false` if market order
239            /// - stop_index_price: u256
240            /// - ge_stop_index_price: `true` means the order can be placed when
241            /// oracle index price is >= than chosen `stop_index_price`
242            /// - side: bool
243            /// - size: u64
244            /// - price: u64 (can be set at random value if `is_limit_order` is false)
245            /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
246            /// - reduce_only: bool
247            /// - salt: vector<u8>
248            encrypted_details: vector<u8>
249        }
250    }
251
252    module events {
253        struct CreatedAccount<!phantom T> has copy, drop {
254            account_obj_id: ID,
255            user: address,
256            account_id: u64
257        }
258
259        struct DepositedCollateral<!phantom T> has copy, drop {
260            account_id: u64,
261            collateral: u64,
262        }
263
264        struct AllocatedCollateral has copy, drop {
265            ch_id: ID,
266            account_id: u64,
267            collateral: u64,
268        }
269
270        struct WithdrewCollateral<!phantom T> has copy, drop {
271            account_id: u64,
272            collateral: u64,
273        }
274
275        struct DeallocatedCollateral has copy, drop {
276            ch_id: ID,
277            account_id: u64,
278            collateral: u64,
279        }
280
281        struct CreatedOrderbook has copy, drop {
282            branch_min: u64,
283            branches_merge_max: u64,
284            branch_max: u64,
285            leaf_min: u64,
286            leaves_merge_max: u64,
287            leaf_max: u64
288        }
289
290        struct CreatedClearingHouse has copy, drop {
291            ch_id: ID,
292            collateral: String,
293            coin_decimals: u64,
294            margin_ratio_initial: IFixed,
295            margin_ratio_maintenance: IFixed,
296            base_oracle_id: ID,
297            collateral_oracle_id: ID,
298            funding_frequency_ms: u64,
299            funding_period_ms: u64,
300            premium_twap_frequency_ms: u64,
301            premium_twap_period_ms: u64,
302            spread_twap_frequency_ms: u64,
303            spread_twap_period_ms: u64,
304            maker_fee: IFixed,
305            taker_fee: IFixed,
306            liquidation_fee: IFixed,
307            force_cancel_fee: IFixed,
308            insurance_fund_fee: IFixed,
309            lot_size: u64,
310            tick_size: u64,
311        }
312
313        struct RegisteredMarketInfo<!phantom T> has copy, drop {
314            ch_id: ID,
315            base_pfs_id: ID,
316            collateral_pfs_id: ID,
317            lot_size: u64,
318            tick_size: u64,
319            scaling_factor: IFixed
320        }
321
322        struct RemovedRegisteredMarketInfo<!phantom T> has copy, drop {
323            ch_id: ID,
324        }
325
326        struct RegisteredCollateralInfo<!phantom T> has copy, drop {
327            ch_id: ID,
328            collateral_pfs_id: ID,
329            scaling_factor: IFixed
330        }
331
332        struct AddedIntegratorConfig<!phantom T> has copy, drop {
333            account_id: u64,
334            integrator_address: address,
335            max_taker_fee: IFixed
336        }
337
338        struct RemovedIntegratorConfig<!phantom T> has copy, drop {
339            account_id: u64,
340            integrator_address: address,
341        }
342
343        struct PaidIntegratorFees<!phantom T> has copy, drop {
344            account_id: u64,
345            integrator_address: address,
346            fees: IFixed
347        }
348
349        struct CreatedIntegratorVault has copy, drop {
350            ch_id: ID,
351            integrator_address: address,
352        }
353
354        struct WithdrewFromIntegratorVault has copy, drop {
355            ch_id: ID,
356            integrator_address: address,
357            fees: u64
358        }
359
360        struct UpdatedClearingHouseVersion has copy, drop {
361            ch_id: ID,
362            version: u64
363        }
364
365        struct UpdatedPremiumTwap has copy, drop {
366            ch_id: ID,
367            book_price: IFixed,
368            index_price: IFixed,
369            premium_twap: IFixed,
370            premium_twap_last_upd_ms: u64,
371        }
372
373        struct UpdatedSpreadTwap has copy, drop {
374            ch_id: ID,
375            book_price: IFixed,
376            index_price: IFixed,
377            spread_twap: IFixed,
378            spread_twap_last_upd_ms: u64,
379        }
380
381        struct UpdatedGasPriceTwap has copy, drop {
382            ch_id: ID,
383            gas_price: IFixed,
384            mean: IFixed,
385            variance: IFixed,
386            gas_price_last_upd_ms: u64
387        }
388
389        struct UpdatedGasPriceTwapParameters has copy, drop {
390            ch_id: ID,
391            gas_price_twap_period_ms: u64,
392            gas_price_taker_fee: IFixed,
393            z_score_threshold: IFixed
394        }
395
396        struct UpdatedMarketLotAndTick has copy, drop {
397            ch_id: ID,
398            lot_size: u64,
399            tick_size: u64
400        }
401
402        struct UpdatedFunding has copy, drop {
403            ch_id: ID,
404            cum_funding_rate_long: IFixed,
405            cum_funding_rate_short: IFixed,
406            funding_last_upd_ms: u64,
407        }
408
409        struct SettledFunding has copy, drop {
410            ch_id: ID,
411            account_id: u64,
412            collateral_change_usd: IFixed,
413            collateral_after: IFixed,
414            mkt_funding_rate_long: IFixed,
415            mkt_funding_rate_short: IFixed
416        }
417
418        struct FilledMakerOrders has copy, drop {
419            events: vector<FilledMakerOrder>
420        }
421
422        struct FilledMakerOrder has copy, drop {
423            ch_id: ID,
424            maker_account_id: u64,
425            taker_account_id: u64,
426            order_id: u128,
427            filled_size: u64,
428            remaining_size: u64,
429            canceled_size: u64,
430            pnl: IFixed,
431            fees: IFixed,
432        }
433
434        struct FilledTakerOrder has copy, drop {
435            ch_id: ID,
436            taker_account_id: u64,
437            taker_pnl: IFixed,
438            taker_fees: IFixed,
439            integrator_taker_fees: IFixed,
440            integrator_address: Option<address>,
441            base_asset_delta_ask: IFixed,
442            quote_asset_delta_ask: IFixed,
443            base_asset_delta_bid: IFixed,
444            quote_asset_delta_bid: IFixed,
445        }
446
447        struct PostedOrder has copy, drop {
448            ch_id: ID,
449            account_id: u64,
450            order_id: u128,
451            order_size: u64,
452            reduce_only: bool,
453            expiration_timestamp_ms: Option<u64>
454        }
455
456        struct CanceledOrder has copy, drop {
457            ch_id: ID,
458            account_id: u64,
459            size: u64,
460            order_id: u128,
461        }
462
463        struct LiquidatedPosition has copy, drop {
464            ch_id: ID,
465            liqee_account_id: u64,
466            liqor_account_id: u64,
467            is_liqee_long: bool,
468            base_liquidated: IFixed,
469            quote_liquidated: IFixed,
470            liqee_pnl: IFixed,
471            liquidation_fees: IFixed,
472            force_cancel_fees: IFixed,
473            insurance_fund_fees: IFixed,
474            bad_debt: IFixed
475        }
476
477        struct PerformedLiquidation has copy, drop {
478            ch_id: ID,
479            liqee_account_id: u64,
480            liqor_account_id: u64,
481            is_liqee_long: bool,
482            base_liquidated: IFixed,
483            quote_liquidated: IFixed,
484            liqor_pnl: IFixed,
485            liqor_fees: IFixed,
486        }
487
488        struct UpdatedCumFundings has copy, drop {
489            ch_id: ID,
490            cum_funding_rate_long: IFixed,
491            cum_funding_rate_short: IFixed,
492        }
493
494        struct CreatedPosition has copy, drop {
495            ch_id: ID,
496            account_id: u64,
497            mkt_funding_rate_long: IFixed,
498            mkt_funding_rate_short: IFixed,
499        }
500
501        struct SetPositionInitialMarginRatio has copy, drop {
502            ch_id: ID,
503            account_id: u64,
504            initial_margin_ratio: IFixed,
505        }
506
507        struct CreatedStopOrderTicket<!phantom T> has copy, drop {
508            ticket_id: ID,
509            account_id: u64,
510            executors: vector<address>,
511            gas: u64,
512            stop_order_type: u64,
513            encrypted_details: vector<u8>
514        }
515
516        struct ExecutedStopOrderTicket<!phantom T> has copy, drop {
517            ticket_id: ID,
518            account_id: u64,
519            executor: address
520        }
521
522        struct DeletedStopOrderTicket<!phantom T> has copy, drop {
523            ticket_id: ID,
524            account_id: u64,
525            executor: address
526        }
527
528        struct EditedStopOrderTicketDetails<!phantom T> has copy, drop {
529            ticket_id: ID,
530            account_id: u64,
531            stop_order_type: u64,
532            encrypted_details: vector<u8>
533        }
534
535        struct EditedStopOrderTicketExecutors<!phantom T> has copy, drop {
536            ticket_id: ID,
537            account_id: u64,
538            executors: vector<address>
539        }
540
541        struct CreatedMarginRatiosProposal has copy, drop {
542            ch_id: ID,
543            margin_ratio_initial: IFixed,
544            margin_ratio_maintenance: IFixed,
545        }
546
547        struct UpdatedMarginRatios has copy, drop {
548            ch_id: ID,
549            margin_ratio_initial: IFixed,
550            margin_ratio_maintenance: IFixed,
551        }
552
553        struct DeletedMarginRatiosProposal has copy, drop {
554            ch_id: ID,
555            margin_ratio_initial: IFixed,
556            margin_ratio_maintenance: IFixed,
557        }
558
559        struct CreatedPositionFeesProposal has copy, drop {
560            ch_id: ID,
561            account_id: u64,
562            maker_fee: IFixed,
563            taker_fee: IFixed,
564        }
565
566        struct DeletedPositionFeesProposal has copy, drop {
567            ch_id: ID,
568            account_id: u64,
569            maker_fee: IFixed,
570            taker_fee: IFixed,
571        }
572
573        struct AcceptedPositionFeesProposal has copy, drop {
574            ch_id: ID,
575            account_id: u64,
576            maker_fee: IFixed,
577            taker_fee: IFixed,
578        }
579
580        struct RejectedPositionFeesProposal has copy, drop {
581            ch_id: ID,
582            account_id: u64,
583            maker_fee: IFixed,
584            taker_fee: IFixed,
585        }
586
587        struct ResettedPositionFees has copy, drop {
588            ch_id: ID,
589            account_id: u64,
590        }
591
592        struct UpdatedFees has copy, drop {
593            ch_id: ID,
594            maker_fee: IFixed,
595            taker_fee: IFixed,
596            liquidation_fee: IFixed,
597            force_cancel_fee: IFixed,
598            insurance_fund_fee: IFixed,
599        }
600
601        struct UpdatedFundingParameters has copy, drop {
602            ch_id: ID,
603            funding_frequency_ms: u64,
604            funding_period_ms: u64,
605            premium_twap_frequency_ms: u64,
606            premium_twap_period_ms: u64,
607        }
608
609        struct UpdatedSpreadTwapParameters has copy, drop {
610            ch_id: ID,
611            spread_twap_frequency_ms: u64,
612            spread_twap_period_ms: u64
613        }
614
615        struct UpdatedMinOrderUsdValue has copy, drop {
616            ch_id: ID,
617            min_order_usd_value: IFixed,
618        }
619
620        struct UpdatedBaseOracleTolerance has copy, drop {
621            ch_id: ID,
622            oracle_tolerance: u64,
623        }
624
625        struct UpdatedCollateralOracleTolerance has copy, drop {
626            ch_id: ID,
627            oracle_tolerance: u64,
628        }
629
630        struct UpdatedMaxOpenInterest has copy, drop {
631            ch_id: ID,
632            max_open_interest: IFixed,
633        }
634
635        struct UpdatedMaxOpenInterestPositionParams has copy, drop {
636            ch_id: ID,
637            max_open_interest_threshold: IFixed,
638            max_open_interest_position_percent: IFixed,
639        }
640
641        struct UpdatedMaxPendingOrders has copy, drop {
642            ch_id: ID,
643            max_pending_orders: u64
644        }
645
646        struct UpdatedStopOrderMistCost has copy, drop {
647            stop_order_mist_cost: u64
648        }
649
650        struct DonatedToInsuranceFund has copy, drop {
651            sender: address,
652            ch_id: ID,
653            new_balance: u64,
654        }
655
656        struct WithdrewFees has copy, drop {
657            sender: address,
658            ch_id: ID,
659            amount: u64,
660            vault_balance_after: u64,
661        }
662
663        struct WithdrewInsuranceFund has copy, drop {
664            sender: address,
665            ch_id: ID,
666            amount: u64,
667            insurance_fund_balance_after: u64,
668        }
669
670        struct UpdatedOpenInterestAndFeesAccrued has copy, drop {
671            ch_id: ID,
672            open_interest: IFixed,
673            fees_accrued: IFixed
674        }
675    }
676
677    module keys {
678        /// Key type for accessing a `MarketInfo` saved in registry.
679        struct RegistryMarketInfo has copy, drop, store {
680            ch_id: ID
681        }
682
683        /// Key type for accessing a `CollateralInfo` saved in registry.
684        struct RegistryCollateralInfo<!phantom T> has copy, drop, store {}
685
686        /// Key type for accessing a `Config` saved in registry.
687        struct RegistryConfig has copy, drop, store {}
688
689        /// Key type for accessing integrator configs for an account.
690        struct IntegratorConfig has copy, drop, store {
691            integrator_address: address,
692        }
693
694        /// Key type for accessing integrator's collected fees.
695        struct IntegratorVault has copy, drop, store {
696            integrator_address: address,
697        }
698
699        /// Key type for accessing market params in clearing house.
700        struct Orderbook has copy, drop, store {}
701
702        /// Key type for accessing vault in clearing house.
703        struct MarketVault has copy, drop, store {}
704
705        /// Key type for accessing trader position in clearing house.
706        struct Position has copy, drop, store {
707            account_id: u64,
708        }
709
710        /// Key type for accessing market margin parameters change proposal in clearing house.
711        struct MarginRatioProposal has copy, drop, store {}
712
713        /// Key type for accessing custom fees parameters change proposal for an account
714        struct PositionFeesProposal has copy, drop, store {
715            account_id: u64
716        }
717
718        /// Key type for accessing asks map in the orderbook
719        struct AsksMap has copy, drop, store {}
720
721        /// Key type for accessing asks map in the orderbook
722        struct BidsMap has copy, drop, store {}
723    }
724
725    module market {
726        /// Static attributes of a perpetuals market.
727        struct MarketParams has copy, drop, store {
728            /// Minimum margin ratio for opening a new position.
729            margin_ratio_initial: IFixed,
730            /// Margin ratio below which full liquidations can occur.
731            margin_ratio_maintenance: IFixed,
732            /// Identifier of the base asset's price feed storage.
733            base_pfs_id: ID,
734            /// Identifier of the collateral asset's price feed storage.
735            collateral_pfs_id: ID,
736            /// The time span between each funding rate update.
737            funding_frequency_ms: u64,
738            /// Period of time over which funding (the difference between book and
739            /// index prices) gets paid.
740            ///
741            /// Setting the funding period too long may cause the perpetual to start
742            /// trading at a very dislocated price to the index because there's less
743            /// of an incentive for basis arbitrageurs to push the prices back in
744            /// line since they would have to carry the basis risk for a longer
745            /// period of time.
746            ///
747            /// Setting the funding period too short may cause nobody to trade the
748            /// perpetual because there's too punitive of a price to pay in the case
749            /// the funding rate flips sign.
750            funding_period_ms: u64,
751            /// The time span between each funding TWAP (both index price and orderbook price) update.
752            premium_twap_frequency_ms: u64,
753            /// The reference time span used for weighting the TWAP (both index price and orderbook price)
754            /// updates for funding rates estimation
755            premium_twap_period_ms: u64,
756            /// The time span between each spread TWAP updates (used for liquidations).
757            spread_twap_frequency_ms: u64,
758            /// The reference time span used for weighting the TWAP updates for spread.
759            spread_twap_period_ms: u64,
760            /// The reference time span used for weighting the TWAP updates for gas price.
761            gas_price_twap_period_ms: u64,
762            /// Proportion of volume charged as fees from makers upon processing
763            /// fill events.
764            maker_fee: IFixed,
765            /// Proportion of volume charged as fees from takers after processing
766            /// fill events.
767            taker_fee: IFixed,
768            /// Proportion of volume charged as fees from liquidatees
769            liquidation_fee: IFixed,
770            /// Proportion of volume charged as fees from liquidatees after forced cancelling
771            /// of pending orders during liquidation.
772            force_cancel_fee: IFixed,
773            /// Proportion of volume charged as fees from liquidatees to deposit into insurance fund
774            insurance_fund_fee: IFixed,
775            /// Minimum USD value an order is required to be worth to be placed
776            min_order_usd_value: IFixed,
777            /// Number of base units exchanged per lot
778            lot_size: u64,
779            /// Number of quote units exchanged per tick
780            tick_size: u64,
781            /// Maximum number of pending orders that a position can have.
782            max_pending_orders: u64,
783            /// Timestamp tolerance for base oracle price
784            base_oracle_tolerance: u64,
785            /// Timestamp tolerance for collateral oracle price
786            collateral_oracle_tolerance: u64,
787            /// Max open interest (in base tokens) available for this market
788            max_open_interest: IFixed,
789            /// The check on `max_open_interest_position_percent` is not performed if
790            /// the market's open interest is below this threshold.
791            max_open_interest_threshold: IFixed,
792            /// Max open interest percentage a position can have relative to total market's open interest
793            max_open_interest_position_percent: IFixed,
794            /// Scaling factor to use to convert collateral units to ifixed values and viceversa
795            scaling_factor: IFixed,
796            /// Additional taker fee to apply in case the gas price set for the transaction violates
797            /// the z-score constraint
798            gas_price_taker_fee: IFixed,
799            /// Z-Score threshold level used to determine if to apply `gas_price_taker_fee` to the
800            /// executed order
801            z_score_threshold: IFixed,
802        }
803
804        /// The state of a perpetuals market.
805        struct MarketState has store {
806            /// The latest cumulative funding premium in this market for longs. Must be updated
807            /// periodically.
808            cum_funding_rate_long: IFixed,
809            /// The latest cumulative funding premium in this market for shorts. Must be updated
810            /// periodically.
811            cum_funding_rate_short: IFixed,
812            /// The timestamp (millisec) of the latest cumulative funding premium update
813            /// (both longs and shorts).
814            funding_last_upd_ms: u64,
815            /// The last calculated funding premium TWAP (used for funding settlement).
816            premium_twap: IFixed,
817            /// The timestamp (millisec) of the last update of `premium_twap`.
818            premium_twap_last_upd_ms: u64,
819            /// The last calculated spread TWAP (used for liquidations).
820            /// Spread is (book - index).
821            spread_twap: IFixed,
822            /// The timestamp (millisec) of `spread_twap` last update.
823            spread_twap_last_upd_ms: u64,
824            /// Gas price TWAP mean.
825            /// It is used to calculate the penalty to add to taker fees based on the Z-score of the current gas price
826            /// relative to the smoothed mean and variance.
827            gas_price_mean: IFixed,
828            /// Gas price TWAP variance.
829            /// It is used to calculate the penalty to add to taker fees based on the Z-score of the current gas price
830            /// relative to the smoothed mean and variance.
831            gas_price_variance: IFixed,
832            /// The timestamp (millisec) of the last update of `gas_price_mean` and `gas_price_variance`.
833            gas_price_last_upd_ms: u64,
834            /// Open interest (in base tokens) as a fixed-point number. Counts the
835            /// total size of contracts as the sum of all long positions.
836            open_interest: IFixed,
837            /// Total amount of fees accrued by this market (in T's units)
838            /// Only admin can withdraw these fees.
839            fees_accrued: IFixed,
840        }
841    }
842
843    module orderbook {
844        /// An order on the orderbook
845        struct Order has copy, drop, store {
846            /// User's account id
847            account_id: u64,
848            /// Amount of lots to be filled
849            size: u64,
850            /// Optional reduce-only requirement for this order.
851            reduce_only: bool,
852            /// Optional expiration time for the order
853            expiration_timestamp_ms: Option<u64>
854        }
855
856        /// The orderbook doesn't know the types of tokens traded, it assumes a correct
857        /// management by the clearing house
858        struct Orderbook has key, store {
859            id: UID,
860            /// Number of limit orders placed on book, monotonically increases
861            counter: u64,
862        }
863    }
864
865    module ordered_map {
866        /// Ordered map with `u128` type as a key and `V` type as a value.
867        struct Map<!phantom V: copy + drop + store> has key, store {
868            /// Object UID for adding dynamic fields that are used as pointers to nodes.
869            id: UID,
870            /// Number of key-value pairs in the map.
871            size: u64,
872            /// Counter for creating another node as a dynamic field.
873            counter: u64,
874            /// Pointer to the root node, which is a branch or a leaf.
875            root: u64,
876            /// Pointer to first leaf.
877            first: u64,
878            /// Minimal number of kids in a non-root branch;
879            /// must satisfy 2 <= branch_min <= branch_max / 2.
880            branch_min: u64,
881            /// Maximal number of kids in a branch, which is merge of two branches;
882            /// must satisfy 2 * branch_min <= branches_merge_max <= branch_max.
883            branches_merge_max: u64,
884            /// Maximal number of kids in a branch.
885            branch_max: u64,
886            /// Minimal number of elements in a non-root leaf;
887            /// must satisfy 2 <= leaf_min <= (leaf_max + 1) / 2.
888            leaf_min: u64,
889            /// Maximal number of elements in a leaf, which is merge of two leaves;
890            /// must satisfy 2 * leaf_min - 1 <= leaves_merge_max <= leaf_max.
891            leaves_merge_max: u64,
892            /// Maximal number of elements in a leaf.
893            leaf_max: u64,
894        }
895
896        /// Branch node with kids and ordered separating keys.
897        struct Branch has drop, store {
898            /// Separating keys for kids sorted in ascending order.
899            keys: vector<u128>,
900            /// Kids of the node.
901            kids: vector<u64>,
902        }
903
904        /// Key-value pair.
905        struct Pair<V: copy + drop + store> has copy, drop, store {
906            key: u128,
907            val: V,
908        }
909
910        /// Leaf node with ordered key-value pairs.
911        struct Leaf<V: copy + drop + store> has drop, store {
912            /// Keys sorted in ascending order together with values.
913            keys_vals: vector<Pair<V>>,
914            /// Pointer to next leaf.
915            next: u64,
916        }
917    }
918
919    module position {
920        /// Stores information about an open position
921        struct Position has store {
922            /// Amount of allocated tokens (e.g., USD stables) backing this account's position.
923            collateral: IFixed,
924            /// The perpetual contract size, controlling the amount of exposure to
925            /// the underlying asset. Positive implies long position and negative,
926            /// short. Represented as a signed fixed-point number.
927            base_asset_amount: IFixed,
928            /// The entry value for this position, including leverage. Represented
929            /// as a signed fixed-point number.
930            quote_asset_notional_amount: IFixed,
931            /// Last long cumulative funding rate used to update this position. The
932            /// market's latest long cumulative funding rate minus this gives the funding
933            /// rate this position must pay. This rate multiplied by this position's
934            /// value (base asset amount * market price) gives the total funding
935            /// owed, which is deducted from the trader account's margin. This debt
936            /// is accounted for in margin ratio calculations, which may lead to
937            /// liquidation. Represented as a signed fixed-point number.
938            cum_funding_rate_long: IFixed,
939            /// Last short cumulative funding rate used to update this position. The
940            /// market's latest short cumulative funding rate minus this gives the funding
941            /// rate this position must pay. This rate multiplied by this position's
942            /// value (base asset amount * market price) gives the total funding
943            /// owed, which is deducted from the trader account's margin. This debt
944            /// is accounted for in margin ratio calculations, which may lead to
945            /// liquidation. Represented as a signed fixed-point number.
946            cum_funding_rate_short: IFixed,
947            /// Base asset amount resting in ask orders in the orderbook.
948            /// Represented as a signed fixed-point number.
949            asks_quantity: IFixed,
950            /// Base asset amount resting in bid orders in the orderbook.
951            /// Represented as a signed fixed-point number.
952            bids_quantity: IFixed,
953            /// Number of pending orders in this position.
954            pending_orders: u64,
955            /// Custom maker fee for this position, set at default value of 100%
956            maker_fee: IFixed,
957            /// Custom taker fee for this position, set at default value of 100%
958            taker_fee: IFixed,
959            /// Initial Margin Ratio set by user for the position. Must always be less
960            /// or equal than market's IMR. Used as a desired reference margin ratio when
961            /// managing collateral in the position during all the actions. Can be changed
962            /// by the user at any moment (between the allowed limits).
963            initial_margin_ratio: IFixed
964        }
965    }
966
967    module registry {
968        /// Registry object that maintains:
969        /// - A mapping between a clearing house id and `MarketInfo`
970        /// - A mapping between a collateral type `T` and `CollateralInfo`
971        /// It also maintains the global counter for account creation.
972        /// Minted and shared when the module is published.
973        struct Registry has key {
974            id: UID,
975            next_account_id: u64
976        }
977
978        /// Struct containing all the immutable info about a registered market
979        struct MarketInfo<!phantom T> has store {
980            base_pfs_id: ID,
981            collateral_pfs_id: ID,
982            lot_size: u64,
983            tick_size: u64,
984            scaling_factor: IFixed
985        }
986
987        /// Struct containing all the immutable info about the collateral
988        /// used in one or more markets
989        struct CollateralInfo<!phantom T> has store {
990            collateral_pfs_id: ID,
991            scaling_factor: IFixed
992        }
993
994        /// Config that stores useful info for the protocol
995        struct Config has store {
996            stop_order_mist_cost: u64,
997        }
998    }
999});
1000
1001impl<T: af_move_type::MoveType> clearing_house::ClearingHouse<T> {
1002    /// Convenience function to build the type of a [`PositionDf`].
1003    pub fn position_df_type(package: Address) -> FieldTypeTag<self::keys::Position, Position> {
1004        Field::type_(
1005            self::keys::Position::type_(package),
1006            Position::type_(package),
1007        )
1008    }
1009
1010    /// Convenience function to build the type of an [`OrderbookDofWrapper`].
1011    pub fn orderbook_dof_wrapper_type(
1012        package: Address,
1013    ) -> FieldTypeTag<Wrapper<keys::Orderbook>, ID> {
1014        Field::type_(
1015            Wrapper::type_(keys::Orderbook::type_(package)),
1016            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
1017        )
1018    }
1019
1020    /// The ID of the package that governs this clearing house's logic.
1021    ///
1022    /// This may be different than the package defining the clearing house's type because a package
1023    /// upgrade + `interface::upgrade_clearing_house_version` call can change
1024    /// [`ClearingHouse::version`] so that the upgraded package is the one that is allowed to make
1025    /// changes to it.
1026    ///
1027    /// Attempting to make a PTB Move call that mutates this clearing house but is not defined in
1028    /// this package version will fail.
1029    pub const fn governing_package_testnet(&self) -> Address {
1030        // NOTE: we published the most recent testnet contracts starting with `VERSION = 1`
1031        TESTNET_PACKAGE_VERSIONS[self.version as usize - 1]
1032    }
1033}
1034
1035impl self::orderbook::Orderbook {
1036    /// Convenience function to build the type of an [`AsksMapDofWrapper`].
1037    pub fn asks_dof_wrapper_type(package: Address) -> FieldTypeTag<Wrapper<keys::AsksMap>, ID> {
1038        Field::type_(
1039            Wrapper::type_(keys::AsksMap::type_(package)),
1040            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
1041        )
1042    }
1043
1044    /// Convenience function to build the type of an [`BidsMapDofWrapper`].
1045    pub fn bids_dof_wrapper_type(package: Address) -> FieldTypeTag<Wrapper<keys::BidsMap>, ID> {
1046        Field::type_(
1047            Wrapper::type_(keys::BidsMap::type_(package)),
1048            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
1049        )
1050    }
1051}
1052
1053impl self::ordered_map::Map<Order> {
1054    /// Convenience function to build the type of an [`OrderLeafDf`].
1055    pub fn leaf_df_type(package: Address) -> FieldTypeTag<u64, self::ordered_map::Leaf<Order>> {
1056        Field::type_(
1057            af_move_type::U64TypeTag,
1058            self::ordered_map::Leaf::type_(package, Order::type_(package)),
1059        )
1060    }
1061}
1062
1063#[cfg(test)]
1064mod tests {
1065    /// Taken from
1066    /// <https://github.com/cargo-public-api/cargo-public-api?tab=readme-ov-file#-as-a-ci-check>
1067    #[test]
1068    fn public_api() {
1069        // Install a compatible nightly toolchain if it is missing
1070        rustup_toolchain::install(public_api::MINIMUM_NIGHTLY_RUST_VERSION).unwrap();
1071
1072        // Build rustdoc JSON
1073        let rustdoc_json = rustdoc_json::Builder::default()
1074            .toolchain(public_api::MINIMUM_NIGHTLY_RUST_VERSION)
1075            .build()
1076            .unwrap();
1077
1078        // Derive the public API from the rustdoc JSON
1079        let public_api = public_api::Builder::from_rustdoc_json(rustdoc_json)
1080            .omit_blanket_impls(true)
1081            .omit_auto_trait_impls(true)
1082            .omit_auto_derived_impls(true)
1083            .build()
1084            .unwrap();
1085
1086        // Assert that the public API looks correct
1087        insta::assert_snapshot!(public_api);
1088    }
1089}