The admin screens
What each of the five staking admin screens tells you — the solvency overview and its thresholds, the pool and position tables, and the earnings desk.
Everything operational lives under Extensions → Staking Services
(/admin/staking). Five screens, gated by the permissions listed on the
install page.
| Screen | Path | Answers |
|---|---|---|
| Overview | /admin/staking |
Is anything waiting on me, and can I pay what I promised? |
| Pools | /admin/staking/pool |
What products are on sale? |
| Positions | /admin/staking/position |
Who holds what, and who wants out? |
| Earnings | /admin/staking/earning |
What has the platform made, and what do I still owe? |
| Settings | /admin/staking/settings |
Platform-wide rules — see Settings |
Overview — the solvency console
This is not a marketing dashboard. It exists to answer six questions, and every headline figure is a server-side aggregate over the whole table rather than a sample of the first page.
A pool is denominated in its own token. Principal, rewards and fees from a BTC pool and a USDT pool cannot be added together, so every money figure appears inside a row that carries exactly one symbol — the pool table, the asset table, the withdrawal queue. Book-level rollups are counts, which are always summable. A single unit is printed at the top only when the entire live book is one asset.
The old console summed a mixed book and put a dollar sign on it. If you have scripts reading these numbers, that is the change.
Alert rail. Three conditions surface above everything else:
- Settlement has stalled — positions matured more than 24 hours ago and
are still
ACTIVE. The cron settles matured positions on its next run, so a position that matured minutes ago is not a fault. Past a day, the cron is not running and you are holding people's principal beyond their term. - Requests awaiting a decision — the count, and how long the oldest has waited.
- Lists are capped — the pool table shows at most 24 pools and the withdrawal queue 10 rows. The banner appears only when there is more, so a truncated list is a stated fact rather than a guess.
Maturity ladder. Live principal in three bands: already matured and unsettled, due within 30 days, and locked beyond that. The meter is weighted by position count for the unit reason above. Matured comes first because it is the only band that is already a problem.
Tiles. Awaiting your decision · due this week · pools at capacity · pools underpaying. "At capacity" starts at 90% utilisation — not the point where a pool breaks, but the point where you still have time to raise capacity before it does.
Pool pressure. Ranked by what needs you first, not by display order: pending requests outrank stale positions, which outrank an underpaying or full pool, which outrank a merely busy one. Each row carries capacity utilisation, live positions, positions due this week, and the APR comparison.
Promised versus paying. Three rates per pool:
| Figure | Meaning |
|---|---|
| Advertised APR | What the pool page says |
| Net promised APR | Advertised, less the admin fee — what the staker should actually receive |
| Realised APR | What has actually been credited, annualised over principal-days |
Realised is measured against net promised, because a pool advertising 12% with a 20% fee pays 9.6% by design. A pool is flagged underpaying only when it is more than 5% below net promised — below that is rounding dust accumulating across thousands of accruals.
Pools that only settle at maturity (autoCompound or END_OF_TERM) never
advance a watermark during the term, so they report not measurable yet rather
than a false 0%.
Book by asset. One row per denomination: live principal, positions, rewards owed to stakers but unclaimed, and platform fees. The "unclaimed fees" figure is bookkeeping only — the money reached your wallet when the fee was collected, not when you mark the row claimed.
Withdrawal requests. Oldest first, because a request is work that arrived without you asking for it. Each row shows the principal, the exit cost computed exactly as settlement will compute it, how many days early the request was, and how long it has waited. A row can show "term ended while waiting" — the fee was fixed the day the user asked, so it still applies.
Flow counters. New positions, exits requested, settled and cancelled over the selected window (24h, 7d or 30d).
The page auto-refreshes every 30 seconds; the endpoint caches for 15 seconds, so a manual refresh always gets fresh numbers.
Pools
A standard data table over staking_pools with the columns you would expect,
plus per-pool analytics.
Actions: create, edit, change status, reorder, and delete. Reordering drives the display sequence users see, not anything economic.
Two rules the table enforces for you:
- Activating a pool while another
ACTIVEpool exists for the same symbol and wallet type is rejected. - Deleting a pool with live positions is rejected — settle them first.
Remember from Creating pools that the Available to
Stake field on the edit form does nothing. The update endpoint strips it, and
capacity changes only through an explicit capacityDelta sent to the API.
Positions
Every position across every pool, with computed rewards and earning detail per row. Filter by status to find work.
Row actions available with edit.staking.position:
- Approve withdrawal — only shown on
PENDING_WITHDRAWALrows. Settles the position, deducts the early-withdrawal fee and returns the principal. - Reject withdrawal — returns the position to
ACTIVE. No money moves. - Complete or Cancel — the terminal transitions described in Positions. They are not interchangeable: cancelling forfeits the staker's unclaimed rewards.
If an action fails, the confirmation dialog stays open showing the backend's reason. A dialog that closes is a dialog that succeeded.
Bulk complete, cancel and withdraw are available for up to 100 positions per call, each settled in its own transaction.
Earnings
The platform revenue desk, backed by staking_admin_earnings. It shows fee
income by pool and by type, with charts over time, and it is where both
distribution actions live.
Four earning types:
| Type | Written by |
|---|---|
PLATFORM_FEE |
The admin fee taken from every reward accrual and from bonus distributions |
EARLY_WITHDRAWAL_FEE |
An early exit settling before endDate |
PERFORMANCE_FEE |
Manual reconciliation entries only |
OTHER |
Reversals — notably the reversal booked when a cancellation forfeits rewards |
The wallet credit already happened when the fee was collected. Marking an earning claimed changes a bookkeeping flag and nothing else — it does not move money, and an unclaimed row is not money waiting to be paid to you. Treat the flag as a reconciliation tick.
There is also a manual create admin earning endpoint. It is explicitly bookkeeping-only: no wallet is credited and no ledger transaction is written. Use it to reconcile revenue that exists elsewhere, never to record revenue you have not received — the whole point of the collector-first design is that the earnings screen cannot overstate what the platform actually holds.
Distributing. The two doors are described in full under Rewards:
Run the accrual catch-up with dryRun: true first. It reports exactly what each
position would receive and what the platform would keep, without writing
anything.
External pool performance
A record-keeping table (staking_external_pool_performances) for logging what
an external venue actually returned on a given date — APR, total staked, profit
and free-text notes. Dates in the future are rejected.
Nothing in the reward engine reads these rows. They exist so you can reconcile what you paid stakers against what your real yield source produced, which is the comparison this product cannot make for you.
Activity log
Every pool creation, position transition and distribution writes a row to
staking_admin_activities with the actor, the action, the object type and the
related ID. Cron-driven distributions are recorded with a null user, marking
them as system actions. Readable with view.staking.activity.
This is separate from the platform-wide audit trail; both are worth keeping.