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