@somnia-chain/markets-sdk


@somnia-chain/markets-sdk / index / PerpOrderMarginPreview

Type Alias: PerpOrderMarginPreview

PerpOrderMarginPreview = { priceable: false; asOfBlock: bigint; } | { priceable: true; asOfBlock: bigint; increasingQuantity: bigint; reducingQuantity: bigint; lockAmount: bigint; initialMarginPortion: bigint; adverseGapPortion: bigint; leverageSurcharge: bigint; effectiveImfBps: bigint; markPrice: bigint; unlockedCollateral: bigint; equity: bigint; imRequirement: bigint; feeHeadroom: bigint; topUpRequired: bigint; wallet: { balance: bigint; allowance: bigint; } | null; walletCoversTopUp: boolean; hasCollateralForLock: boolean; meetsInitialMargin: boolean; voucherBlocked: boolean; restrictedBlocked: boolean; isolationBlocked: boolean; sufficient: boolean; }

Defined in: packages/sdk/src/perp/margin.ts:1454

What a perp order will cost and whether it will be accepted, computed BEFORE sending it.

A discriminated union: an unpriceable market yields no preview at all, because every component below needs the mark. Narrow on priceable first.

Union Members

Type Literal

{ priceable: false; asOfBlock: bigint; }

priceable

priceable: false

The pool's mark feed is stale or zero. Placement of any order with an increasing leg would revert on the contract's own freshness gate, so there is nothing to preview — and no field here could be trusted if there were.

asOfBlock

asOfBlock: bigint

The block every read was pinned to.


Type Literal

{ priceable: true; asOfBlock: bigint; increasingQuantity: bigint; reducingQuantity: bigint; lockAmount: bigint; initialMarginPortion: bigint; adverseGapPortion: bigint; leverageSurcharge: bigint; effectiveImfBps: bigint; markPrice: bigint; unlockedCollateral: bigint; equity: bigint; imRequirement: bigint; feeHeadroom: bigint; topUpRequired: bigint; wallet: { balance: bigint; allowance: bigint; } | null; walletCoversTopUp: boolean; hasCollateralForLock: boolean; meetsInitialMargin: boolean; voucherBlocked: boolean; restrictedBlocked: boolean; isolationBlocked: boolean; sufficient: boolean; }

priceable

priceable: true

asOfBlock

asOfBlock: bigint

The block every read was pinned to.

A preview is a statement about THIS block, not about the block the order lands in. The adverse-gap component moves one-for-one with the mark, so a limit bid above a falling mark locks more than quoted and either gate can flip. Re-quote near send time for anything close to the edge.

increasingQuantity

increasingQuantity: bigint

The part of the order that increases the position — the only part that locks.

reducingQuantity

reducingQuantity: bigint

The part absorbed by existing exposure. Locks nothing.

lockAmount

lockAmount: bigint

Total collateral the pool will lock (raw quote units) — the honest "margin required".

initialMarginPortion

initialMarginPortion: bigint

The initial-margin component of lockAmount, at the effective (OI-scaled) IMF.

adverseGapPortion

adverseGapPortion: bigint

The adverse mark-to-entry component of lockAmount, zero on a favourable entry.

A position opens at the order's price but is marked at the current mark, so a buy above mark (or sell below) is born underwater by that gap; the pool reserves it on top of initial margin. This is the term a naive notional × IMF estimate misses, and the usual reason a "max" order sized that way gets rejected.

leverageSurcharge

leverageSurcharge: bigint

Extra margin demanded because the account set a per-market leverage cap STRICTER than the market's effective IMF. Zero when unset or looser.

Charged on post-fill notional, and unlike the lock it comes out of free equity rather than being reserved.

effectiveImfBps

effectiveImfBps: bigint

The OI-scaled IMF actually applied, bps — not the static initialMarginBps.

markPrice

markPrice: bigint

Mark price the adverse gap was measured against.

unlockedCollateral

unlockedCollateral: bigint

Free collateral available to be locked.

equity

equity: bigint

Account equity (signed) before the lock.

imRequirement

imRequirement: bigint

Initial-margin requirement of EXISTING positions.

feeHeadroom

feeHeadroom: bigint

The pool's worst-case fee reserve for this order — an auto-pull addend, never part of lockAmount. See PerpOrderMarginQuote.feeHeadroom.

topUpRequired

topUpRequired: bigint

What auto-pull would take from the owner's wallet, 0n unless autoPull was passed. The number an order form should show as the wallet spend. See PerpOrderMarginQuote.topUpRequired, including the three cases where the pool declines and this reads 0n for a reason other than "nothing needed".

wallet

wallet: { balance: bigint; allowance: bigint; } | null

The owner's collateral-token balance and MarginBank allowance, null unless autoPull was passed. Both bind on topUpRequired, and which one is short decides whether the fix is "approve more" or "fund the wallet".

walletCoversTopUp

walletCoversTopUp: boolean

The wallet covers topUpRequired. See PerpOrderMarginQuote.walletCoversTopUp.

hasCollateralForLock

hasCollateralForLock: boolean

Gate 1 — the unlocked balance covers the lock, after any auto-pull. Failing it reverts InsufficientCollateral before margin is even checked.

Vacuously true when nothing is locked: the pool calls lockCollateral only if (lockAmount > 0), so a purely reducing order never touches this gate even from a negative unlocked balance. Without autoPull it is measured against unlockedCollateral alone — see PerpOrderMarginQuote.hasCollateralForLock.

meetsInitialMargin

meetsInitialMargin: boolean

Gate 2 — post-lock equity still covers the requirement: equity + topUpRequired - lockAmount >= imRequirement + leverageSurcharge.

Vacuously true for a purely reducing order, which the pool exempts outright (if (increasingQuantity > 0)) on the grounds that closing can only improve account health. An account below initial margin can therefore always reduce.

voucherBlocked

voucherBlocked: boolean

The account holds a credit-voucher floor and this increasing order is barred outright — the market is not on the voucher allowlist, or the protocol's voucher leverage cap is unset. Placement reverts VoucherMarketNotAllowed / VoucherLeverageCapNotSet, whatever the margin numbers say.

Distinct from the margin gates: when the market IS allowlisted, the voucher cap instead feeds the ordinary leverage path and shows up in leverageSurcharge rather than here.

restrictedBlocked

restrictedBlocked: boolean

The market is close-only and this order has an increasing leg, so placement reverts MarketRestricted. See PerpOrderMarginQuote.restrictedBlocked.

isolationBlocked

isolationBlocked: boolean

Isolated margin bars this market for this account, so placement reverts IsolatedMarketBlocked — the one gate here that blocks a reduce too. See PerpOrderMarginQuote.isolationBlocked.

sufficient

sufficient: boolean

Every gate. The order should be accepted.