commit 9bc232be913350e18766e7b314927ea0e52c7880
parent cc93bf0a7c79e6bf62a28a4e81d67956393b5b8b
Author: Florian Dold <florian@dold.me>
Date: Mon, 15 Sep 2025 14:29:49 +0200
wallet-core: disallow empty withdrawals
Diffstat:
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts
@@ -1227,7 +1227,7 @@ async function checkExchangeEntryOutdated(
* If the exchange entry doesn't exist,
* a new ephemeral entry is created.
*/
-async function startUpdateExchangeEntry(
+export async function startUpdateExchangeEntry(
wex: WalletExecutionContext,
exchangeBaseUrl: string,
options: { forceUpdate?: boolean } = {},
diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts
@@ -175,6 +175,7 @@ import {
listExchanges,
lookupExchangeByUri,
markExchangeUsed,
+ startUpdateExchangeEntry,
} from "./exchanges.js";
import {
GenericKycStatusReq,
@@ -3992,6 +3993,22 @@ export async function confirmWithdrawal(
instructedAmount,
req.forcedDenomSel,
);
+ // Disallow withdrawals with no coins, they don't make sense.
+ // We only make an exception for the dev experiment.
+ if (
+ wex.ws.devExperimentState.pretendNoDenoms != true &&
+ initialDenoms.selectedDenoms.length === 0
+ ) {
+ // Just in case, force talking to the exchange again,
+ // so a retry of the withdrawal might work.
+ await startUpdateExchangeEntry(wex, exchange.exchangeBaseUrl, {
+ forceUpdate: true,
+ });
+ throw TalerError.fromUncheckedDetail({
+ code: TalerErrorCode.WALLET_EXCHANGE_DENOMINATIONS_INSUFFICIENT,
+ hint: "No denominations could be selected for withdrawal",
+ });
+ }
}
await ctx.transition(