taler-typescript-core

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

commit 504c0c1b27e7171aa1c44beaa6a161023e88a75d
parent 496fb2697ed65a699f759ef12281b51f66c43e51
Author: Florian Dold <dold@taler.net>
Date:   Thu, 20 Aug 2026 19:06:44 +0200

wallet-core: align peer pull-credit actions and handlers

Diffstat:
Apackages/taler-wallet-core/src/pay-peer-pull-credit.test.ts | 106+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpackages/taler-wallet-core/src/pay-peer-pull-credit.ts | 15+++++++--------
2 files changed, 113 insertions(+), 8 deletions(-)

diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.test.ts b/packages/taler-wallet-core/src/pay-peer-pull-credit.test.ts @@ -0,0 +1,106 @@ +/* + This file is part of GNU Taler + (C) 2026 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +import { TransactionAction } from "@gnu-taler/taler-util"; +import assert from "node:assert"; +import { test } from "node:test"; +import { + PeerPullPaymentCreditStatus, + WalletPeerPullCredit, +} from "./db-common.js"; +import { WalletDbTransaction } from "./dbtx.js"; +import { + computePeerPullCreditTransactionActions, + PeerPullCreditTransactionContext, +} from "./pay-peer-pull-credit.js"; +import { WalletExecutionContext } from "./wallet.js"; + +function makeRecord(status: PeerPullPaymentCreditStatus): WalletPeerPullCredit { + return { + pursePub: "purse-pub", + exchangeBaseUrl: "https://exchange.example/", + amount: "TESTKUDOS:1", + estimatedAmountEffective: "TESTKUDOS:1", + pursePriv: "purse-priv", + contractTermsHash: "contract-hash", + mergePub: "merge-pub", + mergePriv: "merge-priv", + contractPub: "contract-pub", + contractPriv: "contract-priv", + contractEncNonce: "nonce", + mergeTimestamp: 1 as any, + mergeReserveRowId: 1, + withdrawalGroupId: undefined, + status, + }; +} + +test("peer pull-credit actions match the withdrawal handlers", () => { + assert.ok( + !computePeerPullCreditTransactionActions( + makeRecord(PeerPullPaymentCreditStatus.PendingWithdrawing), + ).includes(TransactionAction.Abort), + ); + assert.deepStrictEqual( + computePeerPullCreditTransactionActions( + makeRecord(PeerPullPaymentCreditStatus.SuspendedWithdrawing), + ), + [TransactionAction.Resume], + ); + assert.ok( + computePeerPullCreditTransactionActions( + makeRecord(PeerPullPaymentCreditStatus.SuspendedMergeKycRequired), + ).includes(TransactionAction.Abort), + ); +}); + +test("aborting a suspended pre-withdrawal pull credit starts cleanup", async () => { + let record = makeRecord(PeerPullPaymentCreditStatus.SuspendedCreatePurse); + const tx = { + async getPeerPullCredit(): Promise<WalletPeerPullCredit> { + return record; + }, + async upsertPeerPullCredit(updated: WalletPeerPullCredit): Promise<void> { + record = updated; + }, + async deletePeerPullCredit(): Promise<void> {}, + async upsertTransactionMeta(): Promise<void> {}, + async deleteTransactionMeta(): Promise<void> {}, + notify(): void {}, + } as unknown as WalletDbTransaction; + let reset = false; + const wex = { + async runWalletDbTx<T>( + f: (transaction: WalletDbTransaction) => Promise<T>, + ): Promise<T> { + return await f(tx); + }, + taskScheduler: { + async resetTask(): Promise<void> { + reset = true; + }, + }, + } as unknown as WalletExecutionContext; + + const context = new PeerPullCreditTransactionContext(wex, record.pursePub); + await context.userAbortTransaction(); + + assert.strictEqual( + record.status, + PeerPullPaymentCreditStatus.AbortingDeletePurse, + ); + assert.strictEqual(reset, true); +}); diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts @@ -489,10 +489,13 @@ export class PeerPullCreditTransactionContext implements TransactionContext { rec.abortReason = reason; rec.status = PeerPullPaymentCreditStatus.AbortingDeletePurse; break; - case PeerPullPaymentCreditStatus.Done: case PeerPullPaymentCreditStatus.SuspendedCreatePurse: case PeerPullPaymentCreditStatus.SuspendedMergeKycRequired: case PeerPullPaymentCreditStatus.SuspendedReady: + rec.status = PeerPullPaymentCreditStatus.AbortingDeletePurse; + rec.abortReason = reason; + break; + case PeerPullPaymentCreditStatus.Done: case PeerPullPaymentCreditStatus.SuspendedWithdrawing: case PeerPullPaymentCreditStatus.Aborted: case PeerPullPaymentCreditStatus.AbortingDeletePurse: @@ -1430,19 +1433,15 @@ export function computePeerPullCreditTransactionActions( case PeerPullPaymentCreditStatus.Done: return [TransactionAction.Delete]; case PeerPullPaymentCreditStatus.PendingWithdrawing: - return [ - TransactionAction.Retry, - TransactionAction.Abort, - TransactionAction.Suspend, - ]; + return [TransactionAction.Retry, TransactionAction.Suspend]; case PeerPullPaymentCreditStatus.SuspendedCreatePurse: return [TransactionAction.Resume, TransactionAction.Abort]; case PeerPullPaymentCreditStatus.SuspendedReady: return [TransactionAction.Abort, TransactionAction.Resume]; case PeerPullPaymentCreditStatus.SuspendedWithdrawing: - return [TransactionAction.Resume, TransactionAction.Fail]; + return [TransactionAction.Resume]; case PeerPullPaymentCreditStatus.SuspendedMergeKycRequired: - return [TransactionAction.Resume, TransactionAction.Fail]; + return [TransactionAction.Resume, TransactionAction.Abort]; case PeerPullPaymentCreditStatus.Aborted: return [TransactionAction.Delete]; case PeerPullPaymentCreditStatus.AbortingDeletePurse: