Staking 6.1.9
11 August 2026
This release has upgrade notes. Read them before updating — they describe behaviour changes that need your attention.
Staking v6.1.9
Release Date: August 11, 2026 Tags: MONEY, SETTLEMENT, WITHDRAWALS, EARNINGS, FEES, REPORTING, PRIVACY, POOLS, ADMIN, RELIABILITY, PERFORMANCE, ANALYTICS, DATABASE, BUG-FIXES
Overview
A money release. Several defects in this add-on each moved the wrong amount, or moved nothing at all, and two of them cost a customer.
A staker who withdrew an auto-compounding position the moment their term ended was handed back their stake and none of the interest it had earned. A staker whose early-exit request was never worked by an admin had their principal frozen for good, with their own withdrawal screen answering "a withdrawal request is already in progress" for the rest of time. And the platform's own fee was silently dropped whenever the admin who pressed the button was the Super Admin — deducted from the staker's payout as always, then credited to nobody.
Figures move on the admin screens as a result and there are positions to check, so read Upgrade Notes before you update. The release also carries a performance pass over the staking screens, and repairs two admin actions that could report failure on work that had gone through.
Requires Core v6.6.3.
Update Instructions
pnpm updatorNothing to configure: no new settings, and no repair command to run.
There are records to inspect afterwards, and two admin figures change their meaning. Both are in Upgrade Notes.
Highlights
Every money defect here was one door disagreeing with another
A staking position can be settled through five doors: the staker's own withdraw button, three admin actions, and the hourly engine. This release is the result of walking all five and asking each of them what the same position was worth.
They did not agree. Only the engine knew how to price a matured compounding term, so the other four handed back the bare stake. The engine, in turn, could not see a position waiting on an admin's decision, so a request nobody worked outlived the term it was filed against with every other door refusing it. And the fee collector, asked who was paying, was being handed whichever admin had pressed the button rather than the staker the fee was skimmed from — so on a stock installation it recognised the house, correctly declined to charge the house a fee, and the platform's revenue quietly went to nobody.
What each of those has in common is that nothing failed. No error reached a screen, no log line said money had gone missing, and the totals on the admin dashboard kept adding up — against a number that was already wrong.
Upgrade Notes
A matured auto-compounding stake could be returned without its interest — check those positions
For an auto-compounding position the whole term's yield is paid at maturity, as one amount, by the hourly engine. Every other door returned the recorded stake instead, so a staker who pressed Withdraw in the window before the engine reached their position — or an admin who completed a matured position by hand — closed the term for exactly what was put in. Nothing recorded the shortfall, so it does not appear as an adjustment, a failed payout or a log line anywhere.
- Look for auto-compounding positions that have completed on or after their end date and whose recorded amount is still exactly what was staked. Those settled through the engine carry the compounded figure instead; those that do not are the ones that were short-paid.
- Run that check only over positions that closed before you update. Every door pays the compounded value now, but only the engine writes that figure back onto the position, so a position settled through the withdraw button after the update reads as short-paid when it was in fact paid in full.
- There is no automatic repair, because the platform kept no record of what was owed. The term's rate, its length and its fee percentage are all still on the position, which is what a manual correction needs.
Withdrawal requests that outlived their term will now settle themselves
A pending early-exit request past its own end date was invisible to the engine and refused by the staker's own withdrawal screen, so the principal sat locked with no door left open. Those positions are settled on the next pass after you update.
- Before you update, look at your pending staking withdrawal queue. Anything in it whose term has already ended will be completed automatically, with no early-withdrawal fee — the term ran to its end, so there is no early exit left to charge for. Requests still inside their lock period are untouched and continue to wait for your decision.
- If you were about to work that backlog by hand, do it after the update rather than during it.
Your platform fee and profit figures will change
Two corrections land on the same reports, and both move numbers you may have quoted.
- Staking fees now reach the treasury on admin-triggered work regardless of which account triggered it. On an installation where the Super Admin is the acting admin, earnings distributions, admin-approved early exits and admin-run accruals credited the treasury nothing before this release; they now collect it — the pool's admin fee on a distribution or an accrual, the pool's early-withdrawal fee on an approved early exit. Nothing changes for your stakers — the fee was always deducted from what they were paid — so expect fee revenue to appear where there was none, not to be taken from anybody. Past periods are not restated.
- A bonus distribution now records the money it hands out, not only the slice retained. Distributing 1,000 with a 20% fee used to report +200 profit at the moment the platform committed to paying 800 out; it now records both legs, and the treasury wallet is debited for what it funded, up to its available balance. Reported profit on a bonus distribution will be lower than you are used to, by the amount handed out. Distributions already run are not restated, so the profit reported against those stays overstated.
If you ever re-ran a distribution that reported an error, check that pool
The screen was capable of reporting a failure on a distribution that had been recorded, which invited a second run over the same period. Check that pool's earnings for that date.
The admin earnings report now covers the last ninety days
With no dates supplied the report read the entire admin earnings table and sent one history row per record to the browser, alongside totals and a per-pool breakdown computed over the same unbounded set. On an installation that has been distributing for a year that is the whole ledger, every time the page is opened.
- With no date filter the report describes the last ninety days — the totals, the per-pool breakdown and the history all now describe that one period. The earnings screen carries a pool filter but no date control, so this is the period it shows.
- If you read a headline total off that screen, it is no longer an all-time figure. A pool's lifetime earnings are still on the pool's own analytics.
The first backend start after updating will take longer
- One index is added to the earnings ledger, and it is built the first time the backend starts after the update. On a ledger with a long distribution history that first start takes noticeably longer than usual. Let it finish; it happens once.
Added
An index on the earnings ledger
The two places that look earnings up by distribution cycle — the guard that refuses a second distribution for a period, and the admin earnings report's grouped totals — could not use any existing index, because the one covering that column starts with the position rather than the cycle. Both scanned the table.
- Added an index keyed on the distribution cycle. The duplicate-distribution guard and the earnings report now find their rows directly instead of reading past every earning ever recorded.
Changed
Platform staking totals are now valued in one currency
The add-on publishes three platform-wide staking figures for anything integrating with it: total staked, average APR and total rewards. Each was a bare sum across every pool, and a staking position is denominated in its pool's own token — so half a Bitcoin, four thousand USDT and twelve million of a fractions-of-a-cent token were added together and published as one number. The average APR was weighted the same way, which let the pool with the most decimal places decide the platform's headline rate.
- Changed all three figures to be valued in USD before they are summed, and the APR to be weighted by that value rather than by raw token units. A pool whose token the platform has no rate for is excluded and named, so a caller can tell that a figure is a lower bound instead of being handed a total that is quietly short.
- Applies to the published figures only. None of the staking screens shipped with the add-on reads them, and the staking landing page's own counts are unchanged.
Your stakers' positions list
- Changed the positions list to total each position's earnings in one pass over the page. It previously ran two separate totals per position — two hundred queries on a full page — for two figures the database buckets in a single statement. The earned and unclaimed amounts shown are the same.
Pool analytics
- Changed the earnings distribution chart to bin its five amount bands in the database. Drawing it previously pulled every earning row the pool paid in the charted period across the wire so the five could be counted in memory. The bands and their boundaries are unchanged.
- Changed the average staking duration to be averaged in the database. It previously loaded every completed and active position in the pool to average three dates per row.
- Changed the pool's own rate to be read once. The handler already had the pool in hand and two of the four panels fetched the same row again to get it.
- Changed the four panels — the time series, the metrics, the distributions and the performance trend — to run together rather than one after another. None of them depends on another's result, so the page now waits for the slowest rather than for the sum of all four.
The admin earnings report
- Changed the per-record earnings attribution to a single grouped pass. The report issued one aggregate query per row in the period, so a report covering a few hundred distributions issued a few hundred queries. Rows old enough to predate the distribution cycle key still need their own lookup, and those now run a few at a time rather than all at once — a burst of them could take every connection in the pool the wallet layer shares.
Distributing earnings
- Changed the distribution to write its earning rows in batches and to check which positions were already credited once per thousand positions rather than once per position. A pool with a thousand active stakers issued two thousand statements to pay them; it now issues a handful. Every row still passes the same validation it did when written one at a time, and the run is still refused outright if two distributions collide on the same cycle.
- Changed the platform fee to be credited at the end of the distribution rather than the start. That fee is credited to the Super Admin wallet, which every fee collector on the platform contends for, and taking it first pinned that one row for the whole staker sweep — so a large distribution could hold up unrelated fee collection elsewhere. It is now held for the moment before the work commits, and the whole distribution still succeeds or fails as one.
- If the database rolls the distribution back under that contention, the run is refused with a message asking you to run it again. It is never reported as a success that paid nobody.
Requesting a withdrawal
- Changed the minimum withdrawal amount to govern filing an exit rather than settling one. It is still enforced when a staker asks to leave; it no longer applies on the way out, where re-checking it would have re-stranded the very positions this release unfroze.
Fixed
A matured auto-compounding stake was returned as bare principal
For a compounding position the yield is never written as claimable rewards during the term — it is priced once, at maturity, and folded into what comes back. Only the hourly engine knew how to price it. The staker's own withdraw button and all three admin doors returned the recorded stake instead, so a staker who withdrew the moment their lock expired received exactly what they staked and the whole term's interest stopped existing, with nothing recording that anything had been dropped.
- Fixed every door to settle a matured compounding position at its real value. The pricing, the platform fee on it and the ledger entry for the yield the platform funds now live in one place that both the engine and the settlement path call, so the two cannot disagree and nothing is booked twice.
A withdrawal request nobody approved locked the principal forever
On a default installation an early-exit request waits for admin approval, and until this release that was the only way out of it. The hourly engine looked at active positions only, so a pending request was skipped on every run from the moment it was filed — its end date passed, the term it was written for ended, and nothing settled it. The staker's own withdrawal screen refused them too, answering that a request was already in progress.
- Fixed the engine to settle a pending withdrawal request once the position's own term has ended, and the staker's withdraw button to do the same. A request still inside its lock period is untouched: that one is a genuine early exit awaiting your decision.
- Fixed that settlement to be treated as an ordinary maturity rather than an early exit, so no early-withdrawal fee is charged. The fee is priced from the date the staker asked to leave, which for these positions is a date inside the lock — charging it would have billed the staker for how long the request went unanswered.
The platform's fee depended on who pressed the button
The fee collector deliberately declines to charge the Super Admin, because charging the treasury and crediting it straight back inflates every profit report. It was being told the fee's payer was the admin who triggered the booking rather than the staker it was skimmed from — so on a stock installation, where that admin is the Super Admin, the fee was skipped. The staker was still charged: they were paid the net, with the fee already deducted. It simply arrived nowhere — no treasury credit, no profit row — so on an accrued reward the platform funded the whole gross yield and kept none of it. The same actions run by any other operator account collected normally.
- Fixed the payer to be the staker the fee comes out of. Earnings distributions, reward accruals and early-withdrawal fees now collect the pool's stated fee whoever runs them.
- Fixed the reverse case on cancellation. Rewards a staker forfeits by cancelling are money the platform had already funded and now keeps, so the funded amount is reversed out of the books — and that reversal was being skipped by the same rule, leaving a Super Admin's cancellations reported as a permanent loss.
A bonus distribution reported profit at the moment it paid out
Only the fee half of a bonus distribution was ever recorded. Where the fee reached the treasury at all, the profit report got a matching positive row for it — while the amount written across the stakers' positions had no counter-entry of any kind. Distributing 1,000 with a 20% fee reported +200 against a real result of −800, and an operator running repeated bonuses watched profit climb while the treasury drained.
- Fixed the distribution to record what it hands out as well as what it keeps, based on the rows actually written rather than the amount requested — rounding, skipped compounding terms and the per-position duplicate check can all make the two differ.
Cancelling a position could credit the treasury for rewards the staker had already been paid
The rewards a cancellation forfeits were counted from a view of the ledger taken before the position was locked, and a staker's claim landing in that window was invisible to it. The money left the platform and the platform booked it as recovered.
- Fixed the forfeited rewards to be counted under a lock, so a claim landing in that window is seen and only rewards that are genuinely still unclaimed are reversed.
An earnings distribution that ran could be reported as failed
Both actions save their work and then carry on to report it. A failure in that reporting step sent the action into its error handler, which ran a cleanup step against a transaction that had already been committed. That step fails on its own, and its failure is what reached the screen: an internal server error naming a database transaction state, on work that had gone through. An operator told a distribution failed has every reason to run it again, and the first one had already paid.
- Fixed the distribution reporting an internal error after the earnings had been written.
- Fixed reordering pools reporting the same on an order that had already been saved.
A staking pool page returned the internal note about a customer's own position
The pool page includes the caller's own positions, and those carried the operator's internal moderation commentary about the position and its holder. Both of the position screens already stripped that note, so it reached the same customer through a different door. Nothing displayed it — it travelled in the response, where anyone reading the page's own data could find it.
- Fixed the pool page to exclude it, at the query rather than afterwards, so a field added later is not silently included.
The positions summary added different tokens together
The four totals above a staker's positions summed every position regardless of what it was denominated in, so one Bitcoin and 500 USDT were printed as "501.00" with no unit — beside a figure on the same screen that already refuses that sum and says "3 assets" instead. Rounding to two places compounded it: a small token position read 0.00.
- Fixed the four totals to carry a unit when every position shares one, and to show the count of distinct assets when they do not. Precision now follows the size of the figure, so a fraction of a token is visible rather than rounded out of existence.