@somnia-chain/markets-sdk / index / LiquidationEvent
Type Alias: LiquidationEvent
LiquidationEvent =
object
Defined in: packages/sdk/src/perp/history.ts:146
A liquidation event (mirror of the indexer LiquidationEvent entity). All
numeric fields are raw units; any may be null when the source event didn't
carry it.
Properties
id
id:
string
Defined in: packages/sdk/src/perp/history.ts:148
Event id (${txHash}_${logIndex}).
account
account:
string
Defined in: packages/sdk/src/perp/history.ts:150
Liquidated account (lowercased).
pool
pool:
string|null
Defined in: packages/sdk/src/perp/history.ts:152
Perp pool (lowercased); null on account-scoped rows.
kind
kind:
string
Defined in: packages/sdk/src/perp/history.ts:183
WHICH stage of the liquidation/deleveraging waterfall this row is. Read this first — the rows are stages of one mechanism, not repetitions of one event, and without it an ADL leg is indistinguishable from a liquidation:
AccountLiquidated account-level summary (positionsProcessed, stageReached)
PositionLiquidated per-position liquidation (size, price)
PositionSkipped below min quantity, left in place (size)
PositionTakenOver stage-4 backstop takeover (counterparty = bidder, price)
AutoDeleveraged ADL leg (counterparty absorbed it; price = bankruptcy price)
Throttled DEFERRED by the pool's per-block volume cap
KeeperReward paid to the keeper that ran it (counterparty = keeper)
OrderPanicked the liquidation IOC reverted with a Solidity PANIC
PositionTransferred stage-4 transfer (counterparty, size)
CloseOutMarginSettled stage-4 close-out margin flow (counterparty)
BadDebtAbsorbed the fund was ASKED to cover (insuranceCovered, deficit,
counterparty = fund). It fires on the request, not on the
payment: insuranceCovered may be 0. Read that field
before you conclude the fund paid.
ResidualBadDebt uncovered, INSOLVENT hole after the waterfall (badDebt)
AdlPriceCapacityExhausted terminal: hole exceeds aggregate position capacity (badDebt)
ResidualBackedByOpenPnl hole fully backed by the account's OWN open PnL (deficit, equity)
CoverageDeclined coverage the equity cap DEFERRED (coverageDeclined)
AdlSessionDiscarded ADL session abandoned; amount is on the same-tx BadDebtAbsorbed row
AdlCapacityShortfall ADL could not source enough capacity (size)
A string, not LiquidationKind: the row carries what the DEPLOYED
indexer wrote, which can outrun a pinned SDK. isLiquidationKind
narrows it for an exhaustive switch or to pass back into the filter.
size
size:
string|null
Defined in: packages/sdk/src/perp/history.ts:190
Signed size for the leg, where the event carries one (raw base units).
Signed, not absolute: PositionLiquidated emits a signed sizeDelta, and the sign
is the side being closed.
price
price:
string|null
Defined in: packages/sdk/src/perp/history.ts:195
Price for the leg (raw quote per whole base) — mark price, takeover price, or ADL
bankruptcy price depending on kind.
counterparty
counterparty:
string|null
Defined in: packages/sdk/src/perp/history.ts:205
The other side of the leg: the ADL counterparty who absorbed it, the takeover
bidder, the transfer/close-out peer, or — on BadDebtAbsorbed — the Insurance Fund
the engine ASKED to cover. Null on rows with no counterparty.
On BadDebtAbsorbed this names the fund that was asked, not one that paid. The
address is recorded even when insuranceCovered is 0, so read that field to see
whether any value moved.
penalty
penalty:
string|null
Defined in: packages/sdk/src/perp/history.ts:207
Penalty charged (raw collateral; reserved — not carried by current events).
badDebt
badDebt:
string|null
Defined in: packages/sdk/src/perp/history.ts:228
The LEVEL of the account's uncovered, genuinely insolvent realized hole after this
liquidate() call — ResidualBadDebt, or AdlPriceCapacityExhausted for the
terminal price-capacity case (raw collateral).
A level, not a flow — never SUM this across rows. The underlying residual is a
post-call state sample, so a later call on the same account re-reports the same
(possibly changed) hole, and a stage-5 residual can co-fire with a terminal ADL one
in a single call: two samples of one hole at two stages.
Sound aggregates: the latest row per account is that account's currently known uncovered hole (an upper bound — a deposit can repay it with no row here, see MarginEvent), and the sum of those latest rows across accounts is point-in-time system bad debt.
Deliberately narrow: what the fund actually paid is LiquidationEvent.insuranceCovered,
a gross pre-coverage hole is LiquidationEvent.deficit, and a deferred coverage
decision is LiquidationEvent.coverageDeclined. Collateral that merely MOVED
between accounts is in collateralAmount.
insuranceCovered
insuranceCovered:
string|null
Defined in: packages/sdk/src/perp/history.ts:242
Wei the Insurance Fund ACTUALLY moved — BadDebtAbsorbed only (raw collateral).
A flow, and the only summable amount here: rows are disjoint payments, so a SUM
over any slice is exact fund outflow. A insuranceCovered below the same row's
deficit does NOT mean the fund was underfunded — part of a hole is unattributable
(a pre-existing balance, or funding owed), and that remainder surfaces as a
ResidualBadDebt row instead.
AdlSessionDiscarded deliberately leaves this null: its absorption is the same
absorbBadDebt call that emits BadDebtAbsorbed in the same transaction, so
counting both would double the outflow. Join on txHash.
deficit
deficit:
string|null
Defined in: packages/sdk/src/perp/history.ts:255
The GROSS realized hole a stage reported, before coverage (raw collateral) —
BadDebtAbsorbed (the full negative balance) and ResidualBackedByOpenPnl (a hole
the account's own open profit fully backs, so it is NOT bad debt; read equity
alongside it, and note it becomes bad debt if the position reverses).
A level, and overlapping per-stage views of one hole — never SUM, and never add to
badDebt. When BadDebtAbsorbed and ResidualBadDebt both fire in one call the
balance moved only by what the fund paid, so badDebt == deficit - insuranceCovered
for that call: a useful cross-row audit check, and the direct proof that summing the
gross figure with the residual double-counts.
coverageDeclined
coverageDeclined:
string|null
Defined in: packages/sdk/src/perp/history.ts:266
Attributable coverage the stage-5 equity cap did NOT pay — CoverageDeclined only
(raw collateral).
A flow and summable as "total coverage deferred", but NOT a loss: the fund underwrites insolvency and the account was not insolvent by that much at that moment. If the backing later evaporates the hole returns as a pre-existing negative balance, which is unattributable by definition, so it is written off rather than re-declined (accepted policy, OQ-13).
collateralAmount
collateralAmount:
string|null
Defined in: packages/sdk/src/perp/history.ts:272
Collateral that MOVED rather than was lost — PositionTransferred (collateral
following the position) and CloseOutMarginSettled. Kept separate from badDebt so
neither aggregate contaminates the other.
equity
equity:
string|null
Defined in: packages/sdk/src/perp/history.ts:274
Account equity where the event reports it (ResidualBackedByOpenPnl; signed).
positionsProcessed
positionsProcessed:
string|null
Defined in: packages/sdk/src/perp/history.ts:276
Positions processed (AccountLiquidated only).
stageReached
stageReached:
number|null
Defined in: packages/sdk/src/perp/history.ts:309
The deepest waterfall stage that ACTED (AccountLiquidated only).
The protocol enum is 0-indexed and has six members. The published waterfall numbers its stages 1 to 6. The two do not line up, so map them with this table:
0 OrderCancellation before stage 3 — cancelling the account's resting orders alone restored health 1 CLOBPartial stage 3 2 BidderTakeover stage 4 3 InsuranceFund stage 5 4 ADL stage 6 5 Deferred not a stage — stage 3 hit its per-block rate limit, and stages 4 to 6 were not consulted. Ships dormant, so it does not appear yet
Published stages 1 (Healthy) and 2 (Margin Call) are account states, not actions. The engine cannot reach them, so no value maps to them.
Two rules the number does not state on its own:
It names the deepest stage that ACTED, not the deepest stage consulted. A stage that
ran and moved nothing does not promote it. So BidderTakeover (2) beside a
BadDebtAbsorbed row is consistent, and means the fund was asked and paid nothing.
Check insuranceCovered on that row to confirm.
CLOBPartial (1) is a fall-through marker. It means stages 4 to 6 were consulted and
none of them acted. It does NOT prove stage 3 filled anything. Against an empty book
you get CLOBPartial with a positionsProcessed of 0, which means the account's
orders were cancelled and no position was closed. Always read positionsProcessed
with this field.
marginStatusBefore
marginStatusBefore:
number|null
Defined in: packages/sdk/src/perp/history.ts:311
Margin status before / after (AccountLiquidated only).
marginStatusAfter
marginStatusAfter:
number|null
Defined in: packages/sdk/src/perp/history.ts:312
timestamp
timestamp:
string
Defined in: packages/sdk/src/perp/history.ts:314
Timestamp (unix seconds) of the row.
blockNumber
blockNumber:
string
Defined in: packages/sdk/src/perp/history.ts:315
txHash
txHash:
string
Defined in: packages/sdk/src/perp/history.ts:317
Tx hash the row landed in. Stages of one liquidation share it.