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