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