commit 5108473b16b7fb660689c7d00f74a5493198a131
parent 2bdf20e63fdf67bf978ab46f528f1a7ff9dcc89b
Author: Florian Dold <florian@dold.me>
Date: Wed, 14 May 2025 19:46:16 +0200
wallet-core: fix transition when kyc-wallet returns 200, test scenario
Diffstat:
4 files changed, 129 insertions(+), 8 deletions(-)
diff --git a/packages/taler-harness/src/integrationtests/test-kyc-balance-withdrawal-change-manual.ts b/packages/taler-harness/src/integrationtests/test-kyc-balance-withdrawal-change-manual.ts
@@ -0,0 +1,106 @@
+/*
+ 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 {
+ Configuration,
+ TalerWireGatewayHttpClient,
+ TransactionIdStr,
+ TransactionMajorState,
+} from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import {
+ configureCommonKyc,
+ createKycTestkudosEnvironment,
+} from "../harness/environments.js";
+import { GlobalTestState } from "../harness/harness.js";
+
+function adjustExchangeConfig(config: Configuration): void {
+ configureCommonKyc(config);
+
+ config.setString("KYC-RULE-R1", "operation_type", "balance");
+ config.setString("KYC-RULE-R1", "enabled", "yes");
+ config.setString("KYC-RULE-R1", "exposed", "yes");
+ config.setString("KYC-RULE-R1", "is_and_combinator", "yes");
+ config.setString("KYC-RULE-R1", "threshold", "TESTKUDOS:10");
+ config.setString("KYC-RULE-R1", "timeframe", "forever");
+ config.setString("KYC-RULE-R1", "next_measures", "M1");
+
+ config.setString("KYC-MEASURE-M1", "check_name", "C1");
+ config.setString("KYC-MEASURE-M1", "context", "{}");
+ config.setString("KYC-MEASURE-M1", "program", "NONE");
+
+ config.setString("KYC-CHECK-C1", "type", "INFO");
+ config.setString("KYC-CHECK-C1", "description", "my check!");
+ config.setString("KYC-CHECK-C1", "fallback", "FREEZE");
+}
+
+export async function runKycBalanceWithdrawalChangeManualTest(
+ t: GlobalTestState,
+) {
+ // Set up test environment
+
+ const { walletClient, bankClient, exchange, exchangeBankAccount } =
+ await createKycTestkudosEnvironment(t, {
+ adjustExchangeConfig,
+ });
+
+ const mwResp = await walletClient.call(
+ WalletApiOperation.AcceptManualWithdrawal,
+ {
+ // Specify larger amount than what will be in the reserve.
+ amount: "TESTKUDOS:20",
+ exchangeBaseUrl: exchange.baseUrl,
+ },
+ );
+
+ await exchange.stop();
+
+ await exchange.modifyConfig(async (config) => {
+ config.setString("KYC-RULE-R1", "enabled", "NO");
+ });
+
+ await exchange.start();
+
+ const user = await bankClient.createRandomBankUser();
+
+ // Next, do a manual withdrawal.
+ const wireGatewayApiClient = new TalerWireGatewayHttpClient(
+ exchangeBankAccount.wireGatewayApiBaseUrl,
+ );
+
+ const reservePub = mwResp.reservePub;
+
+ await wireGatewayApiClient.addIncoming({
+ auth: exchangeBankAccount.wireGatewayAuth,
+ body: {
+ amount: "TESTKUDOS:20",
+ debit_account: user.accountPaytoUri,
+ reserve_pub: reservePub,
+ },
+ });
+
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: mwResp.transactionId as TransactionIdStr,
+ txState: {
+ major: TransactionMajorState.Done,
+ },
+ });
+}
+
+runKycBalanceWithdrawalChangeManualTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -59,6 +59,7 @@ import { runForcedSelectionTest } from "./test-forced-selection.js";
import { runKnownAccountsTest } from "./test-known-accounts.js";
import { runKycAmpFailureTest } from "./test-kyc-amp-failure.js";
import { runKycAmpTimeoutTest } from "./test-kyc-amp-timeout.js";
+import { runKycBalanceWithdrawalChangeManualTest } from "./test-kyc-balance-withdrawal-change-manual.js";
import { runKycBalanceWithdrawalTest } from "./test-kyc-balance-withdrawal.js";
import { runKycChallengerTest } from "./test-kyc-challenger.js";
import { runKycDecisionAttrTest } from "./test-kyc-decision-attr.js";
@@ -339,6 +340,7 @@ const allTests: TestMainFunction[] = [
runTopsAmlLegiTest,
runTopsChallengerTwiceTest,
runKycFormBadMeasureTest,
+ runKycBalanceWithdrawalChangeManualTest,
];
export interface TestRunSpec {
diff --git a/packages/taler-wallet-core/src/exchanges.ts b/packages/taler-wallet-core/src/exchanges.ts
@@ -3565,7 +3565,6 @@ async function handleExchangeKycPendingWallet(
switch (res.status) {
case HttpStatusCode.Ok: {
// KYC somehow already passed
- // FIXME: Store next threshold and timestamp!
const walletKycResp = await readSuccessResponseJsonOrThrow(
res,
codecForAmlWalletKycCheckResponse(),
@@ -3810,11 +3809,16 @@ async function handleExchangeKycPendingLegitimization(
resp,
codecForAccountKycStatus(),
);
- logger.trace(`balance KYC account status: ${j2s(accountKycStatus)}`);
+ logger.info(`balance KYC account status: ${j2s(accountKycStatus)}`);
const nextLimit = findNextBalanceLimit(
accountKycStatus,
reserve.thresholdGranted,
);
+ logger.info(
+ `setting next limit to: ${
+ nextLimit ? Amounts.stringify(nextLimit) : "undefined"
+ }`,
+ );
return handleExchangeKycSuccess(wex, exchange.baseUrl, nextLimit);
}
case HttpStatusCode.Accepted:
diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts
@@ -1067,17 +1067,26 @@ async function processWithdrawalGroupBalanceKyc(
});
if (ret.result === "ok") {
- await ctx.transition({}, async (wg) => {
+ const transitionInfo = await ctx.transition({}, async (wg) => {
if (!wg) {
return TransitionResult.stay();
}
- if (wg.status !== WithdrawalGroupStatus.PendingBalanceKyc) {
- return TransitionResult.stay();
+ switch (wg.status) {
+ case WithdrawalGroupStatus.PendingBalanceKyc:
+ case WithdrawalGroupStatus.PendingBalanceKycInit: {
+ wg.status = WithdrawalGroupStatus.PendingReady;
+ return TransitionResult.transition(wg);
+ }
+ default: {
+ return TransitionResult.stay();
+ }
}
- wg.status = WithdrawalGroupStatus.PendingReady;
- return TransitionResult.transition(wg);
});
- return TaskRunResult.progress();
+ if (transitionInfo) {
+ return TaskRunResult.progress();
+ } else {
+ return TaskRunResult.backoff();
+ }
} else if (
withdrawalGroup.status === WithdrawalGroupStatus.PendingBalanceKycInit &&
ret.walletKycStatus === ExchangeWalletKycStatus.Legi