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 AccountCap = self::account::AccountCap<Otw>;
38pub type AccountCapTypeTag = self::account::AccountCapTypeTag<Otw>;
39pub type Account = self::account::Account<Otw>;
40pub type AccountTypeTag = self::account::AccountTypeTag<Otw>;
41pub type StopOrderTicket = self::stop_orders::StopOrderTicket<Otw>;
42pub type StopOrderTicketTypetag = self::stop_orders::StopOrderTicketTypeTag<Otw>;
43pub type ClearingHouse = self::clearing_house::ClearingHouse<Otw>;
44pub type ClearingHouseTypeTag = self::clearing_house::ClearingHouseTypeTag<Otw>;
45pub type Vault = self::clearing_house::Vault<Otw>;
46pub type VaultTypeTag = self::clearing_house::VaultTypeTag<Otw>;
47
48/// Dynamic field storing a [`Position`].
49pub type PositionDf = Field<self::keys::Position, Position>;
50/// Dynamic field storing a leaf in a [`Map`] of [`Order`]s.
51///
52/// [`Map`]: self::ordered_map::Map
53pub type OrderLeafDf = Field<u64, self::ordered_map::Leaf<Order>>;
54/// Dynamic object field wrapper for the [`Orderbook`](orderbook::Orderbook) ID.
55pub type OrderbookDofWrapper = Field<Wrapper<keys::Orderbook>, ID>;
56/// Dynamic object field wrapper for the asks [`Map`](ordered_map::Map) ID.
57pub type AsksMapDofWrapper = Field<Wrapper<keys::AsksMap>, ID>;
58/// Dynamic object field wrapper for the bids [`Map`](ordered_map::Map) ID.
59pub type BidsMapDofWrapper = Field<Wrapper<keys::BidsMap>, ID>;
60
61sui_pkg_sdk!(perpetuals {
62    module account {
63        /// The AccountCap is used to check ownership of `Account` with the same `account_id`.
64        struct AccountCap<!phantom T> has key, store {
65            id: UID,
66            // Account object id
67            account_obj_id: ID,
68            /// Numerical value associated to the account
69            account_id: u64,
70        }
71
72        /// The Account object saves the collateral available to be used in clearing houses.
73        struct Account<!phantom T> has key, store {
74            id: UID,
75            /// Numerical value associated to the account
76            account_id: u64,
77            /// Balance available to be allocated to markets.
78            collateral: Balance<T>,
79        }
80
81        struct IntegratorConfig has store {
82            /// Max **additional** taker fee the user is willing
83            /// to pay for integrator-submitted orders.
84            max_taker_fee: IFixed
85        }
86    }
87
88    module admin {
89        /// Capability object required to perform admin functions.
90        ///
91        /// Minted once when the module is published and transfered to its creator.
92        struct AdminCapability has key, store {
93            id: UID
94        }
95    }
96
97    module clearing_house {
98        /// The central object that owns the market state.
99        ///
100        /// Dynamic fields:
101        /// - [`position::Position`]
102        /// - [`Vault`]
103        ///
104        /// Dynamic objects:
105        /// - [`orderbook::Orderbook`]
106        struct ClearingHouse<!phantom T> has key {
107            id: UID,
108            version: u64,
109            market_params: market::MarketParams,
110            market_state: market::MarketState
111        }
112
113        /// Stores all deposits from traders for collateral T.
114        /// Stores the funds reserved for covering bad debt from untimely
115        /// liquidations.
116        ///
117        /// The Clearing House keeps track of who owns each share of the vault.
118        struct Vault<!phantom T> has store {
119            collateral_balance: Balance<T>,
120            insurance_fund_balance: Balance<T>,
121        }
122
123        /// Stores the proposed parameters for updating margin ratios
124        struct MarginRatioProposal has store {
125            /// Target timestamp at which to apply the proposed updates
126            maturity: u64,
127            /// Proposed IMR
128            margin_ratio_initial: IFixed,
129            /// Proposed MMR
130            margin_ratio_maintenance: IFixed,
131        }
132
133        /// Stores the proposed parameters for a position's custom fees
134        struct PositionFeesProposal has store {
135            /// Proposed IMR
136            maker_fee: IFixed,
137            /// Proposed MMR
138            taker_fee: IFixed,
139        }
140
141        /// Structure that stores the amount of fees collected by an integrator
142        struct IntegratorVault has store {
143            /// Amount of fees collected by this integrator, in collateral units
144            fees: IFixed,
145        }
146
147        struct IntegratorInfo has copy, drop {
148            integrator_address: address,
149            taker_fee: u256,
150        }
151
152        /// Used by clearing house to check margin when placing an order
153        struct SessionHotPotato<!phantom T> {
154            clearing_house: ClearingHouse<T>,
155            orderbook: orderbook::Orderbook,
156            account_id: u64,
157            timestamp_ms: u64,
158            collateral_price: IFixed,
159            index_price: IFixed,
160            gas_price: u64,
161            margin_before: IFixed,
162            min_margin_before: IFixed,
163            position_base_before: IFixed,
164            total_open_interest: IFixed,
165            total_fees: IFixed,
166            maker_events: vector<events::FilledMakerOrder>,
167            liqee_account_id: Option<u64>,
168            liquidator_fees: IFixed,
169            session_summary: SessionSummary
170        }
171
172        struct SessionSummary has drop {
173            base_filled_ask: IFixed,
174            base_filled_bid: IFixed,
175            quote_filled_ask: IFixed,
176            quote_filled_bid: IFixed,
177            base_posted_ask: IFixed,
178            base_posted_bid: IFixed,
179            posted_orders: u64,
180            base_liquidated: IFixed,
181            quote_liquidated: IFixed,
182            is_liqee_long: bool,
183            bad_debt: IFixed
184        }
185    }
186
187    module stop_orders {
188        /// Object that allows to place one order on behalf of the user, used to
189        /// offer stop limit or market orders. A stop order is an order that is placed
190        /// only if the index price respects certain conditions, like being above or
191        /// below a certain price.
192        ///
193        /// Only the `Account` owner can mint this object and can decide who can be
194        /// the executor of the ticket. This allows users to run their
195        /// own stop orders bots eventually, but it's mainly used to allow 3rd parties
196        /// to offer such a service (the user is required to trust such 3rd party).
197        /// The object is shared and the 3rd party is set as `executor`. The ticket
198        /// can be destroyed in any moment only by the user or by the executor.
199        /// The user needs to trust the 3rd party for liveness of the service offered.
200        ///
201        /// The order details are encrypted offchain and the result is stored in the ticket.
202        /// The user needs to share such details with the 3rd party only to allow for execution.
203        struct StopOrderTicket<!phantom T> has key {
204            id: UID,
205            /// Addresses allowed to execute the order on behalf of the user.
206            executors: vector<address>,
207            /// Gas coin that must be provided by the user to cover for one stop order cost.
208            /// This amount of gas is going to be sent to the executor of the order.
209            gas: Balance<SUI>,
210            /// User account id
211            account_id: u64,
212            /// Value to indentify the stop order type. Available values can be found in the
213            /// constants module.
214            stop_order_type: u64,
215            /// Vector containing the blake2b hash obtained from offchain on the stop order parameters.
216            /// Depending on the stop order type value, a different set of parameters is expected to be used.
217            ///
218            /// Parameters encoded for a SLTP stop order (stop_order_type code 0):
219            /// - clearing_house_id: ID
220            /// - expire_timestamp: Option<u64>
221            /// - is_limit_order: `true` if limit order, `false` if market order
222            /// - stop_index_price: u256
223            /// - is_stop_loss: `true` if stop loss order, `false` if take profit order
224            /// - position_is_ask: `true` if position is short, `false` if position is long
225            /// - size: u64
226            /// - price: u64 (can be set at random value if `is_limit_order` is false)
227            /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
228            /// - salt: vector<u8>
229            ///
230            /// Parameters encoded for a Standalone stop order (stop_order_type code 1):
231            /// - clearing_house_id: ID
232            /// - expire_timestamp: Option<u64>
233            /// - is_limit_order: `true` if limit order, `false` if market order
234            /// - stop_index_price: u256
235            /// - ge_stop_index_price: `true` means the order can be placed when
236            /// oracle index price is >= than chosen `stop_index_price`
237            /// - side: bool
238            /// - size: u64
239            /// - price: u64 (can be set at random value if `is_limit_order` is false)
240            /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
241            /// - reduce_only: bool
242            /// - salt: vector<u8>
243            encrypted_details: vector<u8>
244        }
245    }
246
247    module events {
248        struct CreatedAccount<!phantom T> has copy, drop {
249            account_obj_id: ID,
250            user: address,
251            account_id: u64
252        }
253
254        struct DepositedCollateral<!phantom T> has copy, drop {
255            account_id: u64,
256            collateral: u64,
257        }
258
259        struct AllocatedCollateral has copy, drop {
260            ch_id: ID,
261            account_id: u64,
262            collateral: u64,
263        }
264
265        struct WithdrewCollateral<!phantom T> has copy, drop {
266            account_id: u64,
267            collateral: u64,
268        }
269
270        struct DeallocatedCollateral has copy, drop {
271            ch_id: ID,
272            account_id: u64,
273            collateral: u64,
274        }
275
276        struct CreatedOrderbook has copy, drop {
277            branch_min: u64,
278            branches_merge_max: u64,
279            branch_max: u64,
280            leaf_min: u64,
281            leaves_merge_max: u64,
282            leaf_max: u64
283        }
284
285        struct CreatedClearingHouse has copy, drop {
286            ch_id: ID,
287            collateral: String,
288            coin_decimals: u64,
289            margin_ratio_initial: IFixed,
290            margin_ratio_maintenance: IFixed,
291            base_oracle_id: ID,
292            collateral_oracle_id: ID,
293            funding_frequency_ms: u64,
294            funding_period_ms: u64,
295            premium_twap_frequency_ms: u64,
296            premium_twap_period_ms: u64,
297            spread_twap_frequency_ms: u64,
298            spread_twap_period_ms: u64,
299            maker_fee: IFixed,
300            taker_fee: IFixed,
301            liquidation_fee: IFixed,
302            force_cancel_fee: IFixed,
303            insurance_fund_fee: IFixed,
304            lot_size: u64,
305            tick_size: u64,
306        }
307
308        struct RegisteredMarketInfo<!phantom T> has copy, drop {
309            ch_id: ID,
310            base_pfs_id: ID,
311            collateral_pfs_id: ID,
312            lot_size: u64,
313            tick_size: u64,
314            scaling_factor: IFixed
315        }
316
317        struct RemovedRegisteredMarketInfo<!phantom T> has copy, drop {
318            ch_id: ID,
319        }
320
321        struct RegisteredCollateralInfo<!phantom T> has copy, drop {
322            ch_id: ID,
323            collateral_pfs_id: ID,
324            scaling_factor: IFixed
325        }
326
327        struct AddedIntegratorConfig<!phantom T> has copy, drop {
328            account_id: u64,
329            integrator_address: address,
330            max_taker_fee: IFixed
331        }
332
333        struct RemovedIntegratorConfig<!phantom T> has copy, drop {
334            account_id: u64,
335            integrator_address: address,
336        }
337
338        struct PaidIntegratorFees<!phantom T> has copy, drop {
339            account_id: u64,
340            integrator_address: address,
341            fees: IFixed
342        }
343
344        struct UpdatedClearingHouseVersion has copy, drop {
345            ch_id: ID,
346            version: u64
347        }
348
349        struct UpdatedPremiumTwap has copy, drop {
350            ch_id: ID,
351            book_price: IFixed,
352            index_price: IFixed,
353            premium_twap: IFixed,
354            premium_twap_last_upd_ms: u64,
355        }
356
357        struct UpdatedSpreadTwap has copy, drop {
358            ch_id: ID,
359            book_price: IFixed,
360            index_price: IFixed,
361            spread_twap: IFixed,
362            spread_twap_last_upd_ms: u64,
363        }
364
365        struct UpdatedGasPriceTwap has copy, drop {
366            ch_id: ID,
367            gas_price: IFixed,
368            mean: IFixed,
369            variance: IFixed,
370            gas_price_last_upd_ms: u64
371        }
372
373        struct UpdatedFunding has copy, drop {
374            ch_id: ID,
375            cum_funding_rate_long: IFixed,
376            cum_funding_rate_short: IFixed,
377            funding_last_upd_ms: u64,
378        }
379
380        struct SettledFunding has copy, drop {
381            ch_id: ID,
382            account_id: u64,
383            collateral_change_usd: IFixed,
384            collateral_after: IFixed,
385            mkt_funding_rate_long: IFixed,
386            mkt_funding_rate_short: IFixed
387        }
388
389        struct FilledMakerOrders has copy, drop {
390            events: vector<FilledMakerOrder>
391        }
392
393        struct FilledMakerOrder has copy, drop {
394            ch_id: ID,
395            maker_account_id: u64,
396            taker_account_id: u64,
397            order_id: u128,
398            filled_size: u64,
399            remaining_size: u64,
400            canceled_size: u64,
401            pnl: IFixed,
402            fees: IFixed,
403        }
404
405        struct FilledTakerOrder has copy, drop {
406            ch_id: ID,
407            taker_account_id: u64,
408            taker_pnl: IFixed,
409            taker_fees: IFixed,
410            base_asset_delta_ask: IFixed,
411            quote_asset_delta_ask: IFixed,
412            base_asset_delta_bid: IFixed,
413            quote_asset_delta_bid: IFixed,
414        }
415
416        struct PostedOrder has copy, drop {
417            ch_id: ID,
418            account_id: u64,
419            order_id: u128,
420            order_size: u64,
421            reduce_only: bool,
422            expiration_timestamp_ms: Option<u64>
423        }
424
425        struct CanceledOrder has copy, drop {
426            ch_id: ID,
427            account_id: u64,
428            size: u64,
429            order_id: u128,
430        }
431
432        struct LiquidatedPosition has copy, drop {
433            ch_id: ID,
434            liqee_account_id: u64,
435            liqor_account_id: u64,
436            is_liqee_long: bool,
437            base_liquidated: IFixed,
438            quote_liquidated: IFixed,
439            liqee_pnl: IFixed,
440            liquidation_fees: IFixed,
441            force_cancel_fees: IFixed,
442            insurance_fund_fees: IFixed,
443            bad_debt: IFixed
444        }
445
446        struct PerformedLiquidation has copy, drop {
447            ch_id: ID,
448            liqee_account_id: u64,
449            liqor_account_id: u64,
450            is_liqee_long: bool,
451            base_liquidated: IFixed,
452            quote_liquidated: IFixed,
453            liqor_pnl: IFixed,
454            liqor_fees: IFixed,
455        }
456
457        struct UpdatedCumFundings has copy, drop {
458            ch_id: ID,
459            cum_funding_rate_long: IFixed,
460            cum_funding_rate_short: IFixed,
461        }
462
463        struct CreatedPosition has copy, drop {
464            ch_id: ID,
465            account_id: u64,
466            mkt_funding_rate_long: IFixed,
467            mkt_funding_rate_short: IFixed,
468        }
469
470        struct SetPositionInitialMarginRatio has copy, drop {
471            ch_id: ID,
472            account_id: u64,
473            initial_margin_ratio: IFixed,
474        }
475
476        struct CreatedStopOrderTicket<!phantom T> has copy, drop {
477            ticket_id: ID,
478            account_id: u64,
479            executors: vector<address>,
480            gas: u64,
481            stop_order_type: u64,
482            encrypted_details: vector<u8>
483        }
484
485        struct ExecutedStopOrderTicket<!phantom T> has copy, drop {
486            ticket_id: ID,
487            account_id: u64,
488            executor: address
489        }
490
491        struct DeletedStopOrderTicket<!phantom T> has copy, drop {
492            ticket_id: ID,
493            account_id: u64,
494            executor: address
495        }
496
497        struct EditedStopOrderTicketDetails<!phantom T> has copy, drop {
498            ticket_id: ID,
499            account_id: u64,
500            stop_order_type: u64,
501            encrypted_details: vector<u8>
502        }
503
504        struct EditedStopOrderTicketExecutors<!phantom T> has copy, drop {
505            ticket_id: ID,
506            account_id: u64,
507            executors: vector<address>
508        }
509
510        struct CreatedMarginRatiosProposal has copy, drop {
511            ch_id: ID,
512            margin_ratio_initial: IFixed,
513            margin_ratio_maintenance: IFixed,
514        }
515
516        struct UpdatedMarginRatios has copy, drop {
517            ch_id: ID,
518            margin_ratio_initial: IFixed,
519            margin_ratio_maintenance: IFixed,
520        }
521
522        struct DeletedMarginRatiosProposal has copy, drop {
523            ch_id: ID,
524            margin_ratio_initial: IFixed,
525            margin_ratio_maintenance: IFixed,
526        }
527
528        struct CreatedPositionFeesProposal has copy, drop {
529            ch_id: ID,
530            account_id: u64,
531            maker_fee: IFixed,
532            taker_fee: IFixed,
533        }
534
535        struct DeletedPositionFeesProposal has copy, drop {
536            ch_id: ID,
537            account_id: u64,
538            maker_fee: IFixed,
539            taker_fee: IFixed,
540        }
541
542        struct AcceptedPositionFeesProposal has copy, drop {
543            ch_id: ID,
544            account_id: u64,
545            maker_fee: IFixed,
546            taker_fee: IFixed,
547        }
548
549        struct RejectedPositionFeesProposal has copy, drop {
550            ch_id: ID,
551            account_id: u64,
552            maker_fee: IFixed,
553            taker_fee: IFixed,
554        }
555
556        struct ResettedPositionFees has copy, drop {
557            ch_id: ID,
558            account_id: u64,
559        }
560
561        struct UpdatedFees has copy, drop {
562            ch_id: ID,
563            maker_fee: IFixed,
564            taker_fee: IFixed,
565            liquidation_fee: IFixed,
566            force_cancel_fee: IFixed,
567            insurance_fund_fee: IFixed,
568        }
569
570        struct UpdatedFundingParameters has copy, drop {
571            ch_id: ID,
572            funding_frequency_ms: u64,
573            funding_period_ms: u64,
574            premium_twap_frequency_ms: u64,
575            premium_twap_period_ms: u64,
576        }
577
578        struct UpdatedSpreadTwapParameters has copy, drop {
579            ch_id: ID,
580            spread_twap_frequency_ms: u64,
581            spread_twap_period_ms: u64
582        }
583
584        struct UpdatedMinOrderUsdValue has copy, drop {
585            ch_id: ID,
586            min_order_usd_value: IFixed,
587        }
588
589        struct UpdatedBaseOracleTolerance has copy, drop {
590            ch_id: ID,
591            oracle_tolerance: u64,
592        }
593
594        struct UpdatedCollateralOracleTolerance has copy, drop {
595            ch_id: ID,
596            oracle_tolerance: u64,
597        }
598
599        struct UpdatedMaxOpenInterest has copy, drop {
600            ch_id: ID,
601            max_open_interest: IFixed,
602        }
603
604        struct UpdatedMaxOpenInterestPositionParams has copy, drop {
605            ch_id: ID,
606            max_open_interest_threshold: IFixed,
607            max_open_interest_position_percent: IFixed,
608        }
609
610        struct UpdatedMaxPendingOrders has copy, drop {
611            ch_id: ID,
612            max_pending_orders: u64
613        }
614
615        struct UpdatedStopOrderMistCost has copy, drop {
616            stop_order_mist_cost: u64
617        }
618
619        struct DonatedToInsuranceFund has copy, drop {
620            sender: address,
621            ch_id: ID,
622            new_balance: u64,
623        }
624
625        struct WithdrewFees has copy, drop {
626            sender: address,
627            ch_id: ID,
628            amount: u64,
629            vault_balance_after: u64,
630        }
631
632        struct WithdrewInsuranceFund has copy, drop {
633            sender: address,
634            ch_id: ID,
635            amount: u64,
636            insurance_fund_balance_after: u64,
637        }
638
639        struct UpdatedOpenInterestAndFeesAccrued has copy, drop {
640            ch_id: ID,
641            open_interest: IFixed,
642            fees_accrued: IFixed
643        }
644    }
645
646    module keys {
647        /// Key type for accessing a `MarketInfo` saved in registry.
648        struct RegistryMarketInfo has copy, drop, store {
649            ch_id: ID
650        }
651
652        /// Key type for accessing a `CollateralInfo` saved in registry.
653        struct RegistryCollateralInfo<!phantom T> has copy, drop, store {}
654
655        /// Key type for accessing a `Config` saved in registry.
656        struct RegistryConfig has copy, drop, store {}
657
658        /// Key type for accessing integrator configs for an account.
659        struct IntegratorConfig has copy, drop, store {
660            integrator_address: address,
661        }
662
663        /// Key type for accessing integrator's collected fees.
664        struct IntegratorVault has copy, drop, store {
665            integrator_address: address,
666        }
667
668        /// Key type for accessing market params in clearing house.
669        struct Orderbook has copy, drop, store {}
670
671        /// Key type for accessing vault in clearing house.
672        struct MarketVault has copy, drop, store {}
673
674        /// Key type for accessing trader position in clearing house.
675        struct Position has copy, drop, store {
676            account_id: u64,
677        }
678
679        /// Key type for accessing market margin parameters change proposal in clearing house.
680        struct MarginRatioProposal has copy, drop, store {}
681
682        /// Key type for accessing custom fees parameters change proposal for an account
683        struct PositionFeesProposal has copy, drop, store {
684            account_id: u64
685        }
686
687        /// Key type for accessing asks map in the orderbook
688        struct AsksMap has copy, drop, store {}
689
690        /// Key type for accessing asks map in the orderbook
691        struct BidsMap has copy, drop, store {}
692    }
693
694    module market {
695        /// Static attributes of a perpetuals market.
696        struct MarketParams has copy, drop, store {
697            /// Minimum margin ratio for opening a new position.
698            margin_ratio_initial: IFixed,
699            /// Margin ratio below which full liquidations can occur.
700            margin_ratio_maintenance: IFixed,
701            /// Identifier of the base asset's price feed storage.
702            base_pfs_id: ID,
703            /// Identifier of the collateral asset's price feed storage.
704            collateral_pfs_id: ID,
705            /// The time span between each funding rate update.
706            funding_frequency_ms: u64,
707            /// Period of time over which funding (the difference between book and
708            /// index prices) gets paid.
709            ///
710            /// Setting the funding period too long may cause the perpetual to start
711            /// trading at a very dislocated price to the index because there's less
712            /// of an incentive for basis arbitrageurs to push the prices back in
713            /// line since they would have to carry the basis risk for a longer
714            /// period of time.
715            ///
716            /// Setting the funding period too short may cause nobody to trade the
717            /// perpetual because there's too punitive of a price to pay in the case
718            /// the funding rate flips sign.
719            funding_period_ms: u64,
720            /// The time span between each funding TWAP (both index price and orderbook price) update.
721            premium_twap_frequency_ms: u64,
722            /// The reference time span used for weighting the TWAP (both index price and orderbook price)
723            /// updates for funding rates estimation
724            premium_twap_period_ms: u64,
725            /// The time span between each spread TWAP updates (used for liquidations).
726            spread_twap_frequency_ms: u64,
727            /// The reference time span used for weighting the TWAP updates for spread.
728            spread_twap_period_ms: u64,
729            /// The reference time span used for weighting the TWAP updates for gas price.
730            gas_price_twap_period_ms: u64,
731            /// Proportion of volume charged as fees from makers upon processing
732            /// fill events.
733            maker_fee: IFixed,
734            /// Proportion of volume charged as fees from takers after processing
735            /// fill events.
736            taker_fee: IFixed,
737            /// Proportion of volume charged as fees from liquidatees
738            liquidation_fee: IFixed,
739            /// Proportion of volume charged as fees from liquidatees after forced cancelling
740            /// of pending orders during liquidation.
741            force_cancel_fee: IFixed,
742            /// Proportion of volume charged as fees from liquidatees to deposit into insurance fund
743            insurance_fund_fee: IFixed,
744            /// Minimum USD value an order is required to be worth to be placed
745            min_order_usd_value: IFixed,
746            /// Number of base units exchanged per lot
747            lot_size: u64,
748            /// Number of quote units exchanged per tick
749            tick_size: u64,
750            /// Maximum number of pending orders that a position can have.
751            max_pending_orders: u64,
752            /// Timestamp tolerance for base oracle price
753            base_oracle_tolerance: u64,
754            /// Timestamp tolerance for collateral oracle price
755            collateral_oracle_tolerance: u64,
756            /// Max open interest (in base tokens) available for this market
757            max_open_interest: IFixed,
758            /// The check on `max_open_interest_position_percent` is not performed if
759            /// the market's open interest is below this threshold.
760            max_open_interest_threshold: IFixed,
761            /// Max open interest percentage a position can have relative to total market's open interest
762            max_open_interest_position_percent: IFixed,
763            /// Scaling factor to use to convert collateral units to ifixed values and viceversa
764            scaling_factor: IFixed,
765            /// Additional taker fee to apply in case the gas price set for the transaction violates
766            /// the z-score constraint
767            gas_price_taker_fee: IFixed,
768            /// Z-Score threshold level used to determine if to apply `gas_price_taker_fee` to the
769            /// executed order
770            z_score_threshold: IFixed,
771        }
772
773        /// The state of a perpetuals market.
774        struct MarketState has store {
775            /// The latest cumulative funding premium in this market for longs. Must be updated
776            /// periodically.
777            cum_funding_rate_long: IFixed,
778            /// The latest cumulative funding premium in this market for shorts. Must be updated
779            /// periodically.
780            cum_funding_rate_short: IFixed,
781            /// The timestamp (millisec) of the latest cumulative funding premium update
782            /// (both longs and shorts).
783            funding_last_upd_ms: u64,
784            /// The last calculated funding premium TWAP (used for funding settlement).
785            premium_twap: IFixed,
786            /// The timestamp (millisec) of the last update of `premium_twap`.
787            premium_twap_last_upd_ms: u64,
788            /// The last calculated spread TWAP (used for liquidations).
789            /// Spread is (book - index).
790            spread_twap: IFixed,
791            /// The timestamp (millisec) of `spread_twap` last update.
792            spread_twap_last_upd_ms: u64,
793            /// Gas price TWAP mean.
794            /// It is used to calculate the penalty to add to taker fees based on the Z-score of the current gas price
795            /// relative to the smoothed mean and variance.
796            gas_price_mean: IFixed,
797            /// Gas price TWAP variance.
798            /// It is used to calculate the penalty to add to taker fees based on the Z-score of the current gas price
799            /// relative to the smoothed mean and variance.
800            gas_price_variance: IFixed,
801            /// The timestamp (millisec) of the last update of `gas_price_mean` and `gas_price_variance`.
802            gas_price_last_upd_ms: u64,
803            /// Open interest (in base tokens) as a fixed-point number. Counts the
804            /// total size of contracts as the sum of all long positions.
805            open_interest: IFixed,
806            /// Total amount of fees accrued by this market (in T's units)
807            /// Only admin can withdraw these fees.
808            fees_accrued: IFixed,
809        }
810    }
811
812    module orderbook {
813        /// An order on the orderbook
814        struct Order has copy, drop, store {
815            /// User's account id
816            account_id: u64,
817            /// Amount of lots to be filled
818            size: u64,
819            /// Optional reduce-only requirement for this order.
820            reduce_only: bool,
821            /// Optional expiration time for the order
822            expiration_timestamp_ms: Option<u64>
823        }
824
825        /// The orderbook doesn't know the types of tokens traded, it assumes a correct
826        /// management by the clearing house
827        struct Orderbook has key, store {
828            id: UID,
829            /// Number of limit orders placed on book, monotonically increases
830            counter: 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}