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