//! Move types for Aftermath's `Perpetuals` package

use af_move_type::otw::Otw;
use af_sui_pkg_sdk::sui_pkg_sdk;
use af_sui_types::{Address, IdentStr, SUI_FRAMEWORK_ADDRESS};
use af_utilities::types::ifixed::IFixed;
use sui_framework_sdk::balance::Balance;
use sui_framework_sdk::dynamic_object_field::Wrapper;
use sui_framework_sdk::object::{ID, UID};
use sui_framework_sdk::sui::SUI;
use sui_framework_sdk::{Field, FieldTypeTag};

pub mod errors;
pub mod event_ext;
pub mod event_instance;
#[cfg(feature = "graphql")]
pub mod graphql;
pub mod math;
pub mod order_helpers;
pub mod order_id;
#[cfg(feature = "stop-orders")]
pub mod stop_order_helpers;

pub use self::market::{MarketParams, MarketState};
pub use self::orderbook::Order;
pub use self::position::Position;

// Convenient aliases since these types will never exist onchain with a type argument other than an
// OTW.
pub type AdminCapability = self::authority::Capability<self::authority::ADMIN>;
pub type AssistantCapability = self::authority::Capability<self::authority::ASSISTANT>;
pub type AdminAccountCap = self::account::AccountCap<self::account::ADMIN>;
pub type AssistantAccountCap = self::account::AccountCap<self::account::ASSISTANT>;
pub type Account = self::account::Account<Otw>;
pub type AccountTypeTag = self::account::AccountTypeTag<Otw>;
pub type StopOrderTicket = self::stop_orders::StopOrderTicket<Otw>;
pub type StopOrderTicketTypetag = self::stop_orders::StopOrderTicketTypeTag<Otw>;
pub type ClearingHouse = self::clearing_house::ClearingHouse<Otw>;
pub type ClearingHouseTypeTag = self::clearing_house::ClearingHouseTypeTag<Otw>;
pub type Vault = self::clearing_house::Vault<Otw>;
pub type VaultTypeTag = self::clearing_house::VaultTypeTag<Otw>;
pub type MarketInfo = self::registry::MarketInfo<Otw>;
pub type CollateralInfo = self::registry::CollateralInfo<Otw>;

/// Dynamic field storing a [`Vault`].
pub type VaultDf = Field<keys::MarketVault, Vault>;
/// Dynamic field storing a [`Position`].
pub type PositionDf = Field<keys::Position, Position>;
/// Dynamic field storing a leaf in a [`Map`] of [`Order`]s.
///
/// [`Map`]: self::ordered_map::Map
pub type OrderLeafDf = Field<u64, ordered_map::Leaf<Order>>;
/// Dynamic object field wrapper for the [`Orderbook`](orderbook::Orderbook) ID.
pub type OrderbookDofWrapper = Field<Wrapper<keys::Orderbook>, ID>;
/// Dynamic object field wrapper for the asks [`Map`](ordered_map::Map) ID.
pub type AsksMapDofWrapper = Field<Wrapper<keys::AsksMap>, ID>;
/// Dynamic object field wrapper for the bids [`Map`](ordered_map::Map) ID.
pub type BidsMapDofWrapper = Field<Wrapper<keys::BidsMap>, ID>;
/// Dynamic field storing a [`MarketInfo`].
pub type MarketInfoDf = Field<keys::RegistryMarketInfo, MarketInfo>;
/// Dynamic field storing a [`CollateralInfo`].
pub type CollateralInfoDf = Field<keys::RegistryCollateralInfo<Otw>, CollateralInfo>;

sui_pkg_sdk!(perpetuals {
    module account {
        /// Admin Role
        struct ADMIN();

        /// Assistant Role
        struct ASSISTANT();

        /// The AccountCap is used to check ownership of `Account` with the same `account_id`.
        struct AccountCap<!phantom Role> has key, store {
            id: UID,
            // Account object id
            account_obj_id: ID,
            /// Numerical value associated to the account
            account_id: u64,
        }

        /// The Account object saves the collateral available to be used in clearing houses.
        struct Account<!phantom T> has key, store {
            id: UID,
            /// Numerical value associated to the account
            account_id: u64,
            /// Balance available to be allocated to markets.
            collateral: Balance<T>,
            /// Tracks the `ID`s of all `AccountCap<ASSISTANT>`s that have the authority
            /// to interact with thie `Account`. Appended to in `new_assistant_account_cap`
            /// and reduced in `revoke_assistant_account_cap`.
            active_assistants: vector<ID>,
        }

        struct IntegratorConfig has store {
            /// Max **additional** taker fee the user is willing
            /// to pay for integrator-submitted orders.
            max_taker_fee: IFixed
        }
    }

    module authority {
        /// Capability object required to perform admin functions.
        ///
        /// Minted once when the module is published and transfered to its creator.
        struct Capability<!phantom Role> has key, store {
            id: UID
        }

        /// Admin Role
        struct ADMIN();

        /// Assistant Role
        struct ASSISTANT();
    }

    module clearing_house {
        /// The central object that owns the market state.
        ///
        /// Dynamic fields:
        /// - [`position::Position`]
        /// - [`Vault`]
        ///
        /// Dynamic objects:
        /// - [`orderbook::Orderbook`]
        struct ClearingHouse<!phantom T> has key {
            id: UID,
            version: u64,
            paused: bool,
            market_params: market::MarketParams,
            market_state: market::MarketState
        }

        /// Stores all deposits from traders for collateral T.
        /// Stores the funds reserved for covering bad debt from untimely
        /// liquidations.
        ///
        /// The Clearing House keeps track of who owns each share of the vault.
        struct Vault<!phantom T> has store {
            collateral_balance: Balance<T>,
            insurance_fund_balance: Balance<T>,
        }

        /// Stores the proposed parameters for updating margin ratios
        struct MarginRatioProposal has store {
            /// Target timestamp at which to apply the proposed updates
            maturity: u64,
            /// Proposed IMR
            margin_ratio_initial: IFixed,
            /// Proposed MMR
            margin_ratio_maintenance: IFixed,
        }

        /// Stores the proposed parameters for a position's custom fees
        struct PositionFeesProposal has store {
            /// Proposed IMR
            maker_fee: IFixed,
            /// Proposed MMR
            taker_fee: IFixed,
        }

        /// Structure that stores the amount of fees collected by an integrator
        struct IntegratorVault has store {
            /// Amount of fees collected by this integrator, in collateral units
            fees: IFixed,
        }

        struct IntegratorInfo has copy, drop {
            integrator_address: address,
            taker_fee: IFixed,
        }

        /// Stores the proposed parameters for a position's custom fees
        struct SettlementPrices has store {
            /// Base asset's settlement price
            base_price: IFixed,
            /// Collateral asset's settlement price
            collateral_price: IFixed,
        }
        /// Used by clearing house to check margin when placing an order
        struct SessionHotPotato<!phantom T> {
            clearing_house: ClearingHouse<T>,
            orderbook: orderbook::Orderbook,
            account_id: u64,
            timestamp_ms: u64,
            collateral_price: IFixed,
            index_price: IFixed,
            gas_price: u64,
            margin_before: IFixed,
            min_margin_before: IFixed,
            position_base_before: IFixed,
            total_open_interest: IFixed,
            total_fees: IFixed,
            maker_events: vector<events::FilledMakerOrder>,
            liqee_account_id: Option<u64>,
            liquidator_fees: IFixed,
            session_summary: SessionSummary
        }

        struct SessionSummary has drop {
            base_filled_ask: IFixed,
            base_filled_bid: IFixed,
            quote_filled_ask: IFixed,
            quote_filled_bid: IFixed,
            base_posted_ask: IFixed,
            base_posted_bid: IFixed,
            posted_orders: u64,
            base_liquidated: IFixed,
            quote_liquidated: IFixed,
            is_liqee_long: bool,
            bad_debt: IFixed
        }
    }

    module stop_orders {
        /// Object that allows to place one order on behalf of the user, used to
        /// offer stop limit or market orders. A stop order is an order that is placed
        /// only if the index price respects certain conditions, like being above or
        /// below a certain price.
        ///
        /// Only the `AccountCap` owner can mint this object and can decide who can be
        /// the executor of the ticket. This allows users to run their
        /// own stop orders bots eventually, but it's mainly used to allow 3rd parties
        /// to offer such a service (the user is required to trust such 3rd party).
        /// The object is shared and the 3rd party is set as `executors`. The ticket
        /// can be destroyed in any moment only by the user or by the executor.
        /// The user needs to trust the 3rd party for liveness of the service offered.
        ///
        /// The order details are encrypted offchain and the result is stored in the ticket.
        /// The user needs to share such details with the 3rd party only to allow for execution.
        ///
        /// The ticket can be either a shared, owned or party object.
        /// The permission to execute or cancel it is controlled exclusively through `executors`,
        /// which can be modified only by the `AccountCap` owner associated with the ticket
        /// using the function `edit_stop_order_ticket_executors`.
        struct StopOrderTicket<!phantom T> has key, store {
            id: UID,
            /// Addresses allowed to execute the order on behalf of the user.
            executors: vector<address>,
            /// The executor collects the gas in case the order is placed or canceled for any reason.
            /// The user gets back the gas in case he manually cancels the order.
            gas: Balance<SUI>,
            /// User account id
            account_id: u64,
            /// Value to indentify the stop order type. Available values can be found in the
            /// constants module.
            stop_order_type: u64,
            /// Vector containing the blake2b hash obtained from offchain on the stop order parameters.
            /// Depending on the stop order type value, a different set of parameters is expected to be used.
            ///
            /// Parameters encoded for a SLTP stop order (stop_order_type code 0):
            /// - clearing_house_id: ID
            /// - expire_timestamp: Option<u64>
            /// - is_limit_order: `true` if limit order, `false` if market order
            /// - stop_index_price: u256
            /// - is_stop_loss: `true` if stop loss order, `false` if take profit order
            /// - position_is_ask: `true` if position is short, `false` if position is long
            /// - size: u64
            /// - price: u64 (can be set at random value if `is_limit_order` is false)
            /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
            /// - salt: vector<u8>
            ///
            /// Parameters encoded for a Standalone stop order (stop_order_type code 1):
            /// - clearing_house_id: ID
            /// - expire_timestamp: Option<u64>
            /// - is_limit_order: `true` if limit order, `false` if market order
            /// - stop_index_price: u256
            /// - ge_stop_index_price: `true` means the order can be placed when
            /// oracle index price is >= than chosen `stop_index_price`
            /// - side: bool
            /// - size: u64
            /// - price: u64 (can be set at random value if `is_limit_order` is false)
            /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
            /// - reduce_only: bool
            /// - salt: vector<u8>
            encrypted_details: vector<u8>
        }
    }

    module events {
        struct CreatedAccount<!phantom T> has copy, drop {
            account_obj_id: ID,
            user: address,
            account_id: u64
        }

        struct DepositedCollateral<!phantom T> has copy, drop {
            account_id: u64,
            collateral: u64,
        }

        struct AllocatedCollateral has copy, drop {
            ch_id: ID,
            account_id: u64,
            collateral: u64,
        }

        struct WithdrewCollateral<!phantom T> has copy, drop {
            account_id: u64,
            collateral: u64,
        }

        struct DeallocatedCollateral has copy, drop {
            ch_id: ID,
            account_id: u64,
            collateral: u64,
        }

        struct CreatedOrderbook has copy, drop {
            branch_min: u64,
            branches_merge_max: u64,
            branch_max: u64,
            leaf_min: u64,
            leaves_merge_max: u64,
            leaf_max: u64
        }

        struct CreatedClearingHouse has copy, drop {
            ch_id: ID,
            collateral: String,
            coin_decimals: u64,
            margin_ratio_initial: IFixed,
            margin_ratio_maintenance: IFixed,
            base_oracle_id: ID,
            collateral_oracle_id: ID,
            funding_frequency_ms: u64,
            funding_period_ms: u64,
            premium_twap_frequency_ms: u64,
            premium_twap_period_ms: u64,
            spread_twap_frequency_ms: u64,
            spread_twap_period_ms: u64,
            maker_fee: IFixed,
            taker_fee: IFixed,
            liquidation_fee: IFixed,
            force_cancel_fee: IFixed,
            insurance_fund_fee: IFixed,
            lot_size: u64,
            tick_size: u64,
        }

        struct RegisteredMarketInfo<!phantom T> has copy, drop {
            ch_id: ID,
            base_pfs_id: ID,
            base_pfs_source_id: ID,
            collateral_pfs_id: ID,
            collateral_pfs_source_id: ID,
            scaling_factor: IFixed
        }

        struct RemovedRegisteredMarketInfo<!phantom T> has copy, drop {
            ch_id: ID,
        }

        struct RegisteredCollateralInfo<!phantom T> has copy, drop {
            ch_id: ID,
            collateral_pfs_id: ID,
            collateral_pfs_source_id: ID,
            scaling_factor: IFixed
        }

        struct AddedIntegratorConfig<!phantom T> has copy, drop {
            account_id: u64,
            integrator_address: address,
            max_taker_fee: IFixed
        }

        struct RemovedIntegratorConfig<!phantom T> has copy, drop {
            account_id: u64,
            integrator_address: address,
        }

        struct PaidIntegratorFees<!phantom T> has copy, drop {
            account_id: u64,
            integrator_address: address,
            fees: IFixed
        }

        struct CreatedIntegratorVault has copy, drop {
            ch_id: ID,
            integrator_address: address,
        }

        struct WithdrewFromIntegratorVault has copy, drop {
            ch_id: ID,
            integrator_address: address,
            fees: u64
        }

        struct UpdatedClearingHouseVersion has copy, drop {
            ch_id: ID,
            version: u64
        }

        struct PausedMarket has copy, drop {
            ch_id: ID,
        }

        struct ResumedMarket has copy, drop {
            ch_id: ID,
        }

        struct ClosedMarket has copy, drop {
            ch_id: ID,
            base_settlement_price: IFixed,
            collateral_settlement_price: IFixed
        }

        struct ClosedPositionAtSettlementPrices has copy, drop {
            ch_id: ID,
            account_id: u64,
            pnl: IFixed,
            base_asset_amount: IFixed,
            quote_asset_amount: IFixed,
            deallocated_collateral: u64,
            bad_debt: IFixed
        }

        struct UpdatedPremiumTwap has copy, drop {
            ch_id: ID,
            book_price: IFixed,
            index_price: IFixed,
            premium_twap: IFixed,
            premium_twap_last_upd_ms: u64,
        }

        struct UpdatedSpreadTwap has copy, drop {
            ch_id: ID,
            book_price: IFixed,
            index_price: IFixed,
            spread_twap: IFixed,
            spread_twap_last_upd_ms: u64,
        }

        struct UpdatedGasPriceTwap has copy, drop {
            ch_id: ID,
            gas_price: IFixed,
            mean: IFixed,
            variance: IFixed,
            gas_price_last_upd_ms: u64
        }

        struct UpdatedGasPriceTwapParameters has copy, drop {
            ch_id: ID,
            gas_price_twap_period_ms: u64,
            gas_price_taker_fee: IFixed,
            z_score_threshold: IFixed
        }

        struct UpdatedMarketLotAndTick has copy, drop {
            ch_id: ID,
            lot_size: u64,
            tick_size: u64
        }

        struct UpdatedFunding has copy, drop {
            ch_id: ID,
            cum_funding_rate_long: IFixed,
            cum_funding_rate_short: IFixed,
            funding_last_upd_ms: u64,
        }

        struct SettledFunding has copy, drop {
            ch_id: ID,
            account_id: u64,
            collateral_change_usd: IFixed,
            collateral_after: IFixed,
            mkt_funding_rate_long: IFixed,
            mkt_funding_rate_short: IFixed
        }

        struct FilledMakerOrders has copy, drop {
            events: vector<FilledMakerOrder>
        }

        struct FilledMakerOrder has copy, drop {
            ch_id: ID,
            maker_account_id: u64,
            taker_account_id: u64,
            order_id: u128,
            filled_size: u64,
            remaining_size: u64,
            canceled_size: u64,
            pnl: IFixed,
            fees: IFixed,
        }

        struct FilledTakerOrder has copy, drop {
            ch_id: ID,
            taker_account_id: u64,
            taker_pnl: IFixed,
            taker_fees: IFixed,
            integrator_taker_fees: IFixed,
            integrator_address: Option<address>,
            base_asset_delta_ask: IFixed,
            quote_asset_delta_ask: IFixed,
            base_asset_delta_bid: IFixed,
            quote_asset_delta_bid: IFixed,
        }

        struct PostedOrder has copy, drop {
            ch_id: ID,
            account_id: u64,
            order_id: u128,
            order_size: u64,
            reduce_only: bool,
            expiration_timestamp_ms: Option<u64>
        }

        struct CanceledOrder has copy, drop {
            ch_id: ID,
            account_id: u64,
            size: u64,
            order_id: u128,
        }

        struct LiquidatedPosition has copy, drop {
            ch_id: ID,
            liqee_account_id: u64,
            liqor_account_id: u64,
            is_liqee_long: bool,
            base_liquidated: IFixed,
            quote_liquidated: IFixed,
            liqee_pnl: IFixed,
            liquidation_fees: IFixed,
            force_cancel_fees: IFixed,
            insurance_fund_fees: IFixed,
            bad_debt: IFixed
        }

        struct PerformedLiquidation has copy, drop {
            ch_id: ID,
            liqee_account_id: u64,
            liqor_account_id: u64,
            is_liqee_long: bool,
            base_liquidated: IFixed,
            quote_liquidated: IFixed,
            liqor_pnl: IFixed,
            liqor_fees: IFixed,
        }

        struct SocializedBadDebt has copy, drop {
            ch_id: ID,
            bad_debt_usd: IFixed,
            socialized_fundings: IFixed,
            added_to_long: bool,
            cum_funding_rate_long: IFixed,
            cum_funding_rate_short: IFixed,
        }

        struct PerformedADL has copy, drop {
            ch_id: ID,
            bad_debt_account_id: u64,
            size_reduced: u64,
            collateral_transferred: IFixed,
            adl_price: u64,
            counterparty_account_id: u64,
            bad_debt_is_long: bool,
        }

        struct CreatedPosition has copy, drop {
            ch_id: ID,
            account_id: u64,
            mkt_funding_rate_long: IFixed,
            mkt_funding_rate_short: IFixed,
        }

        struct SetPositionInitialMarginRatio has copy, drop {
            ch_id: ID,
            account_id: u64,
            initial_margin_ratio: IFixed,
        }

        struct CreatedStopOrderTicket<!phantom T> has copy, drop {
            ticket_id: ID,
            account_id: u64,
            executors: vector<address>,
            gas: u64,
            stop_order_type: u64,
            encrypted_details: vector<u8>
        }

        struct ExecutedStopOrderTicket<!phantom T> has copy, drop {
            ticket_id: ID,
            account_id: u64,
            executor: address
        }

        struct DeletedStopOrderTicket<!phantom T> has copy, drop {
            ticket_id: ID,
            account_id: u64,
            executor: address
        }

        struct EditedStopOrderTicketDetails<!phantom T> has copy, drop {
            ticket_id: ID,
            account_id: u64,
            encrypted_details: vector<u8>
        }

        struct EditedStopOrderTicketExecutors<!phantom T> has copy, drop {
            ticket_id: ID,
            account_id: u64,
            executors: vector<address>
        }

        struct CreatedMarginRatiosProposal has copy, drop {
            ch_id: ID,
            margin_ratio_initial: IFixed,
            margin_ratio_maintenance: IFixed,
        }

        struct UpdatedMarginRatios has copy, drop {
            ch_id: ID,
            margin_ratio_initial: IFixed,
            margin_ratio_maintenance: IFixed,
        }

        struct DeletedMarginRatiosProposal has copy, drop {
            ch_id: ID,
            margin_ratio_initial: IFixed,
            margin_ratio_maintenance: IFixed,
        }

        struct CreatedPositionFeesProposal has copy, drop {
            ch_id: ID,
            account_id: u64,
            maker_fee: IFixed,
            taker_fee: IFixed,
        }

        struct DeletedPositionFeesProposal has copy, drop {
            ch_id: ID,
            account_id: u64,
            maker_fee: IFixed,
            taker_fee: IFixed,
        }

        struct AcceptedPositionFeesProposal has copy, drop {
            ch_id: ID,
            account_id: u64,
            maker_fee: IFixed,
            taker_fee: IFixed,
        }

        struct RejectedPositionFeesProposal has copy, drop {
            ch_id: ID,
            account_id: u64,
            maker_fee: IFixed,
            taker_fee: IFixed,
        }

        struct ResettedPositionFees has copy, drop {
            ch_id: ID,
            account_id: u64,
        }

        struct UpdatedFees has copy, drop {
            ch_id: ID,
            maker_fee: IFixed,
            taker_fee: IFixed,
            liquidation_fee: IFixed,
            force_cancel_fee: IFixed,
            insurance_fund_fee: IFixed,
        }

        struct UpdatedFundingParameters has copy, drop {
            ch_id: ID,
            funding_frequency_ms: u64,
            funding_period_ms: u64,
            premium_twap_frequency_ms: u64,
            premium_twap_period_ms: u64,
        }

        struct UpdatedSpreadTwapParameters has copy, drop {
            ch_id: ID,
            spread_twap_frequency_ms: u64,
            spread_twap_period_ms: u64
        }

        struct UpdatedMinOrderUsdValue has copy, drop {
            ch_id: ID,
            min_order_usd_value: IFixed,
        }

        struct UpdatedBasePfsID has copy, drop {
            ch_id: ID,
            pfs_id: ID,
        }

        struct UpdatedCollateralPfsID has copy, drop {
            ch_id: ID,
            pfs_id: ID,
        }

        struct UpdatedBasePfsSourceID has copy, drop {
            ch_id: ID,
            source_id: ID,
        }

        struct UpdatedCollateralPfsSourceID has copy, drop {
            ch_id: ID,
            source_id: ID,
        }

        struct UpdatedBasePfsTolerance has copy, drop {
            ch_id: ID,
            pfs_tolerance: u64,
        }

        struct UpdatedCollateralPfsTolerance has copy, drop {
            ch_id: ID,
            pfs_tolerance: u64,
        }

        struct UpdatedMaxSocializeLossesMrDecrease has copy, drop {
            ch_id: ID,
            max_socialize_losses_mr_decrease: IFixed,
        }
        struct UpdatedMaxBadDebt has copy, drop {
            ch_id: ID,
            max_bad_debt: IFixed,
        }

        struct UpdatedCollateralHaircut has copy, drop {
            ch_id: ID,
            collateral_haircut: IFixed,
        }

        struct UpdatedMaxOpenInterest has copy, drop {
            ch_id: ID,
            max_open_interest: IFixed,
        }

        struct UpdatedMaxOpenInterestPositionParams has copy, drop {
            ch_id: ID,
            max_open_interest_threshold: IFixed,
            max_open_interest_position_percent: IFixed,
        }

        struct UpdatedMaxPendingOrders has copy, drop {
            ch_id: ID,
            max_pending_orders: u64
        }

        struct UpdatedStopOrderMistCost has copy, drop {
            stop_order_mist_cost: u64
        }

        struct DonatedToInsuranceFund has copy, drop {
            sender: address,
            ch_id: ID,
            new_balance: u64,
        }

        struct WithdrewFees has copy, drop {
            sender: address,
            ch_id: ID,
            amount: u64,
            vault_balance_after: u64,
        }

        struct WithdrewInsuranceFund has copy, drop {
            sender: address,
            ch_id: ID,
            amount: u64,
            insurance_fund_balance_after: u64,
        }

        struct UpdatedOpenInterestAndFeesAccrued has copy, drop {
            ch_id: ID,
            open_interest: IFixed,
            fees_accrued: IFixed
        }

        struct CreatedAssistantAccountCap has copy, drop {
            account_id: u64,
            assistant_cap_id: ID,
        }

        struct RevokedAssistantAccountCap has copy, drop {
            account_id: u64,
            assistant_cap_id: ID,
        }
    }

    module keys {
        /// Key type for accessing a `MarketInfo` saved in registry.
        struct RegistryMarketInfo has copy, drop, store {
            ch_id: ID
        }

        /// Key type for accessing a `CollateralInfo` saved in registry.
        struct RegistryCollateralInfo<!phantom T> has copy, drop, store {}

        /// Key type for accessing a `Config` saved in registry.
        struct RegistryConfig has copy, drop, store {}

        /// Key type for accessing integrator configs for an account.
        struct IntegratorConfig has copy, drop, store {
            integrator_address: address,
        }

        /// Key type for accessing integrator's collected fees.
        struct IntegratorVault has copy, drop, store {
            integrator_address: address,
        }

        /// Key type for accessing  in clearing house.
        struct SettlementPrices has copy, drop, store {}

        /// Key type for accessing market params in clearing house.
        struct Orderbook has copy, drop, store {}

        /// Key type for accessing vault in clearing house.
        struct MarketVault has copy, drop, store {}

        /// Key type for accessing trader position in clearing house.
        struct Position has copy, drop, store {
            account_id: u64,
        }

        /// Key type for accessing market margin parameters change proposal in clearing house.
        struct MarginRatioProposal has copy, drop, store {}

        /// Key type for accessing custom fees parameters change proposal for an account
        struct PositionFeesProposal has copy, drop, store {
            account_id: u64
        }

        /// Key type for accessing asks map in the orderbook
        struct AsksMap has copy, drop, store {}

        /// Key type for accessing asks map in the orderbook
        struct BidsMap has copy, drop, store {}
    }

    module market {
        /// Static attributes of a perpetuals market.
        struct MarketParams has copy, drop, store {
            /// Set of parameters governing market's core behaviors
            core_params: CoreParams,
            /// Set of parameters related to market's fees
            fees_params: FeesParams,
            /// Set of parameters governing fundings and twap updates
            twap_params: TwapParams,
            /// Set of parameters defining market's limits
            limits_params: LimitsParams
        }

        struct CoreParams has copy, drop, store {
            /// Identifier of the base asset's price feed storage.
            base_pfs_id: ID,
            /// Identifier of the collateral asset's price feed storage.
            collateral_pfs_id: ID,
            /// Identifier of the base asset's price feed storage source id (pyth, stork, etc...).
            base_pfs_source_id: ID,
            /// Identifier of the collateral asset's price feed storage source id (pyth, stork, etc...).
            collateral_pfs_source_id: ID,
            /// Timestamp tolerance for base oracle price
            base_pfs_tolerance: u64,
            /// Timestamp tolerance for collateral oracle price
            collateral_pfs_tolerance: u64,
            /// Number of base units exchanged per lot
            lot_size: u64,
            /// Number of quote units exchanged per tick
            tick_size: u64,
            /// Scaling factor to use to convert collateral units to ifixed values and viceversa
            scaling_factor: IFixed,
            /// Value haircut applied to collateral allocated in the position.
            /// Example: 98%
            collateral_haircut: IFixed,
            /// Minimum margin ratio for opening a new position.
            margin_ratio_initial: IFixed,
            /// Margin ratio below which full liquidations can occur.
            margin_ratio_maintenance: IFixed,
        }

        struct FeesParams has copy, drop, store {
            /// Proportion of volume charged as fees from makers upon processing
            /// fill events.
            maker_fee: IFixed,
            /// Proportion of volume charged as fees from takers after processing
            /// fill events.
            taker_fee: IFixed,
            /// Proportion of volume charged as fees from liquidatees
            liquidation_fee: IFixed,
            /// Proportion of volume charged as fees from liquidatees after forced cancelling
            /// of pending orders during liquidation.
            force_cancel_fee: IFixed,
            /// Proportion of volume charged as fees from liquidatees to deposit into insurance fund
            insurance_fund_fee: IFixed,
            /// Additional taker fee to apply in case the gas price set for the transaction violates
            /// the z-score constraint
            gas_price_taker_fee: IFixed,
        }

        struct TwapParams has copy, drop, store {
            /// The time span between each funding rate update.
            funding_frequency_ms: u64,
            /// Period of time over which funding (the difference between book and
            /// index prices) gets paid.
            ///
            /// Setting the funding period too long may cause the perpetual to start
            /// trading at a very dislocated price to the index because there's less
            /// of an incentive for basis arbitrageurs to push the prices back in
            /// line since they would have to carry the basis risk for a longer
            /// period of time.
            ///
            /// Setting the funding period too short may cause nobody to trade the
            /// perpetual because there's too punitive of a price to pay in the case
            /// the funding rate flips sign.
            funding_period_ms: u64,
            /// The time span between each funding TWAP (both index price and orderbook price) update.
            premium_twap_frequency_ms: u64,
            /// The reference time span used for weighting the TWAP (both index price and orderbook price)
            /// updates for funding rates estimation
            premium_twap_period_ms: u64,
            /// The time span between each spread TWAP updates (used for liquidations).
            spread_twap_frequency_ms: u64,
            /// The reference time span used for weighting the TWAP updates for spread.
            spread_twap_period_ms: u64,
            /// The reference time span used for weighting the TWAP updates for gas price.
            gas_price_twap_period_ms: u64,
        }

        struct LimitsParams has copy, drop, store {
            /// Minimum USD value an order is required to be worth to be placed
            min_order_usd_value: IFixed,
            /// Maximum number of pending orders that a position can have.
            max_pending_orders: u64,
            /// Max open interest (in base tokens) available for this market
            max_open_interest: IFixed,
            /// The check on `max_open_interest_position_percent` is not performed if
            /// the market's open interest is below this threshold.
            max_open_interest_threshold: IFixed,
            /// Max open interest percentage a position can have relative to total market's open interest
            max_open_interest_position_percent: IFixed,
            /// Max amount of bad debt that can be socialized in nominal value.
            /// Positions that violate this check should be ADL'd.
            max_bad_debt: IFixed,
            /// Max amount of bad debt that can be socialized relative to total market's open interest.
            /// Positions that violate this check should be ADL'd.
            max_socialize_losses_mr_decrease: IFixed,
            /// Z-Score threshold level used to determine if to apply `gas_price_taker_fee` to the
            /// executed order
            z_score_threshold: IFixed,
        }
        /// The state of a perpetuals market.
        struct MarketState has store {
            /// The latest cumulative funding premium in this market for longs. Must be updated
            /// periodically.
            cum_funding_rate_long: IFixed,
            /// The latest cumulative funding premium in this market for shorts. Must be updated
            /// periodically.
            cum_funding_rate_short: IFixed,
            /// The timestamp (millisec) of the latest cumulative funding premium update
            /// (both longs and shorts).
            funding_last_upd_ms: u64,
            /// The last calculated funding premium TWAP (used for funding settlement).
            premium_twap: IFixed,
            /// The timestamp (millisec) of the last update of `premium_twap`.
            premium_twap_last_upd_ms: u64,
            /// The last calculated spread TWAP (used for liquidations).
            /// Spread is (book - index).
            spread_twap: IFixed,
            /// The timestamp (millisec) of `spread_twap` last update.
            spread_twap_last_upd_ms: u64,
            /// Gas price TWAP mean.
            /// It is used to calculate the penalty to add to taker fees based on the Z-score of the current gas price
            /// relative to the smoothed mean and variance.
            gas_price_mean: IFixed,
            /// Gas price TWAP variance.
            /// It is used to calculate the penalty to add to taker fees based on the Z-score of the current gas price
            /// relative to the smoothed mean and variance.
            gas_price_variance: IFixed,
            /// The timestamp (millisec) of the last update of `gas_price_mean` and `gas_price_variance`.
            gas_price_last_upd_ms: u64,
            /// Open interest (in base tokens) as a fixed-point number. Counts the
            /// total size of contracts as the sum of all long positions.
            open_interest: IFixed,
            /// Total amount of fees accrued by this market (in T's units)
            /// Only admin can withdraw these fees.
            fees_accrued: IFixed,
        }
    }

    module orderbook {
        /// An order on the orderbook
        struct Order has copy, drop, store {
            /// User's account id
            account_id: u64,
            /// Amount of lots to be filled
            size: u64,
            /// Optional reduce-only requirement for this order.
            reduce_only: bool,
            /// Optional expiration time for the order
            expiration_timestamp_ms: Option<u64>
        }

        /// The orderbook doesn't know the types of tokens traded, it assumes a correct
        /// management by the clearing house
        struct Orderbook has key, store {
            id: UID,
            /// Number of limit orders placed on book, monotonically increases
            counter: u64,
        }
    }

    module ordered_map {
        /// Ordered map with `u128` type as a key and `V` type as a value.
        struct Map<!phantom V: copy + drop + store> has key, store {
            /// Object UID for adding dynamic fields that are used as pointers to nodes.
            id: UID,
            /// Number of key-value pairs in the map.
            size: u64,
            /// Counter for creating another node as a dynamic field.
            counter: u64,
            /// Pointer to the root node, which is a branch or a leaf.
            root: u64,
            /// Pointer to first leaf.
            first: u64,
            /// Minimal number of kids in a non-root branch;
            /// must satisfy 2 <= branch_min <= branch_max / 2.
            branch_min: u64,
            /// Maximal number of kids in a branch, which is merge of two branches;
            /// must satisfy 2 * branch_min <= branches_merge_max <= branch_max.
            branches_merge_max: u64,
            /// Maximal number of kids in a branch.
            branch_max: u64,
            /// Minimal number of elements in a non-root leaf;
            /// must satisfy 2 <= leaf_min <= (leaf_max + 1) / 2.
            leaf_min: u64,
            /// Maximal number of elements in a leaf, which is merge of two leaves;
            /// must satisfy 2 * leaf_min - 1 <= leaves_merge_max <= leaf_max.
            leaves_merge_max: u64,
            /// Maximal number of elements in a leaf.
            leaf_max: u64,
        }

        /// Branch node with kids and ordered separating keys.
        struct Branch has drop, store {
            /// Separating keys for kids sorted in ascending order.
            keys: vector<u128>,
            /// Kids of the node.
            kids: vector<u64>,
        }

        /// Key-value pair.
        struct Pair<V: copy + drop + store> has copy, drop, store {
            key: u128,
            val: V,
        }

        /// Leaf node with ordered key-value pairs.
        struct Leaf<V: copy + drop + store> has drop, store {
            /// Keys sorted in ascending order together with values.
            keys_vals: vector<Pair<V>>,
            /// Pointer to next leaf.
            next: u64,
        }
    }

    module position {
        /// Stores information about an open position
        struct Position has store {
            /// Amount of allocated tokens (e.g., USD stables) backing this account's position.
            collateral: IFixed,
            /// The perpetual contract size, controlling the amount of exposure to
            /// the underlying asset. Positive implies long position and negative,
            /// short. Represented as a signed fixed-point number.
            base_asset_amount: IFixed,
            /// The entry value for this position, including leverage. Represented
            /// as a signed fixed-point number.
            quote_asset_notional_amount: IFixed,
            /// Last long cumulative funding rate used to update this position. The
            /// market's latest long cumulative funding rate minus this gives the funding
            /// rate this position must pay. This rate multiplied by this position's
            /// value (base asset amount * market price) gives the total funding
            /// owed, which is deducted from the trader account's margin. This debt
            /// is accounted for in margin ratio calculations, which may lead to
            /// liquidation. Represented as a signed fixed-point number.
            cum_funding_rate_long: IFixed,
            /// Last short cumulative funding rate used to update this position. The
            /// market's latest short cumulative funding rate minus this gives the funding
            /// rate this position must pay. This rate multiplied by this position's
            /// value (base asset amount * market price) gives the total funding
            /// owed, which is deducted from the trader account's margin. This debt
            /// is accounted for in margin ratio calculations, which may lead to
            /// liquidation. Represented as a signed fixed-point number.
            cum_funding_rate_short: IFixed,
            /// Base asset amount resting in ask orders in the orderbook.
            /// Represented as a signed fixed-point number.
            asks_quantity: IFixed,
            /// Base asset amount resting in bid orders in the orderbook.
            /// Represented as a signed fixed-point number.
            bids_quantity: IFixed,
            /// Number of pending orders in this position.
            pending_orders: u64,
            /// Custom maker fee for this position, set at default value of 100%
            maker_fee: IFixed,
            /// Custom taker fee for this position, set at default value of 100%
            taker_fee: IFixed,
            /// Initial Margin Ratio set by user for the position. Must always be less
            /// or equal than market's IMR. Used as a desired reference margin ratio when
            /// managing collateral in the position during all the actions. Can be changed
            /// by the user at any moment (between the allowed limits).
            initial_margin_ratio: IFixed
        }
    }

    module registry {
        /// Registry object that maintains:
        /// - A mapping between a clearing house id and `MarketInfo`
        /// - A mapping between a collateral type `T` and `CollateralInfo`
        /// It also maintains the global counter for account creation.
        /// Minted and shared when the module is published.
        struct Registry has key {
            id: UID,
            next_account_id: u64
        }

        /// Struct containing all the immutable info about a registered market
        struct MarketInfo<!phantom T> has store {
            base_pfs_id: ID,
            base_pfs_source_id: ID,
            collateral_pfs_id: ID,
            collateral_pfs_source_id: ID,
            scaling_factor: IFixed
        }

        /// Struct containing all the immutable info about the collateral
        /// used in one or more markets
        struct CollateralInfo<!phantom T> has store {
            collateral_pfs_id: ID,
            collateral_pfs_source_id: ID,
            scaling_factor: IFixed
        }

        /// Config that stores useful info for the protocol
        struct Config has store {
            stop_order_mist_cost: u64,
        }
    }
});

impl<T: af_move_type::MoveType> clearing_house::ClearingHouse<T> {
    /// Convenience function to build the type of a [`PositionDf`].
    pub fn position_df_type(package: Address) -> FieldTypeTag<self::keys::Position, Position> {
        Field::type_(
            self::keys::Position::type_(package),
            Position::type_(package),
        )
    }

    /// Convenience function to build the type of an [`OrderbookDofWrapper`].
    pub fn orderbook_dof_wrapper_type(
        package: Address,
    ) -> FieldTypeTag<Wrapper<keys::Orderbook>, ID> {
        Field::type_(
            Wrapper::type_(keys::Orderbook::type_(package)),
            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
        )
    }
}

impl self::orderbook::Orderbook {
    /// Convenience function to build the type of an [`AsksMapDofWrapper`].
    pub fn asks_dof_wrapper_type(package: Address) -> FieldTypeTag<Wrapper<keys::AsksMap>, ID> {
        Field::type_(
            Wrapper::type_(keys::AsksMap::type_(package)),
            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
        )
    }

    /// Convenience function to build the type of an [`BidsMapDofWrapper`].
    pub fn bids_dof_wrapper_type(package: Address) -> FieldTypeTag<Wrapper<keys::BidsMap>, ID> {
        Field::type_(
            Wrapper::type_(keys::BidsMap::type_(package)),
            ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
        )
    }
}

impl self::ordered_map::Map<Order> {
    /// Convenience function to build the type of an [`OrderLeafDf`].
    pub fn leaf_df_type(package: Address) -> FieldTypeTag<u64, self::ordered_map::Leaf<Order>> {
        Field::type_(
            af_move_type::U64TypeTag,
            self::ordered_map::Leaf::type_(package, Order::type_(package)),
        )
    }
}
