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:
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,