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