taler-typescript-core

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

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:
Mpackages/taler-wallet-core/src/withdraw.test.ts | 24++++++++++++++++++++++++
Mpackages/taler-wallet-core/src/withdraw.ts | 49++++++++++++++++++++++++++++++++++++++-----------
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,