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