taler-typescript-core

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

commit c7adf74c9dd6b9b74588b37cbc6fbbcadc7c6a2e
parent 18a27cc4cf1b9582fe9ef5f46bcec0a7c2482e0f
Author: Florian Dold <florian@dold.me>
Date:   Wed, 22 Jul 2026 12:36:55 +0200

harness: new test for SIMPLE kyc auth

Diffstat:
Apackages/taler-harness/src/integrationtests/test-tops-merchant-simple-kycauth.ts | 180+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpackages/taler-harness/src/integrationtests/testrunner.ts | 2++
2 files changed, 182 insertions(+), 0 deletions(-)

diff --git a/packages/taler-harness/src/integrationtests/test-tops-merchant-simple-kycauth.ts b/packages/taler-harness/src/integrationtests/test-tops-merchant-simple-kycauth.ts @@ -0,0 +1,180 @@ +/* + This file is part of GNU Taler + (C) 2025 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 { + IbanString, + j2s, + Logger, + MerchantAccountKycStatus, + Paytos, + succeedOrThrow, + TalerMerchantInstanceHttpClient, + TalerProtocolDuration, +} from "@gnu-taler/taler-util"; +import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js"; +import { + ExchangeService, + GlobalTestState, + LibeufinNexusService, + MerchantService, + NexusBankAccountInfo, + setupDb, +} from "../harness/harness.js"; +import { topsKycRulesConf, topsProvidersTestConf } from "../harness/tops.js"; + +const logger = new Logger("test-tops-merchant-kycauths.ts"); + +/** + * Test short wire transfers in an exchange setup that simulates + * the Taler Operations CH exchange, using libeufin-nexus + * as the taler wire gateway API. + * + * This test exercises the .../kycauths endpoint of the merchant backend. + */ +export async function runTopsMerchantSimpleKycauthTest(t: GlobalTestState) { + const db = await setupDb(t); + + let coinConfig: CoinConfig[]; + coinConfig = defaultCoinConfig.map((x) => x("CHF")); + + const bankAccountInfo: NexusBankAccountInfo = { + // Random IBAN generated via "libeufin-nexus testing iban gen --country CH" + iban: "CH7347363QVFHHFR8BWWB", + // PostFinance BIC + bic: "POFICHBEXXX", + name: "Harness Test Exchange", + qrIban: "CH1130000001166556117", + }; + + const nexus = await LibeufinNexusService.create(t, { + currency: "CHF", + database: db.connStr, + httpPort: 8085, + bankAccountInfo, + }); + + const exchangePayto = Paytos.toFullString( + Paytos.createIban(bankAccountInfo.qrIban as IbanString, undefined, { + "receiver-name": bankAccountInfo.name, + }), + ); + + await nexus.dbinit(); + + await nexus.start(); + + const exchange = ExchangeService.create(t, { + name: "testexchange-1", + currency: "CHF", + httpPort: 8081, + database: db.connStr, + // FIXME: This is a terrible way to configure the exchange, should be moved into config. + extraProcEnv: { + EXCHANGE_AML_PROGRAM_TOPS_ENABLE_DEPOSITS_TOS_NAME: "v1", + EXCHANGE_AML_PROGRAM_TOPS_ENABLE_DEPOSITS_THRESHOLD: "CHF:0", + EXCHANGE_AML_PROGRAM_TOPS_POSTAL_CHECK_COUNTRY_REGEX: "ch|CH|Ch", + }, + }); + + exchange.addBankAccount("nexusacct", { + accountPaytoUri: exchangePayto, + wireGatewayApiBaseUrl: nexus.wireGatewayApiBaseUrl, + wireGatewayAuth: { + type: "basic", + username: "exchange-test", + password: "exchange-test", + }, + }); + + exchange.addCoinConfigList(coinConfig); + + await exchange.modifyConfig(async (config) => { + config.loadFromString(topsKycRulesConf); + config.loadFromString(topsProvidersTestConf); + }); + + await exchange.start(); + + const merchantIban = "CH4810303KL83V1QZ05T7"; + + const merchant = await MerchantService.create(t, { + name: "testmerchant-1", + httpPort: 8083, + database: db.connStr, + }); + + merchant.addExchange(exchange); + + await merchant.start(); + + const merchantPayto = Paytos.toFullString( + Paytos.createIban(merchantIban as IbanString, undefined, { + "receiver-name": "Merchant Test", + }), + ); + + const { accessToken: merchantAdminAccessToken } = + await merchant.addInstanceWithWireAccount({ + id: "admin", + name: "Default Instance", + paytoUris: [merchantPayto], + defaultWireTransferDelay: TalerProtocolDuration.fromSpec({ minutes: 1 }), + }); + + const merchantClient = new TalerMerchantInstanceHttpClient( + merchant.makeInstanceBaseUrl(), + ); + // Do KYC auth transfer + + const kycStatus = await merchantClient.getCurrentInstanceKycStatus( + merchantAdminAccessToken, + { + longpoll: { + type: "state-enter", + status: MerchantAccountKycStatus.KYC_WIRE_REQUIRED, + timeout: 10000, + }, + }, + ); + t.assertTrue(kycStatus.type === "ok"); + console.log(`kyc status: ${j2s(kycStatus)}`); + + t.assertDeepEqual(kycStatus.body.kyc_data[0].status, "kyc-wire-required"); + + const kycData = kycStatus.body.kyc_data[0]; + + const kycResp = succeedOrThrow( + await merchantClient.getInstancePrivateAccountKycauth( + merchantAdminAccessToken, + { + exchangeBaseUrl: kycData.exchange_url, + wireAccountHash: kycData.h_wire, + }, + ), + ); + + console.log(j2s(kycResp)); + + t.assertTrue( + kycResp.wire_instructions.length > 0, + "expected at least one wire instruction", + ); +} + +runTopsMerchantSimpleKycauthTest.suites = ["tops", "libeufin"]; diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts @@ -173,6 +173,7 @@ import { runTopsAmlLegiTest } from "./test-tops-aml-legi.js"; import { runTopsAmlMeasuresTest } from "./test-tops-aml-measures.js"; import { runTopsAmlPdfTest } from "./test-tops-aml-pdf.js"; import { runTopsChallengerTwiceTest } from "./test-tops-challenger-twice.js"; +import { runTopsMerchantSimpleKycauthTest } from "./test-tops-merchant-simple-kycauth.js"; import { runTopsMerchantSwtKycauthTest } from "./test-tops-merchant-swt-kycauth.js"; import { runTopsMerchantTosTest } from "./test-tops-merchant-tos.js"; import { runTopsNexusBasicTest } from "./test-tops-nexus-basic.js"; @@ -444,6 +445,7 @@ const allTests: TestMainFunction[] = [ runTopsNexusSwtTest, runTopsMerchantSwtKycauthTest, runMerchantSelfProvisionCasingTest, + runTopsMerchantSimpleKycauthTest, ]; export interface TestRunSpec {