taler-typescript-core

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

commit 7f966ae5de07fabd09f9cfcf9e0d6309a378063e
parent 27d6013f31a15ccf7b582ea5b90f459757740883
Author: Florian Dold <dold@taler.net>
Date:   Wed, 29 Jul 2026 13:48:11 +0200

wallet-core: add a dev experiment that blocks order claims

Lets a test observe how the wallet retries a claim without taking the order
away from the nonce it claims with.

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

Diffstat:
Mpackages/taler-wallet-core/src/dev-experiments.ts | 29++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/packages/taler-wallet-core/src/dev-experiments.ts b/packages/taler-wallet-core/src/dev-experiments.ts @@ -49,6 +49,7 @@ import { j2s, } from "@gnu-taler/taler-util"; import { + HeadersImpl, HttpRequestLibrary, HttpRequestOptions, HttpResponse, @@ -125,6 +126,8 @@ export interface DevExperimentState { blockPayResponse?: boolean; + blockClaimResponse?: boolean; + /** Migration test for confirmPay */ flagConfirmPayNoWait?: boolean; @@ -513,6 +516,12 @@ export async function applyDevExperiment( wex.ws.devExperimentState.blockPayResponse = val; return; } + case "block-claim-response": { + const val = getValFlag(parsedUri); + logger.info(`setting dev experiment blockClaimResponse=${val}`); + wex.ws.devExperimentState.blockClaimResponse = val; + return; + } case "pretend-no-denoms": { wex.ws.devExperimentState.pretendNoDenoms = true; return; @@ -857,7 +866,13 @@ function mockResponseReplacementJson( }; } -function mockInternalServerError(resp: HttpResponse): HttpResponse { +/** + * Fake a 500 for a request. Takes only the request-identifying part of a + * response, so that a request that is never sent on can be faked as well. + */ +function mockInternalServerError( + resp: Pick<HttpResponse, "requestMethod" | "requestUrl" | "headers">, +): HttpResponse { const textEncoder = new TextEncoder(); const respJson = { code: TalerErrorCode.GENERIC_INTERNAL_INVARIANT_FAILURE, @@ -942,6 +957,18 @@ export class DevExperimentHttpLib implements HttpRequestLibrary { const realResp = await this.underlyingLib.fetch(url, opt); return mockInternalServerError(realResp); } + } else if (this.devExperimentState.blockClaimResponse) { + if (method === "post" && url.endsWith("/claim")) { + logger.warn(`blocking /claim response`); + // The claim is not sent on at all: the merchant would hand the order + // to our nonce, and every further attempt would then be a repeated + // claim instead of a first one. + return mockInternalServerError({ + requestMethod: "POST", + requestUrl: url, + headers: new HeadersImpl(), + }); + } } if ( evalFailProbability(this.devExperimentState.tc?.dropRequestProbability)