taler-typescript-core

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

commit f0b8b496221d1a2536424886d1a1310fa2a35052
parent fb87b6b5ef97d0e461b232b1ae6c0ca968fdc216
Author: Florian Dold <florian@dold.me>
Date:   Tue,  2 Jun 2026 01:51:39 +0200

harness: test for overspending with prospective coin selection

Diffstat:
Apackages/taler-harness/src/integrationtests/test-balance-prospective.ts | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpackages/taler-harness/src/integrationtests/testrunner.ts | 2++
2 files changed, 128 insertions(+), 0 deletions(-)

diff --git a/packages/taler-harness/src/integrationtests/test-balance-prospective.ts b/packages/taler-harness/src/integrationtests/test-balance-prospective.ts @@ -0,0 +1,126 @@ +/* + This file is part of GNU Taler + (C) 2020 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/> + */ + +/** + * Imports. + */ +import { + TransactionMajorState, + TransactionMinorState, +} from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { defaultCoinConfig } from "../harness/denomStructures.js"; +import { + createSimpleTestkudosEnvironmentV3, + withdrawViaBankV4, +} from "../harness/environments.js"; +import { GlobalTestState } from "../harness/harness.js"; + +/** + * Test handling of the prospective coin selection in balances, + * i.e. coin selections where the funds we're using are + * still waiting to be refreshed. + */ +export async function runBalanceProspectiveTest(t: GlobalTestState) { + // Set up test environment + + const { + bankClient, + walletClient, + exchange, + merchant, + merchantAdminAccessToken, + bank, + } = await createSimpleTestkudosEnvironmentV3( + t, + defaultCoinConfig.map((x) => x("TESTKUDOS")), + { + walletConfig: { + testing: { + devModeActive: true, + }, + }, + }, + ); + + // Withdraw exactly one coin + await withdrawViaBankV4(t, { + walletClient, + exchange, + amount: "TESTKUDOS:10.01", + bank, + }); + + await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); + + const coins = await walletClient.call(WalletApiOperation.DumpCoins, {}); + t.assertDeepEqual(coins.coins.length, 1); + + await walletClient.call(WalletApiOperation.ApplyDevExperiment, { + devExperimentUri: "taler://dev-experiment/start-block-refresh", + }); + + const p1 = await walletClient.call(WalletApiOperation.InitiatePeerPushDebit, { + partialContractTerms: { + amount: "TESTKUDOS:4", + summary: "test", + }, + }); + + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: p1.transactionId, + txState: { + major: TransactionMajorState.Pending, + minor: TransactionMinorState.Ready, + }, + }); + + { + // This should succeed based on a prospective balance + const p2 = await walletClient.call( + WalletApiOperation.InitiatePeerPushDebit, + { + partialContractTerms: { + amount: "TESTKUDOS:4", + summary: "test", + }, + }, + ); + + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: p2.transactionId, + txState: { + major: TransactionMajorState.Pending, + minor: TransactionMinorState.CreatePurse, + }, + requireError: true, + }); + } + + { + // No more prospective balance, this should fail + await t.assertThrowsTalerErrorAsync(async () => { + await walletClient.call(WalletApiOperation.InitiatePeerPushDebit, { + partialContractTerms: { + amount: "TESTKUDOS:4", + summary: "test", + }, + }); + }); + } +} + +runBalanceProspectiveTest.suites = ["wallet"]; diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts @@ -38,6 +38,7 @@ import { runAgeRestrictionsDepositTest } from "./test-age-restrictions-deposit.j import { runAgeRestrictionsMerchantTest } from "./test-age-restrictions-merchant.js"; import { runAgeRestrictionsMixedMerchantTest } from "./test-age-restrictions-mixed-merchant.js"; import { runAgeRestrictionsPeerTest } from "./test-age-restrictions-peer.js"; +import { runBalanceProspectiveTest } from "./test-balance-prospective.js"; import { runBankApiTest } from "./test-bank-api.js"; import { runBankWopTest } from "./test-bank-wop.js"; import { runClaimLoopTest } from "./test-claim-loop.js"; @@ -442,6 +443,7 @@ const allTests: TestMainFunction[] = [ runWithdrawalShortenTest, runMerchantRefundFeesTest, runMerchantTokenfamiliesTest, + runBalanceProspectiveTest, ]; export interface TestRunSpec {