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