taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit fe652b24948b0e875eb8fde89d3e3c80c50e3f6b
parent f15a63c8861dc164c39b723658e4e5df3b6e1e8d
Author: Florian Dold <dold@taler.net>
Date:   Thu,  3 Sep 2026 15:56:11 +0200

wallet-core: keep coins already withdrawn from a retired denomination

Redenomination discarded them from the totals while still counting
their cost as reserve balance, so the new selection asked for more
than the reserve held.

Diffstat:
Mpackages/taler-wallet-core/src/withdraw.ts | 19++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts @@ -2827,6 +2827,7 @@ async function redenominateWithdrawal( skip: sel.count, }); + let numDone = 0; for (let j = 0; j < sel.count; j++) { const ci = coinIndex + j; const p = planchetsByIndex.get(ci); @@ -2838,13 +2839,25 @@ async function redenominateWithdrawal( ); continue; } - // Technically the planchet could already - // have been withdrawn, then we're in for another - // re-denomination later. + if (p.planchetStatus === PlanchetStatus.WithdrawalDone) { + // Already a coin; it stays, and its cost has left the reserve. + numDone++; + continue; + } logger.info(`aborting planchet #${coinIndex}`); p.planchetStatus = PlanchetStatus.AbortedReplaced; await tx.upsertPlanchet(p); } + if (numDone > 0 && denom != null) { + const doneValue = Amount.from(denom.value).mult(numDone); + const doneFee = Amount.from(denom.fees.feeWithdraw).mult(numDone); + remaining = remaining.sub(doneValue).sub(doneFee); + prevTotalCoinValue = prevTotalCoinValue.add(doneValue); + prevTotalWithdrawalCost = prevTotalWithdrawalCost.add( + doneValue, + doneFee, + ); + } } coinIndex += sel.count;