commit 5b580579837ff6a9af91968b08e38d23f98e8de8
parent 5d4702c6d106705060f1bccbedd35bf3f7aacbc4
Author: Florian Dold <florian@dold.me>
Date: Mon, 23 Feb 2026 20:46:41 +0100
extend merchant-kyc-auth-multi test
Diffstat:
1 file changed, 145 insertions(+), 104 deletions(-)
diff --git a/packages/taler-harness/src/integrationtests/test-merchant-kyc-auth-multi.ts b/packages/taler-harness/src/integrationtests/test-merchant-kyc-auth-multi.ts
@@ -18,6 +18,7 @@
* Imports.
*/
import {
+ AccessToken,
Configuration,
encodeCrock,
getRandomBytes,
@@ -28,14 +29,18 @@ import {
succeedOrThrow,
TalerMerchantInstanceHttpClient,
TalerProtocolDuration,
+ TalerWireGatewayHttpClient,
} from "@gnu-taler/taler-util";
import {
configureCommonKyc,
createKycTestkudosEnvironment,
} from "../harness/environments.js";
import {
+ BankService,
+ ExchangeService,
getTestHarnessPaytoForLabel,
GlobalTestState,
+ MerchantService,
} from "../harness/harness.js";
const myAmlConfig = `
@@ -88,6 +93,81 @@ function adjustExchangeConfig(config: Configuration) {
const logger = new Logger("test-merchant-kyc-auth-multi.ts");
+async function doAccountKycAuth(
+ t: GlobalTestState,
+ args: {
+ exchange: ExchangeService;
+ merchant: MerchantService;
+ bank: BankService;
+ merchantInstId: string;
+ merchantInstPaytoUri: string;
+ merchantAccessToken: AccessToken;
+ wireGatewayApi: TalerWireGatewayHttpClient;
+ },
+): Promise<void> {
+ const {
+ merchant,
+ exchange,
+ merchantInstId,
+ merchantAccessToken,
+ merchantInstPaytoUri,
+ bank,
+ wireGatewayApi,
+ } = args;
+ const merchantClient = new TalerMerchantInstanceHttpClient(
+ merchant.makeInstanceBaseUrl(merchantInstId),
+ );
+ {
+ const kycRes1 = succeedOrThrow(
+ await merchantClient.getCurrentInstanceKycStatus(merchantAccessToken, {}),
+ );
+ console.log(`kyc res: ${j2s(kycRes1)}`);
+ t.assertDeepEqual(kycRes1.kycRequired, true);
+ const myRow = kycRes1.kyc_data.find(
+ (x) => x.exchange_url === exchange.baseUrl,
+ );
+ t.assertTrue(
+ myRow?.payto_kycauths != null && myRow.payto_kycauths.length == 1,
+ );
+ const authTxPayto = parsePaytoUriOrThrow(myRow.payto_kycauths[0]);
+ const authTxMessage = authTxPayto?.params["message"];
+ t.assertTrue(typeof authTxMessage === "string");
+ t.assertTrue(authTxMessage.startsWith("KYC:"));
+ const accountPub = authTxMessage.substring(4);
+ logger.info(`merchant account pub: ${accountPub}`);
+ await wireGatewayApi.addKycAuth({
+ auth: bank.getAdminAuth(),
+ body: {
+ amount: "TESTKUDOS:0.1",
+ debit_account: merchantInstPaytoUri,
+ account_pub: accountPub,
+ },
+ });
+ }
+
+ // Wait for auth transfer to be registered by the exchange
+ {
+ const kycStatus = await merchantClient.getCurrentInstanceKycStatus(
+ merchantAccessToken,
+ {
+ reason: KycStatusLongPollingReason.AUTH_TRANSFER,
+ timeout: 30000,
+ },
+ );
+ logger.info(`kyc status after transfer: ${j2s(kycStatus)}`);
+ t.assertDeepEqual(kycStatus.case, "ok");
+ t.assertTrue(kycStatus.body.kycRequired === true);
+ const myRow = kycStatus.body.kyc_data.find(
+ (x) =>
+ x.exchange_url === exchange.baseUrl &&
+ x.payto_uri === merchantInstPaytoUri,
+ );
+ t.assertTrue(myRow != null);
+ t.assertDeepEqual(myRow.status, "ready");
+ t.assertTrue(typeof myRow.access_token === "string");
+ }
+}
+
/**
* Test for multiple merchant instances using the same
* bank account (with multiple public keys and thus KYC auth transfers).
@@ -106,19 +186,17 @@ export async function runMerchantKycAuthMultiTest(t: GlobalTestState) {
wireGatewayApi,
} = await createKycTestkudosEnvironment(t, { adjustExchangeConfig });
- const merchantPayto = getTestHarnessPaytoForLabel("merchant-default");
-
- await bankClient.registerAccountExtended({
- name: "merchant-default",
- password: encodeCrock(getRandomBytes(32)),
- username: "merchant-default",
- payto_uri: merchantPayto,
- });
-
{
const merchantInstId = "minst1";
const merchantInstPaytoUri = getTestHarnessPaytoForLabel(merchantInstId);
+ await bankClient.registerAccountExtended({
+ name: merchantInstId,
+ password: encodeCrock(getRandomBytes(32)),
+ username: merchantInstId,
+ payto_uri: merchantInstPaytoUri,
+ });
+
const m1Res = await merchant.addInstanceWithWireAccount(
{
id: merchantInstId,
@@ -131,51 +209,53 @@ export async function runMerchantKycAuthMultiTest(t: GlobalTestState) {
{ adminAccessToken: merchantAdminAccessToken },
);
- await bankClient.registerAccountExtended({
- name: merchantInstId,
- password: encodeCrock(getRandomBytes(32)),
- username: merchantInstId,
- payto_uri: merchantInstPaytoUri,
- });
+ const merchantAccessToken = m1Res.accessToken;
await merchant.runExchangekeyupdateOnce();
await merchant.runKyccheckOnce();
+ await doAccountKycAuth(t, {
+ exchange,
+ merchant,
+ bank,
+ merchantInstId,
+ merchantAccessToken,
+ merchantInstPaytoUri,
+ wireGatewayApi,
+ });
+
const merchantClient = new TalerMerchantInstanceHttpClient(
- merchant.makeInstanceBaseUrl("minst1"),
+ merchant.makeInstanceBaseUrl(merchantInstId),
);
- {
- const kycRes1 = succeedOrThrow(
- await merchantClient.getCurrentInstanceKycStatus(m1Res.accessToken, {}),
- );
- console.log(`kyc res: ${j2s(kycRes1)}`);
- t.assertDeepEqual(kycRes1.kycRequired, true);
- const myRow = kycRes1.kyc_data.find(
- (x) => x.exchange_url === exchange.baseUrl,
- );
- t.assertTrue(
- myRow?.payto_kycauths != null && myRow.payto_kycauths.length == 1,
- );
- const authTxPayto = parsePaytoUriOrThrow(myRow.payto_kycauths[0]);
- const authTxMessage = authTxPayto?.params["message"];
- t.assertTrue(typeof authTxMessage === "string");
- t.assertTrue(authTxMessage.startsWith("KYC:"));
- const accountPub = authTxMessage.substring(4);
- logger.info(`merchant account pub: ${accountPub}`);
- await wireGatewayApi.addKycAuth({
- auth: bank.getAdminAuth(),
- body: {
- amount: "TESTKUDOS:0.1",
- debit_account: merchantInstPaytoUri,
- account_pub: accountPub,
- },
- });
- }
- // Wait for auth transfer to be registered by the exchange
+ const accounts1 = succeedOrThrow(
+ await merchantClient.listBankAccounts(m1Res.accessToken),
+ );
+ t.assertDeepEqual(accounts1.accounts.length, 1);
+ await merchantClient.deleteBankAccount(
+ merchantAccessToken,
+ accounts1.accounts[0].h_wire,
+ );
+ const accounts2 = succeedOrThrow(
+ await merchantClient.listBankAccounts(m1Res.accessToken),
+ );
+ console.log(`accounts after deletion: ${j2s(accounts2)}`);
+
+ // Now re-add same account
+ await merchantClient.addBankAccount(m1Res.accessToken, {
+ payto_uri: merchantInstPaytoUri,
+ });
+
+ const accounts3 = succeedOrThrow(
+ await merchantClient.listBankAccounts(m1Res.accessToken),
+ );
+ console.log(`accounts after re-adding: ${j2s(accounts3)}`);
+
+ // Now we should now have to do KYC auth again, same instance,
+ // account was just re-added.
{
const kycStatus = await merchantClient.getCurrentInstanceKycStatus(
- m1Res.accessToken,
+ merchantAccessToken,
{
reason: KycStatusLongPollingReason.AUTH_TRANSFER,
timeout: 30000,
@@ -185,7 +265,9 @@ export async function runMerchantKycAuthMultiTest(t: GlobalTestState) {
t.assertDeepEqual(kycStatus.case, "ok");
t.assertTrue(kycStatus.body.kycRequired === true);
const myRow = kycStatus.body.kyc_data.find(
- (x) => x.exchange_url === exchange.baseUrl,
+ (x) =>
+ x.exchange_url === exchange.baseUrl &&
+ x.payto_uri === merchantInstPaytoUri,
);
t.assertTrue(myRow != null);
t.assertDeepEqual(myRow.status, "ready");
@@ -199,7 +281,14 @@ export async function runMerchantKycAuthMultiTest(t: GlobalTestState) {
const merchantInstId = "minst2";
const merchantInstPaytoUri = getTestHarnessPaytoForLabel(merchantInstId);
- const m1Res = await merchant.addInstanceWithWireAccount(
+ await bankClient.registerAccountExtended({
+ name: merchantInstId,
+ password: encodeCrock(getRandomBytes(32)),
+ username: merchantInstId,
+ payto_uri: merchantInstPaytoUri,
+ });
+
+ const m2Res = await merchant.addInstanceWithWireAccount(
{
id: merchantInstId,
name: merchantInstId,
@@ -211,66 +300,18 @@ export async function runMerchantKycAuthMultiTest(t: GlobalTestState) {
{ adminAccessToken: merchantAdminAccessToken },
);
- await bankClient.registerAccountExtended({
- name: merchantInstId,
- password: encodeCrock(getRandomBytes(32)),
- username: merchantInstId,
- payto_uri: merchantInstPaytoUri,
- });
-
await merchant.runExchangekeyupdateOnce();
await merchant.runKyccheckOnce();
- const merchantClient = new TalerMerchantInstanceHttpClient(
- merchant.makeInstanceBaseUrl("minst1"),
- );
- {
- const kycRes1 = succeedOrThrow(
- await merchantClient.getCurrentInstanceKycStatus(m1Res.accessToken, {}),
- );
- console.log(`kyc res: ${j2s(kycRes1)}`);
- t.assertDeepEqual(kycRes1.kycRequired, true);
- const myRow = kycRes1.kyc_data.find(
- (x) => x.exchange_url === exchange.baseUrl,
- );
- t.assertTrue(
- myRow?.payto_kycauths != null && myRow.payto_kycauths.length == 1,
- );
- const authTxPayto = parsePaytoUriOrThrow(myRow.payto_kycauths[0]);
- const authTxMessage = authTxPayto?.params["message"];
- t.assertTrue(typeof authTxMessage === "string");
- t.assertTrue(authTxMessage.startsWith("KYC:"));
- const accountPub = authTxMessage.substring(4);
- logger.info(`merchant account pub: ${accountPub}`);
- await wireGatewayApi.addKycAuth({
- auth: bank.getAdminAuth(),
- body: {
- amount: "TESTKUDOS:0.1",
- debit_account: merchantInstPaytoUri,
- account_pub: accountPub,
- },
- });
- }
-
- // Wait for auth transfer to be registered by the exchange
- {
- const kycStatus = await merchantClient.getCurrentInstanceKycStatus(
- m1Res.accessToken,
- {
- reason: KycStatusLongPollingReason.AUTH_TRANSFER,
- timeout: 30000,
- },
- );
- logger.info(`kyc status after transfer: ${j2s(kycStatus)}`);
- t.assertDeepEqual(kycStatus.case, "ok");
- t.assertTrue(kycStatus.body.kycRequired === true);
- const myRow = kycStatus.body.kyc_data.find(
- (x) => x.exchange_url === exchange.baseUrl,
- );
- t.assertTrue(myRow != null);
- t.assertDeepEqual(myRow.status, "ready");
- t.assertTrue(typeof myRow.access_token === "string");
- }
+ await doAccountKycAuth(t, {
+ exchange,
+ merchant,
+ bank,
+ merchantInstId,
+ merchantAccessToken: m2Res.accessToken,
+ merchantInstPaytoUri,
+ wireGatewayApi,
+ });
}
t.logStep("second-account-ready");