This week on Nexus 08.14.26
The liquidation path can take a distressed position onto a reserved system account, unwind it against the book under a bankruptcy bound, and route what is left over to the fund under one recorded budget — the whole route behind a per-risk-class flag that is off everywhere. Reduce-only is now checked against the whole position instead of one order at a time, the markets screener has a route and a sortable grid, the API spec moved into this repository and publishes on deploy, and every official client gained a caller-supplied network target.
Trading
- Reduce-only is checked against the whole position. The engine enforces reduce-only against the aggregate of an account’s resting reduce-only orders — read from a per-account index rather than by walking the book — and an amend re-validates it instead of inheriting the decision made at submission. A set of orders that individually reduce can no longer together flip the position.
- A restricted account can still close out. The indexer admits reduce-only order entry from a restricted account, so an account that may not open a position can still exit one.
- An amend keeps its fills and stops being measured against itself. The engine carries filled quantity forward across a price-only amend, and the risk check on an amend excludes the order being replaced.
- Trade fees settle against collateral, on a defined formula. Fill fees have a formula and move the account’s balance rather than being computed and left aside; liquidation fills are exempt, and the write-ahead log carries the fee schema inert until the formula is switched on.
- A maker rebate cannot exceed its taker fee. A rebate larger than the taker fee on the same trade is rejected, so a fill cannot pay out more than it collected.
Liquidations and risk
- A takeover seam, with the flag off everywhere. Position takeover lands as a cutover seam — a lifecycle state plus routing flagged by risk class — with the flag off in every environment, so nothing routes through it yet. The reserved account it moves a position onto has its own identity and non-participation guards, so it cannot appear as an ordinary counterparty.
- A takeover is decided before anything moves, and applied under one lock. The plan is a value produced by a pure decision step, and the execution path holds a single lock across decide and apply, so the position cannot move between the decision and its application.
- A takeover is a write-ahead-log record, and says so downstream. It is written with its own codec tag, applied on replay, and counted by a drift counter when replay and live state disagree; balance and position updates carry a takeover cause so a reader can tell one from an ordinary change.
- The unwind is bounded by the bankruptcy price. Each liquidation tick runs an unwind loop placing an immediate-or-cancel order bounded by the bankruptcy price, then sweeps the remainder to the backstop.
- Unwind profit and loss goes to the fund under one budget. The result of an unwind is routed to the insurance fund against a single recorded budget per takeover, so the cost of a takeover is one number rather than a sum of legs — and auto-deleveraging now triggers on that budget’s exhaustion rather than on a per-liquidation condition.
- Two terminal states, and no third halt reason. A takeover ends either in uncovered system loss or in auto-deleveraging exhausted, and neither adds a new halt reason. The engine surfaces uncovered system loss on the funding settlement and the indexer carries it through its wire mirror, so a settlement that could not be fully covered says so all the way out.
- Takeover rolls out one risk class at a time. The rollout is configured per risk class and reports gauges as it goes, with an operator runbook alongside it.
Markets and the interface
- The markets screener has a route and a sortable grid.
/marketsis a route in the frontend rather than a section of another page, and the markets table is a sortable grid with a defined column set and display formatters, so each column orders from its header and renders in the units it is quoted in. - Chrome statuses move to the bottom-left footer. Connection and session statuses render in the footer instead of the top chrome, which returns that space to the market.
- The shared navigation names the app it serves. The shared nav is re-authored against the trading interface and its link list now describes its only consumer.
Market data and history
- A market listed after boot gets coverage. The book poller refreshes its market list, so a market listed after the poller started is covered by book and mark data instead of waiting for a restart.
- A captured fill carries whose it was and what it realized. The captured fill row carries account identity and realized profit and loss, so history can answer per-account questions the tape previously dropped.
- Thirty days of realized profit and loss on the account summary.
/account/summaryreports realized profit and loss over a 30-day window.
Bridge and deposits
- Mainnet deposits are on Ethereum mainnet, and the chain id is asserted at startup. The chain label no longer falls back to a value compiled into the code, and the deposit watcher checks its pinned chain id against the node at startup — a watcher pointed at the wrong chain stops rather than indexes.
- Reconciliation pages, including when it stops running. A confirmed mismatch between chain and ledger raises a page directly rather than resting in a dashboard, and checks suppressed for long enough page too: a check that never runs no longer reads the same as a check that passes. The watcher also flags an on-chain release no recorded withdrawal accounts for, and will not advance its cursor past a deposit that has not settled.
- A reconciliation pause survives a restart, and holds say why. A pause is persisted rather than silently resumed, and held credits are exposed with the reason attached, so an operator can tell which hold is in force.
- A gap in the deposit log fails closed. A sequence gap in the deposit write-ahead log stops the service instead of being replayed over.
Streams and subscriptions
- The account stream is shared, routed and self-healing. Consumers share a single subscription rather than each opening their own, a fill is projected onto the account it belongs to so it arrives on the subscription that asked for it, and the stream re-establishes itself after an out-of-sync signal instead of staying disconnected.
Price feeds
- The oracle knows when a market is open. It consumes the engine’s session class and exports whether a feed’s market is open, so a stale price during a closed session is distinguishable from a stalled feed.
- A non-positive price cannot mark a candidate fresh. A feed candidate reporting a non-positive price no longer counts as a fresh observation.
Safety and reliability
- Market actors are supervised and respawned in process. The engine supervises its per-market actors and rebuilds a crashed market from the suffix of the write-ahead log rather than from a full replay, so one market’s failure does not require a restart of the rest — and a rebuild worker that stops making progress is detected instead of waiting indefinitely. A halt raised by a stale restart cannot be resumed away by an operator, and only the instance it was raised against can clear it.
- Boot replay streams, and is sized before it starts. Replay of the write-ahead log streams rather than loading whole, with bounded allocations across state, matching and risk margin, and a pre-flight check refuses an oversized replay up front rather than partway through.
- A commit-in-flight flag closes the publish race. The matching engine marks a commit in flight, closing the window between the durable write and the publish where a reader could observe one without the other.
- Mainnet configuration and access are stated, never inherited. The synthetic-credit kill switch is pinned off there rather than left ambiguous, a configuration render fails when a mainnet overlay leaves a feature flag implicit, and the proxy guards the unqualified
/positionsfamily so those routes are not reachable without the checks the qualified ones carry.
The API contract
- The API spec lives in this repository and publishes on deploy. The OpenAPI spec is owned in the monorepo and published as part of the deploy, so the served spec comes from the same commit as the service serving it — and drift checks now compare the implementation against the monorepo’s copy, catching drift before it is published.
- Unimplemented bridge operations come out of the contract. The first-phase
/v1/bridgeoperations that were never implemented are removed as a breaking change; the API changelog carries the migration. - The rate-limit model, environment-scoped keys and order outcomes are written down. The spec documents request weights, resource classes and the headers that report your budget, states that an API key is bound to one network, and puts
cancellation_reasonand self-trade prevention on the order contract — so a client can plan against the limits, and read why an order ended, rather than inferring either. - 98 operations under one published spec, and four clients checked against it. The spec now published from this repository describes 98 HTTP operations, and Rust, Python, TypeScript and the CLI are the official clients checked against the same pinned copy.
Developer tools and SDKs
- A caller-supplied network, in every client. The Rust, Python and TypeScript clients and the CLI each take a custom network with a base URL you supply, as a breaking change in each; the migration is in each client’s own release notes. The MCP server takes the same axis, and the TypeScript
baseUrlshortcut is deprecated in favour ofcustomNetwork(). - Two client-side security repairs. The TypeScript client mints websocket tokens on
POST /ws/token— the legacy route returned a token whose account channels were silently empty — and no longer follows redirects, because a 3xx forwarded the request signature to whatever origin the redirect named. - Order history, closed positions and equity history in Python, and paging that pages. The Python client implements
/orders/history,/positions/closedand/account/equity-history, follows the next-cursor header on trades and fills, and raises a jurisdiction refusal as its own error type. - Per-network credentials and real-funds guardrails in the CLI. Credentials are stored per network and commands touching real funds are guarded, as a breaking change with its migration in the CLI’s release notes.
Behind the scenes
The account layer moves out of the service and into a crate of its own, one boundary at a time — credentials and client order data first, then the withdrawal-block check, authentication and its replay guard, wallet-signature login and its session store, and delegated agent accounts — with the credential verifier assembled behind them and the swap proved before it was taken.
Elsewhere: builds get a cacheable dependency layer, and one fails rather than shipping without the geolocation database it needs; the benchmark harness reaches its configured sample size, type-checks its benches, reports one-sided ids, gives a below-floor move its own mark, and exits could-not-tell when there is nothing to compare; the sandbox gets a full-drain actor barrier and a risk-module cursor seam; and documentation-sync findings are posted twice a week. Plumbing, mostly — the kind that decides whether the next change is safe to make.