af_iperps/
lib.rs

1#![cfg_attr(all(doc, not(doctest)), feature(doc_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, SUI_FRAMEWORK_ADDRESS};
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;
29use crate::authority::{ADMIN, ASSISTANT};
30
31/// Package IDs of the perpetuals contract versions published on testnet, in order of its versions.
32pub const TESTNET_PACKAGE_VERSIONS: &[Address] = &[Address::from_static(
33    "0x1fc71972750d0d81567183a8500befef94d7699aac76edffcca253fe541367fd",
34)];
35
36// Convenient aliases since these types will never exist onchain with a type argument other than an
37// OTW.
38pub type AdminCapability = self::authority::Capability<ADMIN>;
39pub type AssistantCapability = self::authority::Capability<ASSISTANT>;
40pub type AccountCap = self::account::AccountCap<Otw>;
41pub type AccountCapTypeTag = self::account::AccountCapTypeTag<Otw>;
42pub type Account = self::account::Account<Otw>;
43pub type AccountTypeTag = self::account::AccountTypeTag<Otw>;
44pub type StopOrderTicket = self::stop_orders::StopOrderTicket<Otw>;
45pub type StopOrderTicketTypetag = self::stop_orders::StopOrderTicketTypeTag<Otw>;
46pub type ClearingHouse = self::clearing_house::ClearingHouse<Otw>;
47pub type ClearingHouseTypeTag = self::clearing_house::ClearingHouseTypeTag<Otw>;
48pub type Vault = self::clearing_house::Vault<Otw>;
49pub type VaultTypeTag = self::clearing_house::VaultTypeTag<Otw>;
50pub type MarketInfo = self::registry::MarketInfo<Otw>;
51pub type CollateralInfo = self::registry::CollateralInfo<Otw>;
52
53/// Dynamic field storing a [`Vault`].
54pub type VaultDf = Field<keys::MarketVault, Vault>;
55/// Dynamic field storing a [`Position`].
56pub type PositionDf = Field<keys::Position, Position>;
57/// Dynamic field storing a leaf in a [`Map`] of [`Order`]s.
58///
59/// [`Map`]: self::ordered_map::Map
60pub type OrderLeafDf = Field<u64, ordered_map::Leaf<Order>>;
61/// Dynamic object field wrapper for the [`Orderbook`](orderbook::Orderbook) ID.
62pub type OrderbookDofWrapper = Field<Wrapper<keys::Orderbook>, ID>;
63/// Dynamic object field wrapper for the asks [`Map`](ordered_map::Map) ID.
64pub type AsksMapDofWrapper = Field<Wrapper<keys::AsksMap>, ID>;
65/// Dynamic object field wrapper for the bids [`Map`](ordered_map::Map) ID.
66pub type BidsMapDofWrapper = Field<Wrapper<keys::BidsMap>, ID>;
67/// Dynamic field storing a [`MarketInfo`].
68pub type MarketInfoDf = Field<keys::RegistryMarketInfo, MarketInfo>;
69/// Dynamic field storing a [`CollateralInfo`].
70pub type CollateralInfoDf = Field<keys::RegistryCollateralInfo<Otw>, CollateralInfo>;
71
72sui_pkg_sdk!(perpetuals {
73    module account {
74        /// The AccountCap is used to check ownership of `Account` with the same `account_id`.
75        struct AccountCap<!phantom T> has key, store {
76            id: UID,
77            // Account object id
78            account_obj_id: ID,
79            /// Numerical value associated to the account
80            account_id: u64,
81        }
82
83        /// The Account object saves the collateral available to be used in clearing houses.
84        struct Account<!phantom T> has key, store {
85            id: UID,
86            /// Numerical value associated to the account
87            account_id: u64,
88            /// Balance available to be allocated to markets.
89            collateral: Balance<T>,
90        }
91
92        struct IntegratorConfig has store {
93            /// Max **additional** taker fee the user is willing
94            /// to pay for integrator-submitted orders.
95            max_taker_fee: IFixed
96        }
97    }
98
99    module authority {
100        /// Capability object required to perform admin functions.
101        ///
102        /// Minted once when the module is published and transfered to its creator.
103        struct Capability<!phantom Role> has key, store {
104            id: UID
105        }
106
107        /// Admin Role
108        struct ADMIN();
109
110        /// Assistant Role
111        struct ASSISTANT();
112    }
113
114    module clearing_house {
115        /// The central object that owns the market state.
116        ///
117        /// Dynamic fields:
118        /// - [`position::Position`]
119        /// - [`Vault`]
120        ///
121        /// Dynamic objects:
122        /// - [`orderbook::Orderbook`]
123        struct ClearingHouse<!phantom T> has key {
124            id: UID,
125            version: u64,
126            paused: bool,
127            market_params: market::MarketParams,
128            market_state: market::MarketState
129        }
130
131        /// Stores all deposits from traders for collateral T.
132        /// Stores the funds reserved for covering bad debt from untimely
133        /// liquidations.
134        ///
135        /// The Clearing House keeps track of who owns each share of the vault.
136        struct Vault<!phantom T> has store {
137            collateral_balance: Balance<T>,
138            insurance_fund_balance: Balance<T>,
139        }
140
141        /// Stores the proposed parameters for updating margin ratios
142        struct MarginRatioProposal has store {
143            /// Target timestamp at which to apply the proposed updates
144            maturity: u64,
145            /// Proposed IMR
146            margin_ratio_initial: IFixed,
147            /// Proposed MMR
148            margin_ratio_maintenance: IFixed,
149        }
150
151        /// Stores the proposed parameters for a position's custom fees
152        struct PositionFeesProposal has store {
153            /// Proposed IMR
154            maker_fee: IFixed,
155            /// Proposed MMR
156            taker_fee: IFixed,
157        }
158
159        /// Structure that stores the amount of fees collected by an integrator
160        struct IntegratorVault has store {
161            /// Amount of fees collected by this integrator, in collateral units
162            fees: IFixed,
163        }
164
165        struct IntegratorInfo has copy, drop {
166            integrator_address: address,
167            taker_fee: IFixed,
168        }
169
170        /// Stores the proposed parameters for a position's custom fees
171        struct SettlementPrices has store {
172            /// Base asset's settlement price
173            base_price: IFixed,
174            /// Collateral asset's settlement price
175            collateral_price: IFixed,
176        }
177        /// Used by clearing house to check margin when placing an order
178        struct SessionHotPotato<!phantom T> {
179            clearing_house: ClearingHouse<T>,
180            orderbook: orderbook::Orderbook,
181            account_id: u64,
182            timestamp_ms: u64,
183            collateral_price: IFixed,
184            index_price: IFixed,
185            gas_price: u64,
186            margin_before: IFixed,
187            min_margin_before: IFixed,
188            position_base_before: IFixed,
189            total_open_interest: IFixed,
190            total_fees: IFixed,
191            maker_events: vector<events::FilledMakerOrder>,
192            liqee_account_id: Option<u64>,
193            liquidator_fees: IFixed,
194            session_summary: SessionSummary
195        }
196
197        struct SessionSummary has drop {
198            base_filled_ask: IFixed,
199            base_filled_bid: IFixed,
200            quote_filled_ask: IFixed,
201            quote_filled_bid: IFixed,
202            base_posted_ask: IFixed,
203            base_posted_bid: IFixed,
204            posted_orders: u64,
205            base_liquidated: IFixed,
206            quote_liquidated: IFixed,
207            is_liqee_long: bool,
208            bad_debt: IFixed
209        }
210    }
211
212    module stop_orders {
213        /// Object that allows to place one order on behalf of the user, used to
214        /// offer stop limit or market orders. A stop order is an order that is placed
215        /// only if the index price respects certain conditions, like being above or
216        /// below a certain price.
217        ///
218        /// Only the `AccountCap` owner can mint this object and can decide who can be
219        /// the executor of the ticket. This allows users to run their
220        /// own stop orders bots eventually, but it's mainly used to allow 3rd parties
221        /// to offer such a service (the user is required to trust such 3rd party).
222        /// The object is shared and the 3rd party is set as `executors`. The ticket
223        /// can be destroyed in any moment only by the user or by the executor.
224        /// The user needs to trust the 3rd party for liveness of the service offered.
225        ///
226        /// The order details are encrypted offchain and the result is stored in the ticket.
227        /// The user needs to share such details with the 3rd party only to allow for execution.
228        ///
229        /// The ticket can be either a shared, owned or party object.
230        /// The permission to execute or cancel it is controlled exclusively through `executors`,
231        /// which can be modified only by the `AccountCap` owner associated with the ticket
232        /// using the function `edit_stop_order_ticket_executors`.
233        struct StopOrderTicket<!phantom T> has key, store {
234            id: UID,
235            /// Addresses allowed to execute the order on behalf of the user.
236            executors: vector<address>,
237            /// The executor collects the gas in case the order is placed or canceled for any reason.
238            /// The user gets back the gas in case he manually cancels the order.
239            gas: Balance<SUI>,
240            /// User account id
241            account_id: u64,
242            /// Value to indentify the stop order type. Available values can be found in the
243            /// constants module.
244            stop_order_type: u64,
245            /// Vector containing the blake2b hash obtained from offchain on the stop order parameters.
246            /// Depending on the stop order type value, a different set of parameters is expected to be used.
247            ///
248            /// Parameters encoded for a SLTP stop order (stop_order_type code 0):
249            /// - clearing_house_id: ID
250            /// - expire_timestamp: Option<u64>
251            /// - is_limit_order: `true` if limit order, `false` if market order
252            /// - stop_index_price: u256
253            /// - is_stop_loss: `true` if stop loss order, `false` if take profit order
254            /// - position_is_ask: `true` if position is short, `false` if position is long
255            /// - size: u64
256            /// - price: u64 (can be set at random value if `is_limit_order` is false)
257            /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
258            /// - salt: vector<u8>
259            ///
260            /// Parameters encoded for a Standalone stop order (stop_order_type code 1):
261            /// - clearing_house_id: ID
262            /// - expire_timestamp: Option<u64>
263            /// - is_limit_order: `true` if limit order, `false` if market order
264            /// - stop_index_price: u256
265            /// - ge_stop_index_price: `true` means the order can be placed when
266            /// oracle index price is >= than chosen `stop_index_price`
267            /// - side: bool
268            /// - size: u64
269            /// - price: u64 (can be set at random value if `is_limit_order` is false)
270            /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
271            /// - reduce_only: bool
272            /// - salt: vector<u8>
273            encrypted_details: vector<u8>
274        }
275    }
276
277    module events {
278        struct CreatedAccount<!phantom T> has copy, drop {
279            account_obj_id: ID,
280            user: address,
281            account_id: u64
282        }
283
284        struct DepositedCollateral<!phantom T> has copy, drop {
285            account_id: u64,
286            collateral: u64,
287        }
288
289        struct AllocatedCollateral has copy, drop {
290            ch_id: ID,
291            account_id: u64,
292            collateral: u64,
293        }
294
295        struct WithdrewCollateral<!phantom T> has copy, drop {
296            account_id: u64,
297            collateral: u64,
298        }
299
300        struct DeallocatedCollateral has copy, drop {
301            ch_id: ID,
302            account_id: u64,
303            collateral: u64,
304        }
305
306        struct CreatedOrderbook has copy, drop {
307            branch_min: u64,
308            branches_merge_max: u64,
309            branch_max: u64,
310            leaf_min: u64,
311            leaves_merge_max: u64,
312            leaf_max: u64
313        }
314
315        struct CreatedClearingHouse has copy, drop {
316            ch_id: ID,
317            collateral: String,
318            coin_decimals: u64,
319            margin_ratio_initial: IFixed,
320            margin_ratio_maintenance: IFixed,
321            base_oracle_id: ID,
322            collateral_oracle_id: ID,
323            funding_frequency_ms: u64,
324            funding_period_ms: u64,
325            premium_twap_frequency_ms: u64,
326            premium_twap_period_ms: u64,
327            spread_twap_frequency_ms: u64,
328            spread_twap_period_ms: u64,
329            maker_fee: IFixed,
330            taker_fee: IFixed,
331            liquidation_fee: IFixed,
332            force_cancel_fee: IFixed,
333            insurance_fund_fee: IFixed,
334            lot_size: u64,
335            tick_size: u64,
336        }
337
338        struct RegisteredMarketInfo<!phantom T> has copy, drop {
339            ch_id: ID,
340            base_pfs_id: ID,
341            base_pfs_source_id: ID,
342            collateral_pfs_id: ID,
343            collateral_pfs_source_id: ID,
344            scaling_factor: IFixed
345        }
346
347        struct RemovedRegisteredMarketInfo<!phantom T> has copy, drop {
348            ch_id: ID,
349        }
350
351        struct RegisteredCollateralInfo<!phantom T> has copy, drop {
352            ch_id: ID,
353            collateral_pfs_id: ID,
354            collateral_pfs_source_id: ID,
355            scaling_factor: IFixed
356        }
357
358        struct AddedIntegratorConfig<!phantom T> has copy, drop {
359            account_id: u64,
360            integrator_address: address,
361            max_taker_fee: IFixed
362        }
363
364        struct RemovedIntegratorConfig<!phantom T> has copy, drop {
365            account_id: u64,
366            integrator_address: address,
367        }
368
369        struct PaidIntegratorFees<!phantom T> has copy, drop {
370            account_id: u64,
371            integrator_address: address,
372            fees: IFixed
373        }
374
375        struct CreatedIntegratorVault has copy, drop {
376            ch_id: ID,
377            integrator_address: address,
378        }
379
380        struct WithdrewFromIntegratorVault has copy, drop {
381            ch_id: ID,
382            integrator_address: address,
383            fees: u64
384        }
385
386        struct UpdatedClearingHouseVersion has copy, drop {
387            ch_id: ID,
388            version: u64
389        }
390
391        struct PausedMarket has copy, drop {
392            ch_id: ID,
393        }
394
395        struct ResumedMarket has copy, drop {
396            ch_id: ID,
397        }
398
399        struct ClosedMarket has copy, drop {
400            ch_id: ID,
401            base_settlement_price: IFixed,
402            collateral_settlement_price: IFixed
403        }
404
405        struct ClosedPositionAtSettlementPrices has copy, drop {
406            ch_id: ID,
407            account_id: u64,
408            pnl: IFixed,
409            base_asset_amount: IFixed,
410            quote_asset_amount: IFixed,
411            deallocated_collateral: u64,
412            bad_debt: IFixed
413        }
414
415        struct UpdatedPremiumTwap has copy, drop {
416            ch_id: ID,
417            book_price: IFixed,
418            index_price: IFixed,
419            premium_twap: IFixed,
420            premium_twap_last_upd_ms: u64,
421        }
422
423        struct UpdatedSpreadTwap has copy, drop {
424            ch_id: ID,
425            book_price: IFixed,
426            index_price: IFixed,
427            spread_twap: IFixed,
428            spread_twap_last_upd_ms: u64,
429        }
430
431        struct UpdatedGasPriceTwap has copy, drop {
432            ch_id: ID,
433            gas_price: IFixed,
434            mean: IFixed,
435            variance: IFixed,
436            gas_price_last_upd_ms: u64
437        }
438
439        struct UpdatedGasPriceTwapParameters has copy, drop {
440            ch_id: ID,
441            gas_price_twap_period_ms: u64,
442            gas_price_taker_fee: IFixed,
443            z_score_threshold: IFixed
444        }
445
446        struct UpdatedMarketLotAndTick has copy, drop {
447            ch_id: ID,
448            lot_size: u64,
449            tick_size: u64
450        }
451
452        struct UpdatedFunding has copy, drop {
453            ch_id: ID,
454            cum_funding_rate_long: IFixed,
455            cum_funding_rate_short: IFixed,
456            funding_last_upd_ms: u64,
457        }
458
459        struct SettledFunding has copy, drop {
460            ch_id: ID,
461            account_id: u64,
462            collateral_change_usd: IFixed,
463            collateral_after: IFixed,
464            mkt_funding_rate_long: IFixed,
465            mkt_funding_rate_short: IFixed
466        }
467
468        struct FilledMakerOrders has copy, drop {
469            events: vector<FilledMakerOrder>
470        }
471
472        struct FilledMakerOrder has copy, drop {
473            ch_id: ID,
474            maker_account_id: u64,
475            taker_account_id: u64,
476            order_id: u128,
477            filled_size: u64,
478            remaining_size: u64,
479            canceled_size: u64,
480            pnl: IFixed,
481            fees: IFixed,
482        }
483
484        struct FilledTakerOrder has copy, drop {
485            ch_id: ID,
486            taker_account_id: u64,
487            taker_pnl: IFixed,
488            taker_fees: IFixed,
489            integrator_taker_fees: IFixed,
490            integrator_address: Option<address>,
491            base_asset_delta_ask: IFixed,
492            quote_asset_delta_ask: IFixed,
493            base_asset_delta_bid: IFixed,
494            quote_asset_delta_bid: IFixed,
495        }
496
497        struct PostedOrder has copy, drop {
498            ch_id: ID,
499            account_id: u64,
500            order_id: u128,
501            order_size: u64,
502            reduce_only: bool,
503            expiration_timestamp_ms: Option<u64>
504        }
505
506        struct CanceledOrder has copy, drop {
507            ch_id: ID,
508            account_id: u64,
509            size: u64,
510            order_id: u128,
511        }
512
513        struct LiquidatedPosition has copy, drop {
514            ch_id: ID,
515            liqee_account_id: u64,
516            liqor_account_id: u64,
517            is_liqee_long: bool,
518            base_liquidated: IFixed,
519            quote_liquidated: IFixed,
520            liqee_pnl: IFixed,
521            liquidation_fees: IFixed,
522            force_cancel_fees: IFixed,
523            insurance_fund_fees: IFixed,
524            bad_debt: IFixed
525        }
526
527        struct PerformedLiquidation has copy, drop {
528            ch_id: ID,
529            liqee_account_id: u64,
530            liqor_account_id: u64,
531            is_liqee_long: bool,
532            base_liquidated: IFixed,
533            quote_liquidated: IFixed,
534            liqor_pnl: IFixed,
535            liqor_fees: IFixed,
536        }
537
538        struct SocializedBadDebt has copy, drop {
539            ch_id: ID,
540            bad_debt_usd: IFixed,
541            socialized_fundings: IFixed,
542            added_to_long: bool,
543            cum_funding_rate_long: IFixed,
544            cum_funding_rate_short: IFixed,
545        }
546
547        struct PerformedADL has copy, drop {
548            ch_id: ID,
549            bad_debt_account_id: u64,
550            size_reduced: u64,
551            collateral_transferred: IFixed,
552            adl_price: u64,
553            counterparty_account_id: u64,
554            bad_debt_is_long: bool,
555        }
556
557        struct CreatedPosition has copy, drop {
558            ch_id: ID,
559            account_id: u64,
560            mkt_funding_rate_long: IFixed,
561            mkt_funding_rate_short: IFixed,
562        }
563
564        struct SetPositionInitialMarginRatio has copy, drop {
565            ch_id: ID,
566            account_id: u64,
567            initial_margin_ratio: IFixed,
568        }
569
570        struct CreatedStopOrderTicket<!phantom T> has copy, drop {
571            ticket_id: ID,
572            account_id: u64,
573            executors: vector<address>,
574            gas: u64,
575            stop_order_type: u64,
576            encrypted_details: vector<u8>
577        }
578
579        struct ExecutedStopOrderTicket<!phantom T> has copy, drop {
580            ticket_id: ID,
581            account_id: u64,
582            executor: address
583        }
584
585        struct DeletedStopOrderTicket<!phantom T> has copy, drop {
586            ticket_id: ID,
587            account_id: u64,
588            executor: address
589        }
590
591        struct EditedStopOrderTicketDetails<!phantom T> has copy, drop {
592            ticket_id: ID,
593            account_id: u64,
594            encrypted_details: vector<u8>
595        }
596
597        struct EditedStopOrderTicketExecutors<!phantom T> has copy, drop {
598            ticket_id: ID,
599            account_id: u64,
600            executors: vector<address>
601        }
602
603        struct CreatedMarginRatiosProposal has copy, drop {
604            ch_id: ID,
605            margin_ratio_initial: IFixed,
606            margin_ratio_maintenance: IFixed,
607        }
608
609        struct UpdatedMarginRatios has copy, drop {
610            ch_id: ID,
611            margin_ratio_initial: IFixed,
612            margin_ratio_maintenance: IFixed,
613        }
614
615        struct DeletedMarginRatiosProposal has copy, drop {
616            ch_id: ID,
617            margin_ratio_initial: IFixed,
618            margin_ratio_maintenance: IFixed,
619        }
620
621        struct CreatedPositionFeesProposal has copy, drop {
622            ch_id: ID,
623            account_id: u64,
624            maker_fee: IFixed,
625            taker_fee: IFixed,
626        }
627
628        struct DeletedPositionFeesProposal has copy, drop {
629            ch_id: ID,
630            account_id: u64,
631            maker_fee: IFixed,
632            taker_fee: IFixed,
633        }
634
635        struct AcceptedPositionFeesProposal has copy, drop {
636            ch_id: ID,
637            account_id: u64,
638            maker_fee: IFixed,
639            taker_fee: IFixed,
640        }
641
642        struct RejectedPositionFeesProposal has copy, drop {
643            ch_id: ID,
644            account_id: u64,
645            maker_fee: IFixed,
646            taker_fee: IFixed,
647        }
648
649        struct ResettedPositionFees has copy, drop {
650            ch_id: ID,
651            account_id: u64,
652        }
653
654        struct UpdatedFees has copy, drop {
655            ch_id: ID,
656            maker_fee: IFixed,
657            taker_fee: IFixed,
658            liquidation_fee: IFixed,
659            force_cancel_fee: IFixed,
660            insurance_fund_fee: IFixed,
661        }
662
663        struct UpdatedFundingParameters has copy, drop {
664            ch_id: ID,
665            funding_frequency_ms: u64,
666            funding_period_ms: u64,
667            premium_twap_frequency_ms: u64,
668            premium_twap_period_ms: u64,
669        }
670
671        struct UpdatedSpreadTwapParameters has copy, drop {
672            ch_id: ID,
673            spread_twap_frequency_ms: u64,
674            spread_twap_period_ms: u64
675        }
676
677        struct UpdatedMinOrderUsdValue has copy, drop {
678            ch_id: ID,
679            min_order_usd_value: IFixed,
680        }
681
682        struct UpdatedBasePfsID has copy, drop {
683            ch_id: ID,
684            pfs_id: ID,
685        }
686
687        struct UpdatedCollateralPfsID has copy, drop {
688            ch_id: ID,
689            pfs_id: ID,
690        }
691
692        struct UpdatedBasePfsSourceID has copy, drop {
693            ch_id: ID,
694            source_id: ID,
695        }
696
697        struct UpdatedCollateralPfsSourceID has copy, drop {
698            ch_id: ID,
699            source_id: ID,
700        }
701
702        struct UpdatedBasePfsTolerance has copy, drop {
703            ch_id: ID,
704            pfs_tolerance: u64,
705        }
706
707        struct UpdatedCollateralPfsTolerance has copy, drop {
708            ch_id: ID,
709            pfs_tolerance: u64,
710        }
711
712        struct UpdatedMaxSocializeLossesMrDecrease has copy, drop {
713            ch_id: ID,
714            max_socialize_losses_mr_decrease: IFixed,
715        }
716        struct UpdatedMaxBadDebt has copy, drop {
717            ch_id: ID,
718            max_bad_debt: IFixed,
719        }
720
721        struct UpdatedCollateralHaircut has copy, drop {
722            ch_id: ID,
723            collateral_haircut: IFixed,
724        }
725
726        struct UpdatedMaxOpenInterest has copy, drop {
727            ch_id: ID,
728            max_open_interest: IFixed,
729        }
730
731        struct UpdatedMaxOpenInterestPositionParams has copy, drop {
732            ch_id: ID,
733            max_open_interest_threshold: IFixed,
734            max_open_interest_position_percent: IFixed,
735        }
736
737        struct UpdatedMaxPendingOrders has copy, drop {
738            ch_id: ID,
739            max_pending_orders: u64
740        }
741
742        struct UpdatedStopOrderMistCost has copy, drop {
743            stop_order_mist_cost: u64
744        }
745
746        struct DonatedToInsuranceFund has copy, drop {
747            sender: address,
748            ch_id: ID,
749            new_balance: u64,
750        }
751
752        struct WithdrewFees has copy, drop {
753            sender: address,
754            ch_id: ID,
755            amount: u64,
756            vault_balance_after: u64,
757        }
758
759        struct WithdrewInsuranceFund has copy, drop {
760            sender: address,
761            ch_id: ID,
762            amount: u64,
763            insurance_fund_balance_after: u64,
764        }
765
766        struct UpdatedOpenInterestAndFeesAccrued has copy, drop {
767            ch_id: ID,
768            open_interest: IFixed,
769            fees_accrued: IFixed
770        }
771    }
772
773    module keys {
774        /// Key type for accessing a `MarketInfo` saved in registry.
775        struct RegistryMarketInfo has copy, drop, store {
776            ch_id: ID
777        }
778
779        /// Key type for accessing a `CollateralInfo` saved in registry.
780        struct RegistryCollateralInfo<!phantom T> has copy, drop, store {}
781
782        /// Key type for accessing a `Config` saved in registry.
783        struct RegistryConfig has copy, drop, store {}
784
785        /// Key type for accessing integrator configs for an account.
786        struct IntegratorConfig has copy, drop, store {
787            integrator_address: address,
788        }
789
790        /// Key type for accessing integrator's collected fees.
791        struct IntegratorVault has copy, drop, store {
792            integrator_address: address,
793        }
794
795        /// Key type for accessing  in clearing house.
796        struct SettlementPrices has copy, drop, store {}
797
798        /// Key type for accessing market params in clearing house.
799        struct Orderbook has copy, drop, store {}
800
801        /// Key type for accessing vault in clearing house.
802        struct MarketVault has copy, drop, store {}
803
804        /// Key type for accessing trader position in clearing house.
805        struct Position has copy, drop, store {
806            account_id: u64,
807        }
808
809        /// Key type for accessing market margin parameters change proposal in clearing house.
810        struct MarginRatioProposal has copy, drop, store {}
811
812        /// Key type for accessing custom fees parameters change proposal for an account
813        struct PositionFeesProposal has copy, drop, store {
814            account_id: u64
815        }
816
817        /// Key type for accessing asks map in the orderbook
818        struct AsksMap has copy, drop, store {}
819
820        /// Key type for accessing asks map in the orderbook
821        struct BidsMap has copy, drop, store {}
822    }
823
824    module market {
825        /// Static attributes of a perpetuals market.
826        struct MarketParams has copy, drop, store {
827            /// Set of parameters governing market's core behaviors
828            core_params: CoreParams,
829            /// Set of parameters related to market's fees
830            fees_params: FeesParams,
831            /// Set of parameters governing fundings and twap updates
832            twap_params: TwapParams,
833            /// Set of parameters defining market's limits
834            limits_params: LimitsParams
835        }
836
837        struct CoreParams has copy, drop, store {
838            /// Identifier of the base asset's price feed storage.
839            base_pfs_id: ID,
840            /// Identifier of the collateral asset's price feed storage.
841            collateral_pfs_id: ID,
842            /// Identifier of the base asset's price feed storage source id (pyth, stork, etc...).
843            base_pfs_source_id: ID,
844            /// Identifier of the collateral asset's price feed storage source id (pyth, stork, etc...).
845            collateral_pfs_source_id: ID,
846            /// Timestamp tolerance for base oracle price
847            base_pfs_tolerance: u64,
848            /// Timestamp tolerance for collateral oracle price
849            collateral_pfs_tolerance: u64,
850            /// Number of base units exchanged per lot
851            lot_size: u64,
852            /// Number of quote units exchanged per tick
853            tick_size: u64,
854            /// Scaling factor to use to convert collateral units to ifixed values and viceversa
855            scaling_factor: IFixed,
856            /// Value haircut applied to collateral allocated in the position.
857            /// Example: 98%
858            collateral_haircut: IFixed,
859            /// Minimum margin ratio for opening a new position.
860            margin_ratio_initial: IFixed,
861            /// Margin ratio below which full liquidations can occur.
862            margin_ratio_maintenance: IFixed,
863        }
864
865        struct FeesParams has copy, drop, store {
866            /// Proportion of volume charged as fees from makers upon processing
867            /// fill events.
868            maker_fee: IFixed,
869            /// Proportion of volume charged as fees from takers after processing
870            /// fill events.
871            taker_fee: IFixed,
872            /// Proportion of volume charged as fees from liquidatees
873            liquidation_fee: IFixed,
874            /// Proportion of volume charged as fees from liquidatees after forced cancelling
875            /// of pending orders during liquidation.
876            force_cancel_fee: IFixed,
877            /// Proportion of volume charged as fees from liquidatees to deposit into insurance fund
878            insurance_fund_fee: IFixed,
879            /// Additional taker fee to apply in case the gas price set for the transaction violates
880            /// the z-score constraint
881            gas_price_taker_fee: IFixed,
882        }
883
884        struct TwapParams has copy, drop, store {
885            /// The time span between each funding rate update.
886            funding_frequency_ms: u64,
887            /// Period of time over which funding (the difference between book and
888            /// index prices) gets paid.
889            ///
890            /// Setting the funding period too long may cause the perpetual to start
891            /// trading at a very dislocated price to the index because there's less
892            /// of an incentive for basis arbitrageurs to push the prices back in
893            /// line since they would have to carry the basis risk for a longer
894            /// period of time.
895            ///
896            /// Setting the funding period too short may cause nobody to trade the
897            /// perpetual because there's too punitive of a price to pay in the case
898            /// the funding rate flips sign.
899            funding_period_ms: u64,
900            /// The time span between each funding TWAP (both index price and orderbook price) update.
901            premium_twap_frequency_ms: u64,
902            /// The reference time span used for weighting the TWAP (both index price and orderbook price)
903            /// updates for funding rates estimation
904            premium_twap_period_ms: u64,
905            /// The time span between each spread TWAP updates (used for liquidations).
906            spread_twap_frequency_ms: u64,
907            /// The reference time span used for weighting the TWAP updates for spread.
908            spread_twap_period_ms: u64,
909            /// The reference time span used for weighting the TWAP updates for gas price.
910            gas_price_twap_period_ms: u64,
911        }
912
913        struct LimitsParams has copy, drop, store {
914            /// Minimum USD value an order is required to be worth to be placed
915            min_order_usd_value: IFixed,
916            /// Maximum number of pending orders that a position can have.
917            max_pending_orders: u64,
918            /// Max open interest (in base tokens) available for this market
919            max_open_interest: IFixed,
920            /// The check on `max_open_interest_position_percent` is not performed if
921            /// the market's open interest is below this threshold.
922            max_open_interest_threshold: IFixed,
923            /// Max open interest percentage a position can have relative to total market's open interest
924            max_open_interest_position_percent: IFixed,
925            /// Max amount of bad debt that can be socialized in nominal value.
926            /// Positions that violate this check should be ADL'd.
927            max_bad_debt: IFixed,
928            /// Max amount of bad debt that can be socialized relative to total market's open interest.
929            /// Positions that violate this check should be ADL'd.
930            max_socialize_losses_mr_decrease: IFixed,
931            /// Z-Score threshold level used to determine if to apply `gas_price_taker_fee` to the
932            /// executed order
933            z_score_threshold: IFixed,
934        }
935        /// The state of a perpetuals market.
936        struct MarketState has store {
937            /// The latest cumulative funding premium in this market for longs. Must be updated
938            /// periodically.
939            cum_funding_rate_long: IFixed,
940            /// The latest cumulative funding premium in this market for shorts. Must be updated
941            /// periodically.
942            cum_funding_rate_short: IFixed,
943            /// The timestamp (millisec) of the latest cumulative funding premium update
944            /// (both longs and shorts).
945            funding_last_upd_ms: u64,
946            /// The last calculated funding premium TWAP (used for funding settlement).
947            premium_twap: IFixed,
948            /// The timestamp (millisec) of the last update of `premium_twap`.
949            premium_twap_last_upd_ms: u64,
950            /// The last calculated spread TWAP (used for liquidations).
951            /// Spread is (book - index).
952            spread_twap: IFixed,
953            /// The timestamp (millisec) of `spread_twap` last update.
954            spread_twap_last_upd_ms: u64,
955            /// Gas price TWAP mean.
956            /// It is used to calculate the penalty to add to taker fees based on the Z-score of the current gas price
957            /// relative to the smoothed mean and variance.
958            gas_price_mean: IFixed,
959            /// Gas price TWAP variance.
960            /// It is used to calculate the penalty to add to taker fees based on the Z-score of the current gas price
961            /// relative to the smoothed mean and variance.
962            gas_price_variance: IFixed,
963            /// The timestamp (millisec) of the last update of `gas_price_mean` and `gas_price_variance`.
964            gas_price_last_upd_ms: u64,
965            /// Open interest (in base tokens) as a fixed-point number. Counts the
966            /// total size of contracts as the sum of all long positions.
967            open_interest: IFixed,
968            /// Total amount of fees accrued by this market (in T's units)
969            /// Only admin can withdraw these fees.
970            fees_accrued: IFixed,
971        }
972    }
973
974    module orderbook {
975        /// An order on the orderbook
976        struct Order has copy, drop, store {
977            /// User's account id
978            account_id: u64,
979            /// Amount of lots to be filled
980            size: u64,
981            /// Optional reduce-only requirement for this order.
982            reduce_only: bool,
983            /// Optional expiration time for the order
984            expiration_timestamp_ms: Option<u64>
985        }
986
987        /// The orderbook doesn't know the types of tokens traded, it assumes a correct
988        /// management by the clearing house
989        struct Orderbook has key, store {
990            id: UID,
991            /// Number of limit orders placed on book, monotonically increases
992            counter: u64,
993        }
994    }
995
996    module ordered_map {
997        /// Ordered map with `u128` type as a key and `V` type as a value.
998        struct Map<!phantom V: copy + drop + store> has key, store {
999            /// Object UID for adding dynamic fields that are used as pointers to nodes.
1000            id: UID,
1001            /// Number of key-value pairs in the map.
1002            size: u64,
1003            /// Counter for creating another node as a dynamic field.
1004            counter: u64,
1005            /// Pointer to the root node, which is a branch or a leaf.
1006            root: u64,
1007            /// Pointer to first leaf.
1008            first: u64,
1009            /// Minimal number of kids in a non-root branch;
1010            /// must satisfy 2 <= branch_min <= branch_max / 2.
1011            branch_min: u64,
1012            /// Maximal number of kids in a branch, which is merge of two branches;
1013            /// must satisfy 2 * branch_min <= branches_merge_max <= branch_max.
1014            branches_merge_max: u64,
1015            /// Maximal number of kids in a branch.
1016            branch_max: u64,
1017            /// Minimal number of elements in a non-root leaf;
1018            /// must satisfy 2 <= leaf_min <= (leaf_max + 1) / 2.
1019            leaf_min: u64,
1020            /// Maximal number of elements in a leaf, which is merge of two leaves;
1021            /// must satisfy 2 * leaf_min - 1 <= leaves_merge_max <= leaf_max.
1022            leaves_merge_max: u64,
1023            /// Maximal number of elements in a leaf.
1024            leaf_max: u64,
1025        }
1026
1027        /// Branch node with kids and ordered separating keys.
1028        struct Branch has drop, store {
1029            /// Separating keys for kids sorted in ascending order.
1030            keys: vector<u128>,
1031            /// Kids of the node.
1032            kids: vector<u64>,
1033        }
1034
1035        /// Key-value pair.
1036        struct Pair<V: copy + drop + store> has copy, drop, store {
1037            key: u128,
1038            val: V,
1039        }
1040
1041        /// Leaf node with ordered key-value pairs.
1042        struct Leaf<V: copy + drop + store> has drop, store {
1043            /// Keys sorted in ascending order together with values.
1044            keys_vals: vector<Pair<V>>,
1045            /// Pointer to next leaf.
1046            next: u64,
1047        }
1048    }
1049
1050    module position {
1051        /// Stores information about an open position
1052        struct Position has store {
1053            /// Amount of allocated tokens (e.g., USD stables) backing this account's position.
1054            collateral: IFixed,
1055            /// The perpetual contract size, controlling the amount of exposure to
1056            /// the underlying asset. Positive implies long position and negative,
1057            /// short. Represented as a signed fixed-point number.
1058            base_asset_amount: IFixed,
1059            /// The entry value for this position, including leverage. Represented
1060            /// as a signed fixed-point number.
1061            quote_asset_notional_amount: IFixed,
1062            /// Last long cumulative funding rate used to update this position. The
1063            /// market's latest long cumulative funding rate minus this gives the funding
1064            /// rate this position must pay. This rate multiplied by this position's
1065            /// value (base asset amount * market price) gives the total funding
1066            /// owed, which is deducted from the trader account's margin. This debt
1067            /// is accounted for in margin ratio calculations, which may lead to
1068            /// liquidation. Represented as a signed fixed-point number.
1069            cum_funding_rate_long: IFixed,
1070            /// Last short cumulative funding rate used to update this position. The
1071            /// market's latest short cumulative funding rate minus this gives the funding
1072            /// rate this position must pay. This rate multiplied by this position's
1073            /// value (base asset amount * market price) gives the total funding
1074            /// owed, which is deducted from the trader account's margin. This debt
1075            /// is accounted for in margin ratio calculations, which may lead to
1076            /// liquidation. Represented as a signed fixed-point number.
1077            cum_funding_rate_short: IFixed,
1078            /// Base asset amount resting in ask orders in the orderbook.
1079            /// Represented as a signed fixed-point number.
1080            asks_quantity: IFixed,
1081            /// Base asset amount resting in bid orders in the orderbook.
1082            /// Represented as a signed fixed-point number.
1083            bids_quantity: IFixed,
1084            /// Number of pending orders in this position.
1085            pending_orders: u64,
1086            /// Custom maker fee for this position, set at default value of 100%
1087            maker_fee: IFixed,
1088            /// Custom taker fee for this position, set at default value of 100%
1089            taker_fee: IFixed,
1090            /// Initial Margin Ratio set by user for the position. Must always be less
1091            /// or equal than market's IMR. Used as a desired reference margin ratio when
1092            /// managing collateral in the position during all the actions. Can be changed
1093            /// by the user at any moment (between the allowed limits).
1094            initial_margin_ratio: IFixed
1095        }
1096    }
1097
1098    module registry {
1099        /// Registry object that maintains:
1100        /// - A mapping between a clearing house id and `MarketInfo`
1101        /// - A mapping between a collateral type `T` and `CollateralInfo`
1102        /// It also maintains the global counter for account creation.
1103        /// Minted and shared when the module is published.
1104        struct Registry has key {
1105            id: UID,
1106            next_account_id: u64
1107        }
1108
1109        /// Struct containing all the immutable info about a registered market
1110        struct MarketInfo<!phantom T> has store {
1111            base_pfs_id: ID,
1112            base_pfs_source_id: ID,
1113            collateral_pfs_id: ID,
1114            collateral_pfs_source_id: ID,
1115            scaling_factor: IFixed
1116        }
1117
1118        /// Struct containing all the immutable info about the collateral
1119        /// used in one or more markets
1120        struct CollateralInfo<!phantom T> has store {
1121            collateral_pfs_id: ID,
1122            collateral_pfs_source_id: ID,
1123            scaling_factor: IFixed
1124        }
1125
1126        /// Config that stores useful info for the protocol
1127        struct Config has store {
1128            stop_order_mist_cost: u64,
1129        }
1130    }
1131});
1132
1133impl<T: af_move_type::MoveType> clearing_house::ClearingHouse<T> {
1134    /// Convenience function to build the type of a [`PositionDf`].
1135    pub fn position_df_type(package: Address) -> FieldTypeTag<self::keys::Position, Position> {
1136        Field::type_(
1137            self::keys::Position::type_(package),
1138            Position::type_(package),
1139        )
1140    }
1141
1142    /// Convenience function to build the type of an [`OrderbookDofWrapper`].
1143    pub fn orderbook_dof_wrapper_type(
1144        package: Address,
1145    ) -> FieldTypeTag<Wrapper<keys::Orderbook>, ID> {
1146        Field::type_(
1147            Wrapper::type_(keys::Orderbook::type_(package)),
1148            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
1149        )
1150    }
1151
1152    /// The ID of the package that governs this clearing house's logic.
1153    ///
1154    /// This may be different than the package defining the clearing house's type because a package
1155    /// upgrade + `interface::upgrade_clearing_house_version` call can change
1156    /// [`ClearingHouse::version`] so that the upgraded package is the one that is allowed to make
1157    /// changes to it.
1158    ///
1159    /// Attempting to make a PTB Move call that mutates this clearing house but is not defined in
1160    /// this package version will fail.
1161    pub const fn governing_package_testnet(&self) -> Address {
1162        // NOTE: we published the most recent testnet contracts starting with `VERSION = 1`
1163        TESTNET_PACKAGE_VERSIONS[self.version as usize - 1]
1164    }
1165}
1166
1167impl self::orderbook::Orderbook {
1168    /// Convenience function to build the type of an [`AsksMapDofWrapper`].
1169    pub fn asks_dof_wrapper_type(package: Address) -> FieldTypeTag<Wrapper<keys::AsksMap>, ID> {
1170        Field::type_(
1171            Wrapper::type_(keys::AsksMap::type_(package)),
1172            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
1173        )
1174    }
1175
1176    /// Convenience function to build the type of an [`BidsMapDofWrapper`].
1177    pub fn bids_dof_wrapper_type(package: Address) -> FieldTypeTag<Wrapper<keys::BidsMap>, ID> {
1178        Field::type_(
1179            Wrapper::type_(keys::BidsMap::type_(package)),
1180            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
1181        )
1182    }
1183}
1184
1185impl self::ordered_map::Map<Order> {
1186    /// Convenience function to build the type of an [`OrderLeafDf`].
1187    pub fn leaf_df_type(package: Address) -> FieldTypeTag<u64, self::ordered_map::Leaf<Order>> {
1188        Field::type_(
1189            af_move_type::U64TypeTag,
1190            self::ordered_map::Leaf::type_(package, Order::type_(package)),
1191        )
1192    }
1193}
1194
1195#[cfg(test)]
1196mod tests {
1197    /// Taken from
1198    /// <https://github.com/cargo-public-api/cargo-public-api?tab=readme-ov-file#-as-a-ci-check>
1199    #[test]
1200    fn public_api() {
1201        // Install a compatible nightly toolchain if it is missing
1202        rustup_toolchain::install(public_api::MINIMUM_NIGHTLY_RUST_VERSION).unwrap();
1203
1204        // Build rustdoc JSON
1205        let rustdoc_json = rustdoc_json::Builder::default()
1206            .toolchain(public_api::MINIMUM_NIGHTLY_RUST_VERSION)
1207            .build()
1208            .unwrap();
1209
1210        // Derive the public API from the rustdoc JSON
1211        let public_api = public_api::Builder::from_rustdoc_json(rustdoc_json)
1212            .omit_blanket_impls(true)
1213            .omit_auto_trait_impls(true)
1214            .omit_auto_derived_impls(true)
1215            .build()
1216            .unwrap();
1217
1218        // Assert that the public API looks correct
1219        insta::assert_snapshot!(public_api);
1220    }
1221}