commit 054af1c13e7f09ebb25437e9a38b36db7c0cfc5e
parent f554c3a1abccd9cc04aca4a233f5a7065431b85f
Author: Florian Dold <dold@taler.net>
Date: Thu, 20 Aug 2026 19:06:45 +0200
wallet-core: finish waits for every terminal withdrawal
Diffstat:
2 files changed, 62 insertions(+), 11 deletions(-)
diff --git a/packages/taler-wallet-core/src/withdraw.test.ts b/packages/taler-wallet-core/src/withdraw.test.ts
@@ -26,9 +26,33 @@ import { test } from "node:test";
import {
DenominationVerificationStatus,
timestampProtocolToDb,
+ WithdrawalGroupStatus,
} from "./db-common.js";
import { WalletDenomination } from "./db-common.js";
import { selectWithdrawalDenominations } from "./denomSelection.js";
+import { isWithdrawalFinalStatus } from "./withdraw.js";
+
+test("every terminal withdrawal status ends final-state waits", () => {
+ for (const status of [
+ WithdrawalGroupStatus.Done,
+ WithdrawalGroupStatus.FailedBankAborted,
+ WithdrawalGroupStatus.FailedAbortingBank,
+ WithdrawalGroupStatus.AbortedExchange,
+ WithdrawalGroupStatus.AbortedBank,
+ WithdrawalGroupStatus.AbortedUserRefused,
+ WithdrawalGroupStatus.AbortedOtherWallet,
+ ]) {
+ assert.strictEqual(isWithdrawalFinalStatus(status), true, String(status));
+ }
+ assert.strictEqual(
+ isWithdrawalFinalStatus(WithdrawalGroupStatus.PendingReady),
+ false,
+ );
+ assert.strictEqual(
+ isWithdrawalFinalStatus(WithdrawalGroupStatus.SuspendedReady),
+ false,
+ );
+});
test("withdrawal selection bug repro", (t) => {
const amount = {
diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts
@@ -4554,21 +4554,48 @@ export async function waitWithdrawalFinal(
// Must've been deleted, we consider that final.
return true;
}
- switch (wg.status) {
- case WithdrawalGroupStatus.AbortedBank:
- case WithdrawalGroupStatus.AbortedExchange:
- case WithdrawalGroupStatus.Done:
- case WithdrawalGroupStatus.FailedAbortingBank:
- case WithdrawalGroupStatus.FailedBankAborted:
- // Transaction is final
- return true;
- }
-
- return false;
+ return isWithdrawalFinalStatus(wg.status);
},
});
}
+export function isWithdrawalFinalStatus(
+ status: WithdrawalGroupStatus,
+): boolean {
+ switch (status) {
+ case WithdrawalGroupStatus.PendingRegisteringBank:
+ case WithdrawalGroupStatus.SuspendedRegisteringBank:
+ case WithdrawalGroupStatus.PendingWaitConfirmBank:
+ case WithdrawalGroupStatus.SuspendedWaitConfirmBank:
+ case WithdrawalGroupStatus.PendingQueryingStatus:
+ case WithdrawalGroupStatus.SuspendedQueryingStatus:
+ case WithdrawalGroupStatus.PendingReady:
+ case WithdrawalGroupStatus.SuspendedReady:
+ case WithdrawalGroupStatus.PendingRedenominate:
+ case WithdrawalGroupStatus.SuspendedRedenominate:
+ case WithdrawalGroupStatus.PendingKyc:
+ case WithdrawalGroupStatus.SuspendedKyc:
+ case WithdrawalGroupStatus.PendingBalanceKyc:
+ case WithdrawalGroupStatus.SuspendedBalanceKyc:
+ case WithdrawalGroupStatus.PendingBalanceKycInit:
+ case WithdrawalGroupStatus.SuspendedBalanceKycInit:
+ case WithdrawalGroupStatus.DialogProposed:
+ case WithdrawalGroupStatus.AbortingBank:
+ case WithdrawalGroupStatus.SuspendedAbortingBank:
+ return false;
+ case WithdrawalGroupStatus.Done:
+ case WithdrawalGroupStatus.FailedBankAborted:
+ case WithdrawalGroupStatus.FailedAbortingBank:
+ case WithdrawalGroupStatus.AbortedExchange:
+ case WithdrawalGroupStatus.AbortedBank:
+ case WithdrawalGroupStatus.AbortedUserRefused:
+ case WithdrawalGroupStatus.AbortedOtherWallet:
+ return true;
+ default:
+ assertUnreachable(status);
+ }
+}
+
export async function getWithdrawalDetailsForAmount(
wex: WalletExecutionContext,
req: GetWithdrawalDetailsForAmountRequest,