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