This week on Nexus 09.02.26
Order admission is gated on market lifecycle state, and preview now reads the actor’s live params instead of the lagging registry. The funding rate carries a nested clamp, and collateral floors are decided at the apply seam rather than taken at replay. Admin grants are provisioned from config and enforced through the gate, and accounts are replayed before the epoch is bumped. The leaderboard no longer 404s on a nonexistent season, and a self-trade’s legs are no longer dropped from the reward ledger. The CCXT surface reaches full operation coverage, BTC and ETH gain a two-product Pyth failover chain, and BTC-USDX-PERP moves back to Hyperliquid. Bridge reconciliation gates on the durable deposit and withdrawal counters, NexusVault.release pays an explicit destination, and an unparseable deposit-log amount is skipped rather than scored zero. Here is what shipped.
Trading and orders
- Order admission is gated on market lifecycle state. The engine checks a submitted order against the market’s lifecycle state before it reaches the book, so an order cannot be admitted while its market is in a state that shouldn’t accept one.
- Preview reads the actor’s live params, not the lagging registry. An order preview now reads the market actor’s live parameters directly instead of a registry copy that lagged behind, so a preview reflects the same params a submitted order would be matched against.
Risk, funding and collateral
- The funding rate carries a nested clamp. Funding-rate computation now applies a nested clamp, so a funding rate is bounded at more than one level rather than one flat cap.
- Collateral floors are decided at the apply seam, not taken at replay. Risk decides an account’s collateral floor at the point a change is applied instead of recomputing it during replay, so recovery reconstructs the same floor the account actually had rather than a floor derived after the fact.
Markets, listings and parameters
/readyis gated on engine price-band arming. The readiness endpoint now waits on the engine’s price bands being armed before it reports ready, so a service cannot be marked ready while the price band that protects a market isn’t yet in force.MarketResumedprojects once per journaled resume. A journaled resume now projects itsMarketResumedevent exactly once, so a resume that is replayed doesn’t emit the event a second time.
Admin access and grants
- Admin grants are provisioned from config, and the gate enforces them. An admin grant can now be provisioned directly from config, and the admin gate enforces whatever that config grants, so a grant’s source of truth is the config rather than a manual step.
State, recovery and the write-ahead log
- Accounts are replayed before the epoch is bumped. Recovery now replays every account’s state before it advances the epoch, so a reader can’t observe the new epoch with account state that hasn’t caught up to it yet.
Rewards and incentives
- The leaderboard no longer 404s on a nonexistent season. A leaderboard request for a season that doesn’t exist now gets a normal empty answer instead of a 404, so a client checking an upcoming or past season doesn’t have to treat a missing season as an error.
- A self-trade’s legs are no longer dropped from the reward ledger. The reward ledger’s primary key is widened to include the side of the fill, so both legs of a self-trade are recorded instead of one overwriting the other.
Market data and the interface
- Growth fills and the tail serve a per-leg fee. The indexer’s growth fills feed and its tail now carry the fee for each leg of a fill, so a client reading either can attribute fees to the specific leg that paid them.
- The order book publishes the merged sequence, not the poll counter. The indexer now publishes the sequence number from the merged book itself instead of a counter that only tracked how many times it had polled, so the sequence a client sees corresponds to the book’s own state.
/account/summaryflags its truncated windows. When/account/summaryhas to truncate the window it reports over, it now says so in the response, and its tests check that the flag is present rather than checking the window is complete.- The CCXT surface reaches full operation coverage, and a decision is recorded for every field it still doesn’t serve. Every operation on the CCXT surface is now implemented, and each unified CCXT field the API chooses not to serve carries a recorded decision rather than an unexplained gap.
Price feeds
- BTC and ETH gain a two-product Pyth failover chain. The oracle now falls back across two separate Pyth products for BTC and ETH instead of one, so a single product’s outage doesn’t remove Pyth as a source for either market.
- ETH gains a keyless Hyperliquid last-resort candidate. The oracle adds a Hyperliquid candidate for ETH that needs no API key as its last resort, so the final fallback doesn’t depend on a credential that could itself be unavailable.
- BTC-USDX-PERP moves back to Hyperliquid. The oracle now reads BTC-USDX-PERP’s price from Hyperliquid again, so the market’s mark is derived from the venue it followed before.
Bridge and deposits
GET /v1/bridge/assetsserves bridge asset metadata. A new endpoint answers with the bridge’s asset metadata, so a client can read what the bridge supports without inferring it from deposit or withdrawal responses.GET /v1/bridge/depositsserves a list and a by-id read model. The new endpoint answers both a list of bridge deposits and a lookup by id, so a client can page through deposits or fetch one directly.NexusVault.releasepays an explicit destination. The contract’s release function now pays out to a destination address it’s given rather than an implicit one, so the account released to is the one named in the call.- Bridge reconciliation gates on the durable deposit and withdrawal counters, watched by a shadow-divergence gauge. The bridge’s reconciliation now reads from the durable deposit and withdrawal counters instead of the counters it replaced, and a shadow gauge tracks any divergence between the two during the cutover.
- An unparseable deposit-log amount is skipped, not scored zero. When a deposit-log entry’s amount can’t be parsed, the bridge now skips it instead of recording it as a zero-value deposit, so a parsing failure doesn’t understate what was deposited.
Sandboxes, simulation and the build
Most of the plumbing this window went into the sandboxes and growth-engine’s split into its own services: a sandbox run states the stage and chain it ran on, a bench-gateway run carries the environment fingerprint its own schema requires, a sandbox venue that can’t be named as a URL is recorded as such instead of guessed at, and account signature verification gets its own benchmark. The market-making runner records the spread its ladder actually quotes and identifies itself and its bot on their metric series, and the prod-testnet environment is now catalogued. Elsewhere in the engine’s own plumbing: a RiskMutation’s value movements are classified, the journal’s unbounded dimension is measured and accepted, the ledger’s restore path keeps cause and capability names it doesn’t recognise instead of dropping them, and a divergence halt now carries its own reason.
Growth-engine’s attribution and incentive tracking move onto their own Postgres schemas and a season-config endpoint that the accrual, settlement, distribution and reward-ratio paths now read from, and the dead services template — and the Docker Build job it was the last reason for — is gone.
Behind the scenes
Alongside all of that, work landed on how access and secrets are controlled, and on how traffic is routed.