@somnia-chain/markets-sdk / index / PerpStateOnchain
Interface: PerpStateOnchain
Defined in: packages/sdk/src/perp/state.ts:22
A perp pool's live pricing/funding state, read straight from chain in one pipelined fan-out. Fresher than the indexed Market row (funding fields there only update when FundingUpdated fires, i.e. per settlement window).
Properties
markPrice
markPrice:
bigint
Defined in: packages/sdk/src/perp/state.ts:24
EMA-smoothed oracle mark price (raw quote units per whole base).
markPriceOk
markPriceOk:
boolean
Defined in: packages/sdk/src/perp/state.ts:29
Whether the mark feed is live. When false, markPrice is not meaningful — the
FundingUpdated event signals the same condition with a 0 sentinel.
indexPrice
indexPrice:
bigint
Defined in: packages/sdk/src/perp/state.ts:31
Unsmoothed oracle index price (raw quote units per whole base).
indexUpdatedAt
indexUpdatedAt:
bigint
Defined in: packages/sdk/src/perp/state.ts:33
Index price oracle timestamp (seconds).
fundingRate
fundingRate:
bigint
Defined in: packages/sdk/src/perp/state.ts:35
Current funding rate per settlement window (1e18-scaled fraction, signed).
cumulativeFundingPerUnit
cumulativeFundingPerUnit:
bigint
Defined in: packages/sdk/src/perp/state.ts:37
Settled cumulative funding per base unit (1e18-scaled, signed).
projectedCumulativeFundingPerUnit
projectedCumulativeFundingPerUnit:
bigint
Defined in: packages/sdk/src/perp/state.ts:39
Cumulative funding projected to now (unsettled accrual included).
openInterest
openInterest:
bigint
Defined in: packages/sdk/src/perp/state.ts:47
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 two-field form
did not match the deployed ABI at all — it made every getPerpState call throw.
fundingWindowSec
fundingWindowSec:
number
Defined in: packages/sdk/src/perp/state.ts:53
The rate's DENOMINATOR in seconds (fundingCalculationWindowSec), 28800 on every
live pool. fundingRate is per THIS window — not per settlement interval and not
annualized. Normalize with it; never with a hardcoded constant.
fundingIntervalSec
fundingIntervalSec:
number
Defined in: packages/sdk/src/perp/state.ts:60
Settlement cadence in seconds. 3600 on every live pool, so
fundingWindowSec / fundingIntervalSec is 8. It has been 300 (n = 96), and the same
emitted rate means a 12x different per-interval accrual across that boundary — which
is why this is read per pool and never assumed. Indexed history still spans it.
lastFundingUpdateAt
lastFundingUpdateAt:
bigint
Defined in: packages/sdk/src/perp/state.ts:62
Last settlement, unix seconds (the chain stores nanoseconds).
nextFundingAt
nextFundingAt:
bigint
Defined in: packages/sdk/src/perp/state.ts:64
When the next settlement becomes due. Settlement is LAZY, so it may pass unmet.
emaPremium
emaPremium:
bigint
Defined in: packages/sdk/src/perp/state.ts:86
EMA'd premium driving the rate, and NOT mark vs index — expect it to disagree with
(mark - index) / index, which is a different quantity by design.
Since DEX-2252 the underlying premium is Binance's impact-price shape rather than a
book midpoint: [max(0, impactBid - index) - max(0, index - impactAsk)] / index,
where each impact price is the quantity-weighted price of filling a configured
impact notional on that side, counting only orders that pass a fillability check,
and time-weighted across the settlement interval. Three consequences:
- There is a deadband. An index sitting anywhere inside the impact spread prices exactly zero, so a merely wide book is no longer charged funding for its spread.
- Zero does not mean an empty book. A side that cannot show the impact notional of fillable depth drops out and the other side stands alone, so a ONE-SIDED book can carry a non-zero premium. Only a book with nothing priceable on either side is reliably zero.
- It lags the book, because it is an average over the interval rather than a reading at an instant.
Not recoverable from events, so this read is the only source.
oracle
oracle:
`0x${string}`
Defined in: packages/sdk/src/perp/state.ts:96
The pool's aggregator oracle contract.
This is the address the pool itself reads prices from, so it is the head of the
chain that produces markPrice and indexPrice — the aggregator chains to the
sim-controlled oracle and then to the agent EMA feed. It is a per-pool address:
every live pool reports a different one, so it cannot be substituted with a
per-network constant such as the deployment config's oracleHub.