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