Next release — not live yet
Nothing on this page is live. The height is not pinned yet.
Every rule here ships with the next node release after 0.9.7, and the gateway rows ship with the gateway of the same release. Until the swap, a live chain answers the OLD behaviour named beside each row. Read this page to prepare a client, not to explain what you see today.
{"type":"account_state","address":"0x…"} carries the live height if you need
to check where the chain is.
Every raw-size row states its own size plane
node_fills, node_trades and node_order_statuses each gain a sz_decimals
field. It is the plane THAT ROW was written on, and it is what you divide the
row's raw size by.
Archive candles gain the same field, and the candle read normalizes a bar by
the plane the bar states rather than by the market's current one.
Why it matters, and why it is not cosmetic. A market's size precision can
RISE by a governance vote. The vote multiplies every stored lot count, so no
real quantity moves — but a row written before the vote keeps the smaller lot
count. A reader that divides every row by the market's CURRENT precision reports
each of those older rows 10^Δ too small. That error is silent: the numbers
stay well-formed and understate.
Before the swap these fields are absent. A row with no sz_decimals means
"not recorded" — fall back to the market's current precision, which is exact
only while no raise has happened since that row was written. No raise has
enacted yet, so the fallback is exact today.
Checklist
- Read
sz_decimalsper ROW; treat an absent value as the market's current precision, and only that. - Stop caching a market's precision across a read. It is per-row now.
- A perp's precision NEVER comes from a spot token, even where the names match. Read it from the market.
Two ceilings also change unit, with no change to their stored values:
per_market_limits.max_oi and max_oi_per_second are documented as WHOLE UNITS
of the base asset, not raw lots. They are one pair of numbers for every perp, and
a lot means a different real quantity on each market, so a shared lot count could
not state one real limit.
Four relocated reads answer 410 instead of 400
spot_meta, all_mids, active_asset_ctx and user_events answer a bare 400
UNKNOWN_TYPE today, even though this reference names a replacement for each. They
join the 410 set and carry details.use, naming the read to call instead.
Nothing that works today stops working: a 400 and a 410 both mean "do not call
this name". Branch on error.code rather than on the status, and a client is correct
on both sides of the swap.
The faucet gives one claim per address, ever, and one grant per IP per day
Two rules change together.
Once ever becomes a claim COUNT, not a value cap. The committed row accumulates
toward 3000 USDC / 10 MTF today, so it bounds a lifetime VALUE: an address that asked
for less kept the remainder and could come back. After the swap the row records that
the address has claimed. Asking for less than the full grant spends the slot, and
the handler answers 429 before it queues rather than after.
The per-IP window goes from one MINUTE to one DAY (86400 s, configurable). It is node-local and resets on restart, before and after — a speed bump, not an anti-sybil control.
Checklist
- Ask for the FULL grant. There is no second call for the remainder.
- Treat
429 address already fundedas final for that address. - Expect one grant per source IP per day, not per minute.
Breaking: vault_modify signs a new type
The EIP-712 type string gains six words, so every field the action applies is inside the digest:
MetaFluxTransaction:VaultModify(string metafluxChain,uint64 vaultId,string newName,bool hasNewLockPeriodSecs,uint64 newLockPeriodSecs,bool hasNewManagementFeeBps,uint16 newManagementFeeBps,bool hasNewPaused,bool newPaused,uint64 nonce)
Each optional field signs as two words: a presence bool, then the value. An
absent key and a key sent as 0 are different digests, so one signature covers
exactly one wire form.
A signature made with the four-field string stops verifying at the swap. The capability is unreachable from a client that has not moved. Update the signing type, then re-sign.
Why: the old digest bound new_name alone, and a relay could add a fee change or
a pause to a signature the leader gave for a rename.
Checklist
- Move to the new type string — see typed-data signing.
- Send the exact field set you signed. An added or removed key is refused.
- Update both client SDKs before the swap. An old SDK cannot sign the action.
statuses gains parked, and the array gets longer
A TP/SL or stop leg accepted off the book now reports
{"parked":{"oid","cloid"}}. A
position_tpsl group used to answer an empty statuses array, and a mixed
normal_tpsl batch answered fewer entries than it sent legs.
The same token lands on the order_updates
feed and in the node's node_order_statuses stream.
A closed union breaks on it. A client that parses statuses into a closed
enum fails the WHOLE response on the new key. Add the arm first.
parked is the term across this reference.
order_status answers the legacy
token triggered for the same state, and that one endpoint does not change.
A rejected leg's error loses a level
statuses[i].error IS the {code, message, details?} object. A live node wraps
it once more, so a caller reading statuses[i].error.error.code must drop one
level. The reference has always documented the flat shape, and both client SDKs
already type it.
A replayed nonce gets a verdict
An action the block builder drops as a replay now answers
NONCE_REPLAYED at HTTP 200. A live node
drops it in silence, so the caller waits out the order window and the gateway
answers a 502.
nonce_must_increase and nonce_too_small never existed on this API. Branch on
the code.
cloid dedup runs per leg
batch_order checks every leg that
carries a cloid, and scale_order
checks its ladder handle. Two legs of one action that share a cloid refuse the
whole action.
Two consequences:
- A ladder handle is reserved. A later single order that reuses it is refused. On a live node that order JOINS the group instead.
- An attempt the COMMIT refused gives its
cloidback, so a re-signed retry may reuse the handle.
order_status stops answering unknown twice
A cancelled SPOT order answers canceled. A spot order or scale rung that
neither rests nor matches answers rejected, with
reason: "Order could not immediately match against any resting orders." A
parked leg also resolves by cloid from committed state, so it keeps resolving
after a node restart, and its trigger object carries cloid.
Three silent accepts become refusals
| Action | New refusal |
|---|---|
agent_set_abstraction | PRECONDITION_FAILED — agentSetAbstraction is not available; the account owner must sign userSetAbstraction. It never set a config; a live node accepts the call and writes nothing |
update_leverage | PRECONDITION_FAILED — no perp market for asset. A live node writes a leverage row for a market that does not exist |
c_deposit / c_withdraw | INVALID_REQUEST — amount is finer than the token's wei_decimals. A live node commits a sub-wei amount and leaves dust no ledger row can render |
Read-side and WebSocket rows
active_asset_datarefuses a spot pair, an unknown coin and a coin that names no perp, with{"channel":"error","data":{"error":"market not found"}}. A live gateway answers a zeroed snapshot that blanks your ownaddressandcoin.- A subscribe answers ONE snapshot frame.
open_ordersstays the exception. trades:limitcaps the merged answer. A live gateway can return up to twice the number you asked for on a ranged ask.trades.last_tradeis the newest print in THIS answer, which is what the reference has always said. A live node stamps the MARKET's newest print on a windowed page, so the page reads as if it ran later than it does.candle_snapshot:coverage.reaches_newestis proved against the newest bar the store holds, not against yourend_time. An archive-served bar stampsTast + interval − 1like every other source.
Two corrections to this reference
Neither is a change to the chain. The reference was wrong and the code was right.
top_up_isolated_only_marginaccepts a PLAIN isolated position, not strict-isolated only.candle_snapshotserves real trade volume inv,qandnon amarkororaclebar. They are not"0", andnis not a sample count.