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 = "stop-orders")]
24pub mod stop_order_helpers;
25
26pub use self::market::{MarketParams, MarketState};
27pub use self::orderbook::Order;
28pub use self::position::Position;
29
30/// Package IDs of the perpetuals contract versions published on testnet, in order of its versions.
31pub const TESTNET_PACKAGE_VERSIONS: &[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        }
107
108        /// Stores the proposed parameters for updating margin ratios
109        struct MarginRatioProposal has store {
110            /// Target timestamp at which to apply the proposed updates
111            maturity: u64,
112            /// Proposed IMR
113            margin_ratio_initial: IFixed,
114            /// Proposed MMR
115            margin_ratio_maintenance: IFixed,
116        }
117
118        /// Stores the proposed parameters for a position's custom fees
119        struct PositionFeesProposal has store {
120            /// Proposed IMR
121            maker_fee: IFixed,
122            /// Proposed MMR
123            taker_fee: IFixed,
124        }
125
126        /// Used by clearing house to check margin when placing an order
127        struct SessionHotPotato<!phantom T> {
128            clearing_house: ClearingHouse<T>,
129            account_id: u64,
130            timestamp_ms: u64,
131            collateral_price: IFixed,
132            index_price: IFixed,
133            book_price: IFixed,
134            margin_before: IFixed,
135            min_margin_before: IFixed,
136            fills: vector<orderbook::FillReceipt>,
137            post: orderbook::PostReceipt,
138            // TODO: Rust's `Option` is perfectly fine here
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 `SubAccount` 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 or by the executor.
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            /// Addresses allowed to execute the order on behalf of the user.
183            executors: vector<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            /// User account id
188            account_id: u64,
189            /// Value to indentify the stop order type. Available values can be found in the
190            /// constants module.
191            stop_order_type: u64,
192            /// Vector containing the blake2b hash obtained from offchain on the stop order parameters.
193            /// Depending on the stop order type value, a different set of parameters is expected to be used.
194            ///
195            /// Parameters encoded for a SLTP stop order (stop_order_type code 0):
196            /// - clearing_house_id: ID
197            /// - expire_timestamp: Option<u64>
198            /// - is_limit_order: `true` if limit order, `false` if market order
199            /// - stop_index_price: u256
200            /// - is_stop_loss: `true` if stop loss order, `false` if take profit order
201            /// - position_is_ask: `true` if position is short, `false` if position is long
202            /// - size: u64
203            /// - price: u64 (can be set at random value if `is_limit_order` is false)
204            /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
205            /// - salt: vector<u8>
206            ///
207            /// Parameters encoded for a Standalone stop order (stop_order_type code 1):
208            /// - clearing_house_id: ID
209            /// - expire_timestamp: Option<u64>
210            /// - is_limit_order: `true` if limit order, `false` if market order
211            /// - stop_index_price: u256
212            /// - ge_stop_index_price: `true` means the order can be placed when
213            /// oracle index price is >= than chosen `stop_index_price`
214            /// - side: bool
215            /// - size: u64
216            /// - price: u64 (can be set at random value if `is_limit_order` is false)
217            /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
218            /// - reduce_only: bool
219            /// - salt: vector<u8>
220            encrypted_details: vector<u8>
221        }
222    }
223
224    module subaccount {
225        /// The SubAccount object represents a shared version of the `Account` object
226        /// with limited access to protocol's features. Being a shared object, it can
227        /// only be used by the addresses specified in the `users` field.
228        /// Only the parent Account can withdraw Coin from a subaccount. The parent account is
229        /// required to specify a Sui address that will be able to use the subaccount on its behalf
230        /// and can change this address at any moment.
231        ///
232        /// Subaccounts are used for trading and depositing, without running into race conditions, i.e.,
233        /// concurrent transactions using the same subaccount can be created and submitted (unlike
234        /// accounts).
235        ///
236        /// The created subaccount will share the primary's account_id. That means it has access to the
237        /// same positions of the primary.
238        ///
239        /// The subaccount's users are then able to:
240        /// - deposit collateral into the subaccount
241        /// - allocate collateral from subaccount to a clearing house
242        /// - use session to trade and liquidate on clearing house
243        /// - cancel pending orders
244        /// - deallocate from a clearing house to a subaccount
245        struct SubAccount<!phantom T> has key, store {
246            id: UID,
247            /// Addresses able to make calls using this `SubAccount`
248            users: vector<address>,
249            /// Numerical value associated to the parent account
250            account_id: u64,
251            /// Balance available to be allocated to markets.
252            collateral: Balance<T>,
253        }
254    }
255
256    module events {
257        struct CreatedAccount<!phantom T> has copy, drop {
258            user: address,
259            account_id: u64
260        }
261
262        struct DepositedCollateral<!phantom T> has copy, drop {
263            account_id: u64,
264            subaccount_id: Option<ID>,
265            collateral: u64,
266        }
267
268        struct AllocatedCollateral has copy, drop {
269            ch_id: ID,
270            account_id: u64,
271            subaccount_id: Option<ID>,
272            collateral: u64,
273        }
274
275        struct WithdrewCollateral<!phantom T> has copy, drop {
276            account_id: u64,
277            subaccount_id: Option<ID>,
278            collateral: u64,
279        }
280
281        struct DeallocatedCollateral has copy, drop {
282            ch_id: ID,
283            account_id: u64,
284            subaccount_id: Option<ID>,
285            collateral: u64,
286        }
287
288        struct CreatedOrderbook has copy, drop {
289            branch_min: u64,
290            branches_merge_max: u64,
291            branch_max: u64,
292            leaf_min: u64,
293            leaves_merge_max: u64,
294            leaf_max: u64
295        }
296
297        struct CreatedClearingHouse has copy, drop {
298            ch_id: ID,
299            collateral: String,
300            coin_decimals: u64,
301            margin_ratio_initial: IFixed,
302            margin_ratio_maintenance: IFixed,
303            base_oracle_id: ID,
304            collateral_oracle_id: ID,
305            funding_frequency_ms: u64,
306            funding_period_ms: u64,
307            premium_twap_frequency_ms: u64,
308            premium_twap_period_ms: u64,
309            spread_twap_frequency_ms: u64,
310            spread_twap_period_ms: u64,
311            maker_fee: IFixed,
312            taker_fee: IFixed,
313            liquidation_fee: IFixed,
314            force_cancel_fee: IFixed,
315            insurance_fund_fee: IFixed,
316            lot_size: u64,
317            tick_size: u64,
318        }
319
320        struct RegisteredMarketInfo<!phantom T> has copy, drop {
321            ch_id: ID,
322            base_pfs_id: ID,
323            collateral_pfs_id: ID,
324            lot_size: u64,
325            tick_size: u64,
326            scaling_factor: IFixed
327        }
328
329        struct RemovedRegisteredMarketInfo<!phantom T> has copy, drop {
330            ch_id: ID,
331        }
332
333        struct RegisteredCollateralInfo<!phantom T> has copy, drop {
334            ch_id: ID,
335            collateral_pfs_id: ID,
336            scaling_factor: IFixed
337        }
338
339        struct UpdatedClearingHouseVersion has copy, drop {
340            ch_id: ID,
341            version: u64
342        }
343
344        struct UpdatedPremiumTwap has copy, drop {
345            ch_id: ID,
346            book_price: IFixed,
347            index_price: IFixed,
348            premium_twap: IFixed,
349            premium_twap_last_upd_ms: u64,
350        }
351
352        struct UpdatedSpreadTwap has copy, drop {
353            ch_id: ID,
354            book_price: IFixed,
355            index_price: IFixed,
356            spread_twap: IFixed,
357            spread_twap_last_upd_ms: u64,
358        }
359
360        struct UpdatedFunding has copy, drop {
361            ch_id: ID,
362            cum_funding_rate_long: IFixed,
363            cum_funding_rate_short: IFixed,
364            funding_last_upd_ms: u64,
365        }
366
367        struct SettledFunding has copy, drop {
368            ch_id: ID,
369            account_id: u64,
370            collateral_change_usd: IFixed,
371            collateral_after: IFixed,
372            mkt_funding_rate_long: IFixed,
373            mkt_funding_rate_short: IFixed
374        }
375
376        struct FilledMakerOrders has copy, drop {
377            events: vector<FilledMakerOrder>
378        }
379
380        struct FilledMakerOrder has copy, drop {
381            ch_id: ID,
382            maker_account_id: u64,
383            taker_account_id: u64,
384            order_id: u128,
385            filled_size: u64,
386            remaining_size: u64,
387            pnl: IFixed,
388            fees: IFixed,
389        }
390
391        struct FilledTakerOrder has copy, drop {
392            ch_id: ID,
393            taker_account_id: u64,
394            taker_pnl: IFixed,
395            taker_fees: IFixed,
396            base_asset_delta_ask: IFixed,
397            quote_asset_delta_ask: IFixed,
398            base_asset_delta_bid: IFixed,
399            quote_asset_delta_bid: IFixed,
400        }
401
402        struct OrderbookPostReceipt has copy, drop {
403            ch_id: ID,
404            account_id: u64,
405            order_id: u128,
406            order_size: u64,
407        }
408
409        struct CanceledOrder has copy, drop {
410            ch_id: ID,
411            account_id: u64,
412            size: u64,
413            order_id: u128,
414        }
415
416        struct LiquidatedPosition has copy, drop {
417            ch_id: ID,
418            liqee_account_id: u64,
419            liqor_account_id: u64,
420            is_liqee_long: bool,
421            base_liquidated: IFixed,
422            quote_liquidated: IFixed,
423            liqee_pnl: IFixed,
424            liquidation_fees: IFixed,
425            force_cancel_fees: IFixed,
426            insurance_fund_fees: IFixed,
427            bad_debt: IFixed
428        }
429
430        struct PerformedLiquidation has copy, drop {
431            ch_id: ID,
432            liqee_account_id: u64,
433            liqor_account_id: u64,
434            is_liqee_long: bool,
435            base_liquidated: IFixed,
436            quote_liquidated: IFixed,
437            liqor_pnl: IFixed,
438            liqor_fees: IFixed,
439        }
440
441        struct UpdatedCumFundings has copy, drop {
442            ch_id: ID,
443            cum_funding_rate_long: IFixed,
444            cum_funding_rate_short: IFixed,
445        }
446
447        struct CreatedPosition has copy, drop {
448            ch_id: ID,
449            account_id: u64,
450            subaccount_id: Option<ID>,
451            mkt_funding_rate_long: IFixed,
452            mkt_funding_rate_short: IFixed,
453        }
454
455        struct SetPositionInitialMarginRatio has copy, drop {
456            ch_id: ID,
457            account_id: u64,
458            initial_margin_ratio: IFixed,
459        }
460
461        struct CreatedStopOrderTicket<!phantom T> has copy, drop {
462            ticket_id: ID,
463            account_id: u64,
464            subaccount_id: Option<ID>,
465            executors: vector<address>,
466            gas: u64,
467            stop_order_type: u64,
468            encrypted_details: vector<u8>
469        }
470
471        struct ExecutedStopOrderTicket<!phantom T> has copy, drop {
472            ticket_id: ID,
473            account_id: u64,
474            executor: address
475        }
476
477        struct DeletedStopOrderTicket<!phantom T> has copy, drop {
478            ticket_id: ID,
479            account_id: u64,
480            subaccount_id: Option<ID>,
481            executor: address
482        }
483
484        struct EditedStopOrderTicketDetails<!phantom T> has copy, drop {
485            ticket_id: ID,
486            account_id: u64,
487            subaccount_id: Option<ID>,
488            stop_order_type: u64,
489            encrypted_details: vector<u8>
490        }
491
492        struct EditedStopOrderTicketExecutors<!phantom T> has copy, drop {
493            ticket_id: ID,
494            account_id: u64,
495            subaccount_id: Option<ID>,
496            executors: vector<address>
497        }
498
499        struct CreatedMarginRatiosProposal has copy, drop {
500            ch_id: ID,
501            margin_ratio_initial: IFixed,
502            margin_ratio_maintenance: IFixed,
503        }
504
505        struct UpdatedMarginRatios has copy, drop {
506            ch_id: ID,
507            margin_ratio_initial: IFixed,
508            margin_ratio_maintenance: IFixed,
509        }
510
511        struct DeletedMarginRatiosProposal has copy, drop {
512            ch_id: ID,
513            margin_ratio_initial: IFixed,
514            margin_ratio_maintenance: IFixed,
515        }
516
517        struct CreatedPositionFeesProposal has copy, drop {
518            ch_id: ID,
519            account_id: u64,
520            maker_fee: IFixed,
521            taker_fee: IFixed,
522        }
523
524        struct DeletedPositionFeesProposal has copy, drop {
525            ch_id: ID,
526            account_id: u64,
527            maker_fee: IFixed,
528            taker_fee: IFixed,
529        }
530
531        struct AcceptedPositionFeesProposal has copy, drop {
532            ch_id: ID,
533            account_id: u64,
534            maker_fee: IFixed,
535            taker_fee: IFixed,
536        }
537
538        struct RejectedPositionFeesProposal has copy, drop {
539            ch_id: ID,
540            account_id: u64,
541            maker_fee: IFixed,
542            taker_fee: IFixed,
543        }
544
545        struct ResettedPositionFees has copy, drop {
546            ch_id: ID,
547            account_id: u64,
548        }
549
550        struct UpdatedFees has copy, drop {
551            ch_id: ID,
552            maker_fee: IFixed,
553            taker_fee: IFixed,
554            liquidation_fee: IFixed,
555            force_cancel_fee: IFixed,
556            insurance_fund_fee: IFixed,
557        }
558
559        struct UpdatedFundingParameters has copy, drop {
560            ch_id: ID,
561            funding_frequency_ms: u64,
562            funding_period_ms: u64,
563            premium_twap_frequency_ms: u64,
564            premium_twap_period_ms: u64,
565        }
566
567        struct UpdatedSpreadTwapParameters has copy, drop {
568            ch_id: ID,
569            spread_twap_frequency_ms: u64,
570            spread_twap_period_ms: u64
571        }
572
573        struct UpdatedMinOrderUsdValue has copy, drop {
574            ch_id: ID,
575            min_order_usd_value: IFixed,
576        }
577
578        struct UpdatedLiquidationTolerance has copy, drop {
579            ch_id: ID,
580            liquidation_tolerance: u64,
581        }
582
583        struct UpdatedBaseOracleTolerance has copy, drop {
584            ch_id: ID,
585            oracle_tolerance: u64,
586        }
587
588        struct UpdatedCollateralOracleTolerance has copy, drop {
589            ch_id: ID,
590            oracle_tolerance: u64,
591        }
592
593        struct UpdatedMaxOpenInterest has copy, drop {
594            ch_id: ID,
595            max_open_interest: IFixed,
596        }
597
598        struct UpdatedMaxOpenInterestPositionParams has copy, drop {
599            ch_id: ID,
600            max_open_interest_threshold: IFixed,
601            max_open_interest_position_percent: IFixed,
602        }
603
604        struct UpdatedMaxPendingOrders has copy, drop {
605            ch_id: ID,
606            max_pending_orders: u64
607        }
608
609        struct UpdatedStopOrderMistCost has copy, drop {
610            stop_order_mist_cost: u64
611        }
612
613        struct DonatedToInsuranceFund has copy, drop {
614            sender: address,
615            ch_id: ID,
616            new_balance: u64,
617        }
618
619        struct WithdrewFees has copy, drop {
620            sender: address,
621            ch_id: ID,
622            amount: u64,
623            vault_balance_after: u64,
624        }
625
626        struct WithdrewInsuranceFund has copy, drop {
627            sender: address,
628            ch_id: ID,
629            amount: u64,
630            insurance_fund_balance_after: u64,
631        }
632
633        struct UpdatedOpenInterestAndFeesAccrued has copy, drop {
634            ch_id: ID,
635            open_interest: IFixed,
636            fees_accrued: IFixed
637        }
638
639        struct CreatedSubAccount has copy, drop {
640            subaccount_id: ID,
641            users: vector<address>,
642            account_id: u64
643        }
644
645        struct SetSubAccountUsers has copy, drop {
646            subaccount_id: ID,
647            users: vector<address>,
648            account_id: u64
649        }
650    }
651
652    module keys {
653        /// Key type for accessing a `MarketInfo` saved in registry.
654        struct RegistryMarketInfo has copy, drop, store {
655            ch_id: ID
656        }
657
658        /// Key type for accessing a `CollateralInfo` saved in registry.
659        struct RegistryCollateralInfo<!phantom T> has copy, drop, store {}
660
661        /// Key type for accessing a `Config` saved in registry.
662        struct RegistryConfig has copy, drop, store {}
663
664        /// Key type for accessing market params in clearing house.
665        struct Orderbook has copy, drop, store {}
666
667        /// Key type for accessing vault in clearing house.
668        struct MarketVault has copy, drop, store {}
669
670        /// Key type for accessing trader position in clearing house.
671        struct Position has copy, drop, store {
672            account_id: u64,
673        }
674
675        /// Key type for accessing market margin parameters change proposal in clearing house.
676        struct MarginRatioProposal has copy, drop, store {}
677
678        /// Key type for accessing custom fees parameters change proposal for an account
679        struct PositionFeesProposal has copy, drop, store {
680            account_id: u64
681        }
682
683        /// Key type for accessing asks map in the orderbook
684        struct AsksMap has copy, drop, store {}
685
686        /// Key type for accessing asks map in the orderbook
687        struct BidsMap has copy, drop, store {}
688    }
689
690    module market {
691        /// Static attributes of a perpetuals market.
692        struct MarketParams has copy, drop, store {
693            /// Minimum margin ratio for opening a new position.
694            margin_ratio_initial: IFixed,
695            /// Margin ratio below which full liquidations can occur.
696            margin_ratio_maintenance: IFixed,
697            /// Identifier of the base asset's price feed storage.
698            base_pfs_id: ID,
699            /// Identifier of the collateral asset's price feed storage.
700            collateral_pfs_id: ID,
701            /// The time span between each funding rate update.
702            funding_frequency_ms: u64,
703            /// Period of time over which funding (the difference between book and
704            /// index prices) gets paid.
705            ///
706            /// Setting the funding period too long may cause the perpetual to start
707            /// trading at a very dislocated price to the index because there's less
708            /// of an incentive for basis arbitrageurs to push the prices back in
709            /// line since they would have to carry the basis risk for a longer
710            /// period of time.
711            ///
712            /// Setting the funding period too short may cause nobody to trade the
713            /// perpetual because there's too punitive of a price to pay in the case
714            /// the funding rate flips sign.
715            funding_period_ms: u64,
716            /// The time span between each funding TWAP (both index price and orderbook price) update.
717            premium_twap_frequency_ms: u64,
718            /// The reference time span used for weighting the TWAP (both index price and orderbook price)
719            /// updates for funding rates estimation
720            premium_twap_period_ms: u64,
721            /// The time span between each spread TWAP updates (used for liquidations).
722            spread_twap_frequency_ms: u64,
723            /// The reference time span used for weighting the TWAP updates for spread.
724            spread_twap_period_ms: u64,
725            /// Proportion of volume charged as fees from makers upon processing
726            /// fill events.
727            maker_fee: IFixed,
728            /// Proportion of volume charged as fees from takers after processing
729            /// fill events.
730            taker_fee: IFixed,
731            /// Proportion of volume charged as fees from liquidatees
732            liquidation_fee: IFixed,
733            /// Proportion of volume charged as fees from liquidatees after forced cancelling
734            /// of pending orders during liquidation.
735            force_cancel_fee: IFixed,
736            /// Proportion of volume charged as fees from liquidatees to deposit into insurance fund
737            insurance_fund_fee: IFixed,
738            /// Minimum USD value an order is required to be worth to be placed
739            min_order_usd_value: IFixed,
740            /// Number of base units exchanged per lot
741            lot_size: u64,
742            /// Number of quote units exchanged per tick
743            tick_size: u64,
744            /// Number of lots in a position that a liquidator may buy in excess of what would be
745            /// strictly required to bring the liqee's account back to IMR.
746            liquidation_tolerance: u64,
747            /// Maximum number of pending orders that a position can have.
748            max_pending_orders: u64,
749            /// Timestamp tolerance for base oracle price
750            base_oracle_tolerance: u64,
751            /// Timestamp tolerance for collateral oracle price
752            collateral_oracle_tolerance: u64,
753            /// Max open interest (in base tokens) available for this market
754            max_open_interest: IFixed,
755            /// The check on `max_open_interest_position_percent` is not performed if
756            /// the market's open interest is below this threshold.
757            max_open_interest_threshold: IFixed,
758            /// Max open interest percentage a position can have relative to total market's open interest
759            max_open_interest_position_percent: IFixed,
760            /// Scaling factor to use to convert collateral units to ifixed values and viceversa
761            scaling_factor: 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            /// Initial Margin Ratio set by user for the position. Must always be less
929            /// or equal than market's IMR. Used as a desired reference margin ratio when
930            /// managing collateral in the position during all the actions. Can be changed
931            /// by the user at any moment (between the allowed limits).
932            initial_margin_ratio: IFixed
933        }
934    }
935
936    module registry {
937        /// Registry object that maintains:
938        /// - A mapping between a clearing house id and `MarketInfo`
939        /// - A mapping between a collateral type `T` and `CollateralInfo`
940        /// It also maintains the global counter for account creation.
941        /// Minted and shared when the module is published.
942        struct Registry has key {
943            id: UID,
944            next_account_id: u64
945        }
946
947        /// Struct containing all the immutable info about a registered market
948        struct MarketInfo<!phantom T> has store {
949            base_pfs_id: ID,
950            collateral_pfs_id: ID,
951            lot_size: u64,
952            tick_size: u64,
953            scaling_factor: IFixed
954        }
955
956        /// Struct containing all the immutable info about the collateral
957        /// used in one or more markets
958        struct CollateralInfo<!phantom T> has store {
959            collateral_pfs_id: ID,
960            scaling_factor: IFixed
961        }
962
963        /// Config that stores useful info for the protocol
964        struct Config has store {
965            stop_order_mist_cost: u64,
966        }
967    }
968});
969
970impl<T: af_move_type::MoveType> clearing_house::ClearingHouse<T> {
971    /// Convenience function to build the type of a [`PositionDf`].
972    pub fn position_df_type(package: Address) -> FieldTypeTag<self::keys::Position, Position> {
973        Field::type_(
974            self::keys::Position::type_(package),
975            Position::type_(package),
976        )
977    }
978
979    /// Convenience function to build the type of an [`OrderbookDofWrapper`].
980    pub fn orderbook_dof_wrapper_type(
981        package: Address,
982    ) -> FieldTypeTag<Wrapper<keys::Orderbook>, ID> {
983        Field::type_(
984            Wrapper::type_(keys::Orderbook::type_(package)),
985            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
986        )
987    }
988
989    /// The ID of the package that governs this clearing house's logic.
990    ///
991    /// This may be different than the package defining the clearing house's type because a package
992    /// upgrade + `interface::upgrade_clearing_house_version` call can change
993    /// [`ClearingHouse::version`] so that the upgraded package is the one that is allowed to make
994    /// changes to it.
995    ///
996    /// Attempting to make a PTB Move call that mutates this clearing house but is not defined in
997    /// this package version will fail.
998    pub const fn governing_package_testnet(&self) -> ObjectId {
999        // NOTE: we published the most recent testnet contracts starting with `VERSION = 1`
1000        TESTNET_PACKAGE_VERSIONS[self.version as usize - 1]
1001    }
1002}
1003
1004impl self::orderbook::Orderbook {
1005    /// Convenience function to build the type of an [`AsksMapDofWrapper`].
1006    pub fn asks_dof_wrapper_type(package: Address) -> FieldTypeTag<Wrapper<keys::AsksMap>, ID> {
1007        Field::type_(
1008            Wrapper::type_(keys::AsksMap::type_(package)),
1009            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
1010        )
1011    }
1012
1013    /// Convenience function to build the type of an [`BidsMapDofWrapper`].
1014    pub fn bids_dof_wrapper_type(package: Address) -> FieldTypeTag<Wrapper<keys::BidsMap>, ID> {
1015        Field::type_(
1016            Wrapper::type_(keys::BidsMap::type_(package)),
1017            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
1018        )
1019    }
1020}
1021
1022impl self::ordered_map::Map<Order> {
1023    /// Convenience function to build the type of an [`OrderLeafDf`].
1024    pub fn leaf_df_type(package: Address) -> FieldTypeTag<u64, self::ordered_map::Leaf<Order>> {
1025        Field::type_(
1026            af_move_type::U64TypeTag,
1027            self::ordered_map::Leaf::type_(package, Order::type_(package)),
1028        )
1029    }
1030}
1031
1032#[cfg(test)]
1033mod tests {
1034    /// Taken from
1035    /// <https://github.com/cargo-public-api/cargo-public-api?tab=readme-ov-file#-as-a-ci-check>
1036    #[test]
1037    fn public_api() {
1038        // Install a compatible nightly toolchain if it is missing
1039        rustup_toolchain::install(public_api::MINIMUM_NIGHTLY_RUST_VERSION).unwrap();
1040
1041        // Build rustdoc JSON
1042        let rustdoc_json = rustdoc_json::Builder::default()
1043            .toolchain(public_api::MINIMUM_NIGHTLY_RUST_VERSION)
1044            .build()
1045            .unwrap();
1046
1047        // Derive the public API from the rustdoc JSON
1048        let public_api = public_api::Builder::from_rustdoc_json(rustdoc_json)
1049            .omit_blanket_impls(true)
1050            .omit_auto_trait_impls(true)
1051            .omit_auto_derived_impls(true)
1052            .build()
1053            .unwrap();
1054
1055        // Assert that the public API looks correct
1056        insta::assert_snapshot!(public_api);
1057    }
1058}