taler-typescript-core

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

commit 6337ac7b784d6556ebeb2dad3021ce40732511b9
parent 2eec83e5dfe015d11a2bb6a939662a6e61e95b6f
Author: Florian Dold <dold@taler.net>
Date:   Wed, 29 Jul 2026 11:47:06 +0200

harness: check that a non-canonical suggested exchange fails the withdrawal

Issue: https://bugs.taler.net/n/10001

Diffstat:
Apackages/taler-harness/src/integrationtests/test-withdrawal-bad-suggested-exchange.ts | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpackages/taler-harness/src/integrationtests/testrunner.ts | 2++
2 files changed, 98 insertions(+), 0 deletions(-)

diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-bad-suggested-exchange.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-bad-suggested-exchange.ts @@ -0,0 +1,96 @@ +/* + 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/> + */ + +/** + * Imports. + */ +import { TalerErrorCode, j2s } from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { createSimpleTestkudosEnvironmentV3 } from "../harness/environments.js"; +import { GlobalTestState } from "../harness/harness.js"; + +/** + * The exchange of the simple test environment always listens here. + */ +const exchangeBaseUrl = "http://localhost:8081/"; + +/** + * The same exchange, but not a canonical base URL. A base URL is only ever + * used by resolving a relative path against it, and resolving "keys" against + * this one yields "http://localhost:8081/keys" -- so a wallet that accepts it + * ends up talking to a base URL the bank never named. + */ +const nonCanonicalExchangeBaseUrl = "http://localhost:8081/taler-exchange"; + +/** + * Check that a bank-integrated withdrawal fails when the bank suggests an + * exchange base URL that isn't canonical. + */ +export async function runWithdrawalBadSuggestedExchangeTest( + t: GlobalTestState, +) { + const { walletClient, bankClient, exchange } = + await createSimpleTestkudosEnvironmentV3(t, undefined, { + additionalBankConfig: (bank) => { + bank.changeConfig((config) => { + // Both bank implementations get misconfigured, each under the + // option name it reads. + config.setString( + "bank", + "suggested_exchange", + nonCanonicalExchangeBaseUrl, + ); + config.setString( + "libeufin-bank", + "suggested_withdrawal_exchange", + nonCanonicalExchangeBaseUrl, + ); + }); + }, + }); + + // Keep the constants above honest: the suggestion has to differ from the + // real base URL in nothing but its canonical form. + t.assertDeepEqual(exchange.baseUrl, exchangeBaseUrl); + + const user = await bankClient.createRandomBankUser(); + bankClient.setAuth(user); + + const withdrawal = await bankClient.createWithdrawalOperation( + user.username, + "TESTKUDOS:10", + ); + + t.logStep("Hand the withdrawal to the wallet"); + + const err = await t.assertThrowsTalerErrorAsync(async () => { + const res = await walletClient.call( + WalletApiOperation.GetWithdrawalDetailsForUri, + { + talerWithdrawUri: withdrawal.taler_withdraw_uri, + }, + ); + console.log(`unexpectedly got withdrawal details: ${j2s(res)}`); + }); + + console.log(`got error: ${j2s(err.errorDetail)}`); + t.assertDeepEqual( + err.errorDetail.code, + TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE, + ); +} + +runWithdrawalBadSuggestedExchangeTest.suites = ["wallet"]; diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts @@ -235,6 +235,7 @@ import { runWebMerchantLoginTest } from "./test-web-merchant-login.js"; import { runWireMetadataTest } from "./test-wire-metadata.js"; import { runWithdrawalAbortBankTest } from "./test-withdrawal-abort-bank.js"; import { runWithdrawalAmountTest } from "./test-withdrawal-amount.js"; +import { runWithdrawalBadSuggestedExchangeTest } from "./test-withdrawal-bad-suggested-exchange.js"; import { runWithdrawalBankIntegratedTest } from "./test-withdrawal-bank-integrated.js"; import { runWithdrawalCashacceptorTest } from "./test-withdrawal-cashacceptor.js"; import { runWithdrawalConflictTest } from "./test-withdrawal-conflict.js"; @@ -335,6 +336,7 @@ const allTests: TestMainFunction[] = [ runWalletDblessTest, runWallettestingTest, runWithdrawalAbortBankTest, + runWithdrawalBadSuggestedExchangeTest, runWithdrawalBankIntegratedTest, runWithdrawalFakebankTest, runWithdrawalFeesTest,