@somnia-chain/markets-sdk / index / PerpMarket
Type Alias: PerpMarket
PerpMarket =
BaseMarket&object
Defined in: packages/sdk/src/markets.ts:115
A perpetual-futures order-book market. Rides the same OrderBook core as spot (base/quote book, raw quote units per whole base), with a synthetic base: positions + collateral live cross-margin in the MarginBank, and the pool tracks funding against an oracle index price.
Type Declaration
marketType
marketType:
"PERP"
Discriminator (narrowed).
baseToken
baseToken:
Address
Wrapper token standing in for the synthetic base (e.g. WBTC).
quoteToken
quoteToken:
Address
The MarginBank collateral token (e.g. USDso).
baseSymbol
baseSymbol:
string|null
Synthetic-base symbol (e.g. "WBTC"); null when the wrapper exposes none.
quoteSymbol
quoteSymbol:
string|null
Collateral token symbol (e.g. "USDso"); null when the token exposes none.
baseIsNative
baseIsNative:
boolean
Always false — the perp base is synthetic, never native. Kept so spot-shaped base/quote code paths can treat SPOT and PERP uniformly.
tickSize
tickSize:
string
Price increment, raw quote units per whole base (decimal string).
lotSize
lotSize:
string
Quantity increment, raw base units (decimal string).
minQuantity
minQuantity:
string
Minimum order quantity, raw base units (decimal string).
marginBank
marginBank:
Address
Cross-margin MarginBank holding collateral + positions (lowercased).
initialMarginBps
initialMarginBps:
number
Initial margin requirement in bps (500 = 5% = 20x max leverage).
stopRegistry
stopRegistry:
Address|null
Per-pool PerpStopOrderRegistry (lowercased); null on pools without one.
The registry is per-pool and every stop-order write takes it as an explicit
registry argument (Trader.placePerpStopOrder,
Trader.cancelPerpStopOrder, Trader.cancelPerpStopOrders), so
this is where that address comes from — same as stopRegistry on a
SpotMarket. Null means the pool has no registry deployed, and TP/SL is
unavailable on it rather than merely unfound.
markPrice
markPrice:
string|null
Mark price sampled at FUNDING cadence (raw quote per whole base).
Shares the column with the spot mark price but is a different quantity, and the difference matters:
- It advances only when funding settles — every ~300s on testnet, expected ~3600s on
mainnet — not per trade. For a live mark, read the chain
(
getPerpState().markPrice, which also reportsmarkPriceOk). - It is null whenever the contract emitted its 0 sentinel for a stale/reverting mark
feed. A stale feed leaves the PREVIOUS value in place rather than zeroing it, so a
non-null value here is not by itself evidence of freshness — compare
markPriceUpdatedAtagainst the settlement cadence. - It is NOT what drives funding. The premium is the order-book MIDPOINT versus the
index, not mark versus index, and the two routinely disagree in sign. Read
getPerpState().emaPremiumfor the quantity funding actually uses.
markPriceUpdatedAt
markPriceUpdatedAt:
string|null
When markPrice last advanced (unix seconds); null until the first settlement.
fundingRate
fundingRate:
string|null
Funding rate for the last settlement window (1e18-scaled fraction, signed). Null until the first FundingUpdated is indexed.
cumulativeFundingPerUnit
cumulativeFundingPerUnit:
string|null
Cumulative funding per base unit since inception (1e18-scaled, signed).
indexPrice
indexPrice:
string|null
Oracle index price at the last funding update (raw quote per whole base).
fundingUpdatedAt
fundingUpdatedAt:
string|null
Timestamp (unix seconds) of the last FundingUpdated; null until the first.
fundingWindowSec
fundingWindowSec:
number|null
The rate's DENOMINATOR in seconds (fundingCalculationWindowSec), 28800 on every
live pool. fundingRate above is per THIS window — not per settlement interval and
not annualized. Pass it to normalizeFundingRate and friends; a hardcoded
denominator produces a plausible-looking wrong chart rather than an error.
fundingIntervalSec
fundingIntervalSec:
number|null
Settlement cadence in seconds. 300 on testnet, expected 3600 on mainnet, so
fundingWindowSec / fundingIntervalSec is 96 vs 8 — the same rate value means a
12x different per-interval accrual between them.
openInterest
openInterest:
string|null
TOTAL open interest in base units.
Replaces longOpenInterest / shortOpenInterest. The contract keeps ONE counter
because the short side is provably equal in a matched CLOB, and the removed pair was
null on every row anyway — the subscription feeding it was dead.
openInterestUpdatedAt
openInterestUpdatedAt:
string|null
Timestamp (unix seconds) of the last OpenInterestUpdated; null until the first.