taler-typescript-core

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

commit c798bd1cd67add48b805f512b5072502d558651a
parent aec34138e692fe6c267027be7dc27e5c49e398ba
Author: Florian Dold <dold@taler.net>
Date:   Fri, 24 Jul 2026 15:52:52 +0200

wallet-core: don't report a balance change when scanning a payment URI

Diffstat:
Mpackages/taler-wallet-core/src/pay-merchant.ts | 12+++++++++---
Mpackages/taler-wallet-core/src/pay-peer-pull-debit.ts | 5++++-
Mpackages/taler-wallet-core/src/pay-peer-push-credit.ts | 5++++-
3 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts @@ -1226,7 +1226,9 @@ async function processDownloadProposal( ? PurchaseStatus.DialogShared : PurchaseStatus.DialogProposed; } - await h.update(p); + // Downloading the proposal only presents the offer to the user, no + // funds are committed until the payment is confirmed. + await h.update(p, BalanceEffect.None); }); return TaskRunResult.progress(); @@ -1245,7 +1247,9 @@ async function startPayReplay( rec.purchaseStatus = PurchaseStatus.PendingPayingReplay; rec.lastSessionId = sessionId; } - await h.update(rec); + // The coins were already spent by the original payment, replaying it + // for a new session does not spend anything on top of that. + await h.update(rec, BalanceEffect.None); tx.scheduleOnCommit(() => { wex.taskScheduler.resetTask(ctx.taskId).catch((e) => { logger.error(safeStringifyException(e)); @@ -1600,7 +1604,9 @@ async function storePayReplaySuccess( break; } purchase.lastSessionId = sessionId; - await h.update(purchase); + // A replay only demonstrates the earlier payment to the merchant, + // no additional funds are spent. + await h.update(purchase, BalanceEffect.None); }); } diff --git a/packages/taler-wallet-core/src/pay-peer-pull-debit.ts b/packages/taler-wallet-core/src/pay-peer-pull-debit.ts @@ -96,6 +96,7 @@ import { } from "./pay-peer-common.js"; import { createRefreshGroup } from "./refresh.js"; import { + BalanceEffect, constructTransactionIdentifier, isUnsuccessfulTransaction, parseTransactionIdentifier, @@ -1039,7 +1040,9 @@ async function internalPreparePeerPullDebit( status: PeerPullDebitRecordStatus.DialogProposed, totalCostEstimated: Amounts.stringify(totalAmount), }; - await h.update(newRec); + // Only the request is presented to the user, nothing is spent until + // the payment is confirmed. + await h.update(newRec, BalanceEffect.None); return { newRec, scopeInfo: await getExchangeScopeInfo(tx, exchangeBaseUrl, currency), diff --git a/packages/taler-wallet-core/src/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/pay-peer-push-credit.ts @@ -98,6 +98,7 @@ import { } from "./kyc.js"; import { getMergeReserveInfo, isPurseMerged } from "./pay-peer-common.js"; import { + BalanceEffect, constructTransactionIdentifier, isUnsuccessfulTransaction, parseTransactionIdentifier, @@ -671,7 +672,9 @@ async function internalPreparePeerPushCredit( currency: Amounts.currencyOf(purseStatus.balance), estimatedAmountEffective: Amounts.stringify(wi.withdrawalAmountEffective), }; - await h.update(newRec); + // Only the offer is presented to the user, the incoming funds are not + // counted towards the balance until the transfer is confirmed. + await h.update(newRec, BalanceEffect.None); return { scopeInfo: await getExchangeScopeInfo(tx, exchangeBaseUrl, currency), newRec,