commit ab5f1771a65b39a61a8e8c4e8ed08f574507f059
parent 562d239a6eab98e4dd5bc18e34a97ef5655f60a3
Author: Florian Dold <florian@dold.me>
Date: Tue, 6 May 2025 19:36:45 +0200
harness: refactor test
Diffstat:
3 files changed, 243 insertions(+), 211 deletions(-)
diff --git a/packages/taler-harness/src/harness/tops.ts b/packages/taler-harness/src/harness/tops.ts
@@ -15,6 +15,16 @@
*/
import {
+ AccessToken,
+ decodeCrock,
+ encodeCrock,
+ hashNormalizedPaytoUri,
+ j2s,
+ KycStatusLongPollingReason,
+ OfficerAccount,
+ OfficerId,
+ parsePaytoUriOrThrow,
+ succeedOrThrow,
TalerCorebankApiClient,
TalerCoreBankHttpClient,
TalerExchangeHttpClient,
@@ -24,12 +34,15 @@ import {
} from "@gnu-taler/taler-util";
import {
createSyncCryptoApi,
+ EddsaKeyPairStrings,
WalletApiOperation,
} from "@gnu-taler/taler-wallet-core";
+import { logger } from "../integrationtests/test-tops-aml-kyx-natural.js";
import { CoinConfig, defaultCoinConfig } from "./denomStructures.js";
-import { KycTestEnv } from "./environments.js";
+import { TestfakeChallengerService } from "./fake-challenger.js";
import {
BankService,
+ DbInfo,
ExchangeService,
getTestHarnessPaytoForLabel,
GlobalTestState,
@@ -562,9 +575,25 @@ KYC_KYCAID_FORM_ID = form_individual
KYC_KYCAID_POST_URL = http://localhost:6005/done
`;
+export interface TopsTestEnv {
+ commonDb: DbInfo;
+ bankClient: TalerCorebankApiClient;
+ exchange: ExchangeService;
+ exchangeBankAccount: HarnessExchangeBankAccount;
+ walletClient: WalletClient;
+ walletService: WalletService;
+ amlKeypair: EddsaKeyPairStrings;
+ merchant: MerchantService;
+ bankApi: TalerCoreBankHttpClient;
+ exchangeApi: TalerExchangeHttpClient;
+ wireGatewayApi: TalerWireGatewayHttpClient;
+ merchantApi: TalerMerchantInstanceHttpClient;
+ officerAcc: OfficerAccount;
+}
+
export async function createTopsEnvironment(
t: GlobalTestState,
-): Promise<KycTestEnv> {
+): Promise<TopsTestEnv> {
const db = await setupDb(t);
let coinConfig: CoinConfig[];
@@ -722,10 +751,16 @@ export async function createTopsEnvironment(
httpClient: harnessHttpLib,
});
+ const officerAcc: OfficerAccount = {
+ id: amlKeypair.pub as OfficerId,
+ signingKey: decodeCrock(amlKeypair.priv),
+ };
+
return {
commonDb: db,
exchange,
amlKeypair,
+ officerAcc,
walletClient,
walletService,
bankClient,
@@ -737,3 +772,173 @@ export async function createTopsEnvironment(
exchangeApi,
};
}
+
+export async function doFakeChallenger(
+ t: GlobalTestState,
+ args: {
+ exchangeClient: TalerExchangeHttpClient;
+ requirementId: string;
+ challenger: TestfakeChallengerService;
+ address: any;
+ },
+): Promise<{ setupRequest: any }> {
+ const { exchangeClient, challenger, requirementId } = args;
+ const startResp = succeedOrThrow(
+ await exchangeClient.startExternalKycProcess(requirementId, {}),
+ );
+ console.log(`start resp`, j2s(startResp));
+
+ let challengerRedirectUrl = startResp.redirect_url;
+
+ const resp = await harnessHttpLib.fetch(challengerRedirectUrl);
+ const respJson = await resp.json();
+ console.log(`challenger resp: ${j2s(respJson)}`);
+
+ const nonce = respJson.nonce;
+ t.assertTrue(typeof nonce === "string");
+ const proofRedirectUrl = respJson.redirect_url;
+
+ challenger.fakeVerification(nonce, args.address);
+
+ console.log("nonce", nonce);
+ console.log("proof redirect URL", proofRedirectUrl);
+
+ const proofResp = await harnessHttpLib.fetch(proofRedirectUrl, {
+ redirect: "manual",
+ });
+ console.log("proof status:", proofResp.status);
+ t.assertDeepEqual(proofResp.status, 303);
+
+ const setupRequest = challenger.getSetupRequest(nonce);
+ console.log(`setup request: ${j2s(setupRequest)}`);
+ return {
+ setupRequest,
+ };
+}
+
+export async function doTopsKycAuth(
+ t: GlobalTestState,
+ args: {
+ merchantClient: TalerMerchantInstanceHttpClient;
+ exchangeBankAccount: HarnessExchangeBankAccount;
+ wireGatewayApi: TalerWireGatewayHttpClient;
+ },
+): Promise<{ accessToken: AccessToken; merchantPaytoHash: string }> {
+ const { merchantClient, wireGatewayApi, exchangeBankAccount } = args;
+ {
+ const kycStatus = await merchantClient.getCurrentInstanceKycStatus(
+ undefined,
+ {},
+ );
+
+ console.log(`kyc status: ${j2s(kycStatus)}`);
+
+ t.assertDeepEqual(kycStatus.case, "ok");
+
+ t.assertTrue(kycStatus.body != null);
+
+ t.assertDeepEqual(kycStatus.body.kyc_data[0].status, "kyc-wire-required");
+
+ const depositPaytoUri = kycStatus.body.kyc_data[0].payto_uri;
+ t.assertTrue(kycStatus.body.kyc_data[0].payto_kycauths != null);
+ const authTxPayto = parsePaytoUriOrThrow(
+ kycStatus.body.kyc_data[0]?.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: exchangeBankAccount.wireGatewayAuth,
+ body: {
+ amount: "CHF:0.1",
+ debit_account: depositPaytoUri,
+ account_pub: accountPub,
+ },
+ });
+ }
+
+ let accessToken: AccessToken;
+ let merchantPaytoHash: string;
+
+ // Wait for auth transfer to be registered by the exchange
+ {
+ const kycStatus = await merchantClient.getCurrentInstanceKycStatus(
+ undefined,
+ {
+ reason: KycStatusLongPollingReason.AUTH_TRANSFER,
+ timeout: 30000,
+ },
+ );
+ logger.info(`kyc status after transfer: ${j2s(kycStatus)}`);
+ t.assertDeepEqual(kycStatus.case, "ok");
+ t.assertTrue(kycStatus.body != null);
+ t.assertDeepEqual(kycStatus.body.kyc_data[0].status, "kyc-required");
+ t.assertTrue(typeof kycStatus.body.kyc_data[0].access_token === "string");
+ accessToken = kycStatus.body.kyc_data[0].access_token as AccessToken;
+ merchantPaytoHash = encodeCrock(
+ hashNormalizedPaytoUri(kycStatus.body.kyc_data[0].payto_uri),
+ );
+ return { accessToken, merchantPaytoHash };
+ }
+}
+
+export async function doTopsAcceptTos(
+ t: GlobalTestState,
+ args: {
+ accessToken: AccessToken;
+ exchangeClient: TalerExchangeHttpClient;
+ merchantClient: TalerMerchantInstanceHttpClient;
+ merchant: MerchantService;
+ },
+): Promise<void> {
+ const { exchangeClient, merchant, merchantClient, accessToken } = args;
+ {
+ const kycInfo = await exchangeClient.checkKycInfo(
+ accessToken,
+ undefined,
+ undefined,
+ );
+ console.log(j2s(kycInfo));
+
+ t.assertDeepEqual(kycInfo.case, "ok");
+ t.assertDeepEqual(kycInfo.body.requirements.length, 1);
+ t.assertDeepEqual(kycInfo.body.requirements[0].form, "accept-tos");
+ const requirementId = kycInfo.body.requirements[0].id;
+ t.assertTrue(typeof requirementId === "string");
+
+ const uploadRes = await exchangeClient.uploadKycForm(requirementId, {
+ FORM_ID: "accept-tos",
+ FORM_VERSION: 1,
+ ACCEPTED_TERMS_OF_SERVICE: "v1",
+ });
+ console.log("upload res", uploadRes);
+ t.assertDeepEqual(uploadRes.case, "ok");
+ }
+
+ {
+ const kycInfo = await exchangeClient.checkKycInfo(
+ accessToken,
+ undefined,
+ undefined,
+ );
+ console.log(j2s(kycInfo));
+
+ // FIXME: Do we expect volunary measures here?
+ // => not yet, see https://bugs.gnunet.org/view.php?id=9879
+ }
+
+ await merchant.runKyccheckOnce();
+
+ {
+ const kycStatus = await merchantClient.getCurrentInstanceKycStatus(
+ undefined,
+ {
+ reason: KycStatusLongPollingReason.AUTH_TRANSFER,
+ timeout: 30000,
+ },
+ );
+ logger.info(`kyc status after accept-tos: ${j2s(kycStatus)}`);
+ }
+}
diff --git a/packages/taler-harness/src/integrationtests/test-tops-aml-custom-addr-postal.ts b/packages/taler-harness/src/integrationtests/test-tops-aml-custom-addr-postal.ts
@@ -35,7 +35,7 @@ import {
} from "@gnu-taler/taler-util";
import { startFakeChallenger } from "../harness/fake-challenger.js";
import { GlobalTestState, harnessHttpLib } from "../harness/harness.js";
-import { createTopsEnvironment } from "../harness/tops.js";
+import { createTopsEnvironment, doFakeChallenger } from "../harness/tops.js";
const logger = new Logger("test-tops-aml.ts");
@@ -48,6 +48,7 @@ export async function runTopsAmlCustomAddrPostalTest(t: GlobalTestState) {
const {
exchange,
amlKeypair,
+ officerAcc,
merchant,
exchangeBankAccount,
wireGatewayApi,
@@ -172,11 +173,6 @@ export async function runTopsAmlCustomAddrPostalTest(t: GlobalTestState) {
logger.info(`kyc status after accept-tos: ${j2s(kycStatus)}`);
}
- const officerAcc: OfficerAccount = {
- id: amlKeypair.pub as OfficerId,
- signingKey: decodeCrock(amlKeypair.priv),
- };
-
// Trigger postal registration check
// via AML officer.
{
@@ -232,41 +228,20 @@ export async function runTopsAmlCustomAddrPostalTest(t: GlobalTestState) {
t.assertDeepEqual(kycInfoResp.case, "ok");
const kycInfo = kycInfoResp.body;
t.assertDeepEqual(kycInfo.requirements[0].form, "LINK");
- t.assertTrue(typeof kycInfo.requirements[0].id === "string");
-
- const startResp = succeedOrThrow(
- await exchangeClient.startExternalKycProcess(
- kycInfo.requirements[0].id,
- {},
- ),
- );
- console.log(`start resp`, j2s(startResp));
-
- let challengerRedirectUrl = startResp.redirect_url;
-
- const resp = await harnessHttpLib.fetch(challengerRedirectUrl);
- const respJson = await resp.json();
- console.log(`challenger resp: ${j2s(respJson)}`);
-
- const nonce = respJson.nonce;
- t.assertTrue(typeof nonce === "string");
- const proofRedirectUrl = respJson.redirect_url;
-
- challenger.fakeVerification(nonce, {
- CONTACT_NAME: "Richard Stallman",
- ADDRESS_LINES: "Bundesgasse 1\n1234 Bern",
- });
-
- console.log("nonce", nonce);
- console.log("proof redirect URL", proofRedirectUrl);
+ const requirementId = kycInfo.requirements[0].id;
+ t.assertTrue(typeof requirementId === "string");
- const proofResp = await harnessHttpLib.fetch(proofRedirectUrl, {
- redirect: "manual",
+ const chRes = await doFakeChallenger(t, {
+ exchangeClient,
+ requirementId,
+ challenger,
+ address: {
+ CONTACT_NAME: "Richard Stallman",
+ ADDRESS_LINES: "Bundesgasse 1\n1234 Bern",
+ },
});
- console.log("proof status:", proofResp.status);
- t.assertDeepEqual(proofResp.status, 303);
- const setupReq = challenger.getSetupRequest(nonce);
+ const setupReq = chRes.setupRequest;
console.log(`setup request: ${j2s(setupReq)}`);
t.assertDeepEqual(setupReq.CONTACT_NAME, "Richard Stallman");
diff --git a/packages/taler-harness/src/integrationtests/test-tops-aml-kyx-natural.ts b/packages/taler-harness/src/integrationtests/test-tops-aml-kyx-natural.ts
@@ -18,38 +18,29 @@
* Imports.
*/
import {
- AccessToken,
- decodeCrock,
- encodeCrock,
- hashNormalizedPaytoUri,
j2s,
- KycStatusLongPollingReason,
Logger,
- OfficerAccount,
- OfficerId,
- parsePaytoUriOrThrow,
succeedOrThrow,
TalerExchangeHttpClient,
TalerMerchantInstanceHttpClient,
TalerProtocolTimestamp,
} from "@gnu-taler/taler-util";
-import {
- startFakeChallenger,
- TestfakeChallengerService,
-} from "../harness/fake-challenger.js";
+import { startFakeChallenger } from "../harness/fake-challenger.js";
import { GlobalTestState, harnessHttpLib } from "../harness/harness.js";
-import { createTopsEnvironment } from "../harness/tops.js";
+import {
+ createTopsEnvironment,
+ doFakeChallenger,
+ doTopsAcceptTos,
+ doTopsKycAuth,
+} from "../harness/tops.js";
-const logger = new Logger("test-tops-aml.ts");
+export const logger = new Logger("test-tops-aml.ts");
export async function runTopsAmlKyxNaturalTest(t: GlobalTestState) {
// Set up test environment
-
const {
- walletClient,
- bankClient,
exchange,
- amlKeypair,
+ officerAcc,
merchant,
exchangeBankAccount,
wireGatewayApi,
@@ -63,124 +54,27 @@ export async function runTopsAmlKyxNaturalTest(t: GlobalTestState) {
const merchantClient = new TalerMerchantInstanceHttpClient(
merchant.makeInstanceBaseUrl(),
);
- // Do KYC auth transfer
- {
- const kycStatus = await merchantClient.getCurrentInstanceKycStatus(
- undefined,
- {},
- );
-
- console.log(`kyc status: ${j2s(kycStatus)}`);
-
- t.assertDeepEqual(kycStatus.case, "ok");
-
- t.assertTrue(kycStatus.body != null);
-
- t.assertDeepEqual(kycStatus.body.kyc_data[0].status, "kyc-wire-required");
-
- const depositPaytoUri = kycStatus.body.kyc_data[0].payto_uri;
- t.assertTrue(kycStatus.body.kyc_data[0].payto_kycauths != null);
- const authTxPayto = parsePaytoUriOrThrow(
- kycStatus.body.kyc_data[0]?.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: exchangeBankAccount.wireGatewayAuth,
- body: {
- amount: "CHF:0.1",
- debit_account: depositPaytoUri,
- account_pub: accountPub,
- },
- });
- }
-
- let accessToken: AccessToken;
- let merchantPaytoHash: string;
- // Wait for auth transfer to be registered by the exchange
- {
- const kycStatus = await merchantClient.getCurrentInstanceKycStatus(
- undefined,
- {
- reason: KycStatusLongPollingReason.AUTH_TRANSFER,
- timeout: 30000,
- },
- );
- logger.info(`kyc status after transfer: ${j2s(kycStatus)}`);
- t.assertDeepEqual(kycStatus.case, "ok");
- t.assertTrue(kycStatus.body != null);
- t.assertDeepEqual(kycStatus.body.kyc_data[0].status, "kyc-required");
- t.assertTrue(typeof kycStatus.body.kyc_data[0].access_token === "string");
- accessToken = kycStatus.body.kyc_data[0].access_token as AccessToken;
- merchantPaytoHash = encodeCrock(
- hashNormalizedPaytoUri(kycStatus.body.kyc_data[0].payto_uri),
- );
- }
+ // Do KYC auth transfer
+ const { accessToken, merchantPaytoHash } = await doTopsKycAuth(t, {
+ merchantClient,
+ exchangeBankAccount,
+ wireGatewayApi,
+ });
const exchangeClient = new TalerExchangeHttpClient(exchange.baseUrl, {
httpClient: harnessHttpLib,
});
// Accept ToS
- {
- const kycInfo = await exchangeClient.checkKycInfo(
- accessToken,
- undefined,
- undefined,
- );
- console.log(j2s(kycInfo));
-
- t.assertDeepEqual(kycInfo.case, "ok");
- t.assertDeepEqual(kycInfo.body.requirements.length, 1);
- t.assertDeepEqual(kycInfo.body.requirements[0].form, "accept-tos");
- const requirementId = kycInfo.body.requirements[0].id;
- t.assertTrue(typeof requirementId === "string");
-
- const uploadRes = await exchangeClient.uploadKycForm(requirementId, {
- FORM_ID: "accept-tos",
- FORM_VERSION: 1,
- ACCEPTED_TERMS_OF_SERVICE: "v1",
- });
- console.log("upload res", uploadRes);
- t.assertDeepEqual(uploadRes.case, "ok");
- }
-
- {
- const kycInfo = await exchangeClient.checkKycInfo(
- accessToken,
- undefined,
- undefined,
- );
- console.log(j2s(kycInfo));
-
- // FIXME: Do we expect volunary measures here?
- // => not yet, see https://bugs.gnunet.org/view.php?id=9879
- }
-
- await merchant.runKyccheckOnce();
-
- {
- const kycStatus = await merchantClient.getCurrentInstanceKycStatus(
- undefined,
- {
- reason: KycStatusLongPollingReason.AUTH_TRANSFER,
- timeout: 30000,
- },
- );
- logger.info(`kyc status after accept-tos: ${j2s(kycStatus)}`);
- }
-
- const officerAcc: OfficerAccount = {
- id: amlKeypair.pub as OfficerId,
- signingKey: decodeCrock(amlKeypair.priv),
- };
+ await doTopsAcceptTos(t, {
+ accessToken,
+ exchangeClient,
+ merchantClient,
+ merchant,
+ });
- // Trigger postal registration check
- // via AML officer.
+ // Trigger kyx measure.
{
const decisionsResp = succeedOrThrow(
await exchangeClient.getAmlDecisions(officerAcc, {
@@ -211,9 +105,7 @@ export async function runTopsAmlKyxNaturalTest(t: GlobalTestState) {
);
}
- // Trigger postal registration check
- // via AML officer.
-
+ // Upload form.
{
const kycInfoResp = await exchangeClient.checkKycInfo(
accessToken,
@@ -278,44 +170,4 @@ export async function runTopsAmlKyxNaturalTest(t: GlobalTestState) {
// and make a decision.
}
-async function doFakeChallenger(
- t: GlobalTestState,
- args: {
- exchangeClient: TalerExchangeHttpClient;
- requirementId: string;
- challenger: TestfakeChallengerService;
- address: any;
- },
-): Promise<void> {
- const { exchangeClient, challenger, requirementId } = args;
- const startResp = succeedOrThrow(
- await exchangeClient.startExternalKycProcess(requirementId, {}),
- );
- console.log(`start resp`, j2s(startResp));
-
- let challengerRedirectUrl = startResp.redirect_url;
-
- const resp = await harnessHttpLib.fetch(challengerRedirectUrl);
- const respJson = await resp.json();
- console.log(`challenger resp: ${j2s(respJson)}`);
-
- const nonce = respJson.nonce;
- t.assertTrue(typeof nonce === "string");
- const proofRedirectUrl = respJson.redirect_url;
-
- challenger.fakeVerification(nonce, args.address);
-
- console.log("nonce", nonce);
- console.log("proof redirect URL", proofRedirectUrl);
-
- const proofResp = await harnessHttpLib.fetch(proofRedirectUrl, {
- redirect: "manual",
- });
- console.log("proof status:", proofResp.status);
- t.assertDeepEqual(proofResp.status, 303);
-
- const setupReq = challenger.getSetupRequest(nonce);
- console.log(`setup request: ${j2s(setupReq)}`);
-}
-
runTopsAmlKyxNaturalTest.suites = ["wallet"];