@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.