Skip to main content

Vault & staking reads

Read queries on POST /info. The endpoint, the request envelope, the number planes and the error shape are on that page and apply to every query here.

Per-vault TVL, share price, and strategy

Returns a snapshot of one vault: TVL, share price, and strategy.

Request

{ "type": "vault_state", "vault": "0x<vault_addr>" }
FieldTypeRequiredMeaning
vaulthex addressyesVault to read

Response

{
"data": {
"type": "vault_state",
"vault": "0x<addr>",
"name": "MFlux Conservative",
"tvl": "10000000000",
"share_price": "10500000",
"depositor_count": 142,
"high_water_mark": "10500000",
"performance_fee_bps":"1000",
"lock_period_ms": 86400000,
"strategy": "User"
}
}
FieldTypeMeaning
vaulthex addressVault address
namestringVault display name
tvlDecimal stringMark-to-market net asset value — see Rules
share_priceDecimal stringMark-to-market value of one share — see Rules
depositor_countuintNumber of depositors
high_water_markDecimal stringPerformance-fee ratchet, not NAV — see Rules
performance_fee_bpsDecimal stringPerformance fee, in basis points
lock_period_msuint64Minimum deposit lock period, in milliseconds
strategystringVault kind: "User" or "Metaliquidity"

Rules

  • strategy is the vault's kind, "User" or "Metaliquidity". It is not a free-text strategy label.
  • tvl and share_price are mark-to-market NAV: settled cash, plus unrealised PnL on every open position at the latest oracle mark, plus unrealised funding. The Metaliquidity backstop vault also subtracts its pending-loss reserve. This is the same NAV that vault_withdraw burns shares against, so the read and the payout agree.
  • high_water_mark is not NAV. It is a ratchet for performance-fee accounting: profit raises it, a deposit raises it, a withdrawal lowers it, and a trading loss never changes it. In drawdown, high_water_mark sits above share_price — the gap is the profit the vault must re-earn before it charges a performance fee again. Never price a redemption off high_water_mark.

Per-account staking and delegation state

Returns one account's staking, delegation, and unbonding state.

Request

{ "type": "staking_state", "address": "0x<addr>" }
FieldTypeRequiredMeaning
addresshex addressyesAccount to read

Response

{
"data": {
"type": "staking_state",
"address": "0x<addr>",
"total_staked": "1000000000",
"delegations": [
{
"validator": "0x<val_addr>",
"amount": "500000000",
"lock_months": 6,
"reward_weight": "1250000000",
"since_ts": 1735000000000,
"pending_rewards": "1000000"
}
],
"pending_unstakes": [
{ "amount": "200000000", "matures_at_ts": 1735780000000 }
],
"total_stake": "87600000",
"pending_validator_pool_usdc": "8800.447354",
"n_active_validators": 5,
"reward_source": "fee_funded_on_book_buy"
}
}

The response is FLAT. total_stake, pending_validator_pool_usdc, n_active_validators and reward_source sit at the top level. There is no reward_pool object.

warning
lock_months and reward_weight are NOT LIVE YET

The two keys ship with the next node release. A live node serves a delegation row with exactly validator, amount, since_ts and pending_rewards — the example above shows the target shape, not today's. Read both keys as optional: absent on a live node, present after the release. A client that requires either key breaks against the chain you can reach today.

Everything the rules below say about the two keys describes the released behaviour. The rule that does hold today is the one about pending_rewards: a flexible row accrues nothing, and the served read gives you no way to see why until these keys land.

FieldTypeMeaning
addresshex addressResolved account address
total_stakedDecimal stringThis account's delegated stake only, whole-MTF — the sum of delegations[*].amount. It is "0" for an account that delegates nothing
delegations[*].validatorhex addressValidator the stake is delegated to
delegations[*].amountDecimal stringStake delegated to this validator, whole-MTF
delegations[*].lock_monthsuint8The row's lock tier in committed state: 0 flexible, or 1, 6, 24. It tells a delegator what to change. Do not compute reward_weight from it. NOT LIVE YET — see the notice above
delegations[*].reward_weightDecimal stringThis row's weight in its validator's reward split, on the same whole-MTF plane as amount. The row's share of a distribution is this weight over the sum of weights at that validator, before the validator's commission. It is a weight, not a payable amount. It is not derivable from lock_months — see the rules below. NOT LIVE YET — see the notice above
delegations[*].since_tsuint64Last reward-claim time, consensus ms — not the time the delegation began. Committed state keeps the last-claim stamp only. Do not compute a delegation age from it
delegations[*].pending_rewardsDecimal stringAccrued, unclaimed rewards, whole-MTF. A row whose reward_weight is "0" never accrues here — see the rules below
pending_unstakes[*].amountDecimal stringStake in the unbonding window, whole-MTF
pending_unstakes[*].matures_at_tsuint64When that amount becomes withdrawable, consensus ms
total_stakeDecimal stringTotal staked MTF across the whole chain, whole-MTF — the denominator this account's delegated stake competes in. Chain-wide, not per-account
pending_validator_pool_usdcDecimal stringFees accrued to the validator pool, not yet distributed, whole USDC. This is the reward the next distribution draws from. A constant value is normal — see the rule below
n_active_validatorsuint64Count of validators marked active in committed staking state
reward_sourcestringAlways "fee_funded_on_book_buy". Lets a client tell a fee-funded chain from an emission-funded one without inferring it

Rules

  • reward_weight is served, not derived. Do not rebuild it from lock_months. Three inputs set the weight, and the read carries only the result.

    1. The lock tier. A flexible row (lock_months: 0) weighs "0". A locked row weighs amount × 1.0 at 1 month, × 2.5 at 6 months, and × 4.0 at 24 months.
    2. The multiplier the row stored at delegate time. A governance retune of the ladder never rewrites an existing row. So a row can hold a multiplier the current ladder no longer gives.
    3. The locked-stake allowlist. A locked row whose validator is not in that allowlist is capped to amount × 1.0, whatever the tier. A 24-month row off the allowlist weighs the same as a 1-month row, not four times it. Governance can drop a validator from the allowlist after you delegate, so a correctly admitted row reaches this state without doing anything.

    A caller that rebuilds the ladder from lock_months alone misses the allowlist fallback and over-states the row's share. Read the served value.

  • A reward_weight of "0" beside a non-zero amount is not a late payment. The row earns nothing from a distribution, and it earns nothing from the next one either. pending_rewards never grows on that row, so waiting does not change the number. A delegator changes it by locking, not by waiting: undelegate the row, wait out the unbonding window, then delegate again with lock_months of 1, 6 or 24. The undelegated stake sits in pending_unstakes until that window matures and only then reaches the free pool a new delegation draws on, so this is not a same-block swap. Pick a validator on the locked-stake allowlist — a validator off it refuses a locked tier at delegate time.

  • This read serves no APR, on purpose. The emission era is over: rewards are funded from fees, not minted on a curve, so there is no annual rate to publish. Do not derive one. pending_validator_pool_usdc is a snapshot of accrued fees, not a rate — it depends on trading volume that has not happened yet.

  • A pool that does not move is not a stalled read. reward_source is "fee_funded_on_book_buy", and the second half of that name is a real step: the distribution spends the pooled USDC on the MTF/USDC book, then pays the MTF it ACQUIRED out by stake weight. It never credits USDC into an MTF-denominated reward, so a buy that fills nothing pays nothing. With no resting asks on MTF/USDC the buy acquires nothing, the distribution is skipped, and the pool carries forward unchanged. The pool is not spent and not stranded; it waits. A pool above the floor therefore does NOT mean a payout is due — check height on another read to tell a waiting pool from a frozen connection.

  • This read does NOT serve the undelegated free pool. c_deposit credits a free pool and c_withdraw debits it, and stake can sit in that pool undelegated for as long as the holder likes. No field on this read reports it. total_staked therefore under-reports what an account holds: it counts delegated stake only, so an account with a funded free pool and no delegation reads "0". Do not present total_staked as the account's whole staked balance.

  • The free pool is not the same as pending_unstakes. Undelegated stake is already free. pending_unstakes is stake still inside its unbonding window, not withdrawable until matures_at_ts.

  • total_staked and pending_unstakes are disjoint. token_delegate moves stake out of the free pool into total_staked; undelegating moves it out of total_staked into pending_unstakes for the unbonding window. Only the free pool is the figure c_withdraw returns to spot with no unbonding window.

  • total_stake and total_staked are different figures with near-identical names. total_stake is chain-wide; total_staked is this account. Do not swap them.