From 74fa4b3e392908bf99450a23f80b40a65897dd83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20=C3=81valos?= Date: Tue, 2 Apr 2024 12:59:42 -0600 Subject: WIP for unifying tests with corebank API --- packages/taler-harness/src/harness/harness.ts | 4 + packages/taler-harness/src/harness/helpers.ts | 235 +++++++++++++++++++++ .../src/integrationtests/test-payment.ts | 17 +- 3 files changed, 250 insertions(+), 6 deletions(-) (limited to 'packages/taler-harness/src') diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts index b27eaa371..ac65844bc 100644 --- a/packages/taler-harness/src/harness/harness.ts +++ b/packages/taler-harness/src/harness/harness.ts @@ -892,6 +892,10 @@ const useLibeufinBank = false; export interface BankServiceHandle { readonly corebankApiBaseUrl: string; readonly http: HttpRequestLibrary; + + setSuggestedExchange(exchange: ExchangeService, exchangePayto: string): void + start(): Promise + pingUntilAvailable(): Promise } export type BankService = BankServiceHandle; diff --git a/packages/taler-harness/src/harness/helpers.ts b/packages/taler-harness/src/harness/helpers.ts index ea9047d0b..3835e8b03 100644 --- a/packages/taler-harness/src/harness/helpers.ts +++ b/packages/taler-harness/src/harness/helpers.ts @@ -36,6 +36,8 @@ import { TalerCorebankApiClient, TransactionMajorState, WalletNotification, + WireGatewayApiClient, + createEddsaKeyPair, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { CoinConfig, defaultCoinConfig } from "./denomStructures.js"; @@ -51,6 +53,7 @@ import { FakebankService, GlobalTestState, HarnessExchangeBankAccount, + LibeufinBankService, MerchantService, MerchantServiceInterface, WalletCli, @@ -58,6 +61,7 @@ import { WalletService, WithAuthorization, generateRandomPayto, + generateRandomTestIban, setupDb, setupSharedDb, } from "./harness.js"; @@ -85,6 +89,7 @@ export interface SimpleTestEnvironment { export interface SimpleTestEnvironmentNg { commonDb: DbInfo; bank: BankService; + bankClient?: TalerCorebankApiClient, exchange: ExchangeService; exchangeBankAccount: HarnessExchangeBankAccount; merchant: MerchantService; @@ -100,6 +105,8 @@ export interface EnvOptions { mixedAgeRestriction?: boolean; + withLibeufin?: boolean; + additionalExchangeConfig?(e: ExchangeService): void; additionalMerchantConfig?(m: MerchantService): void; additionalBankConfig?(b: BankService): void; @@ -402,6 +409,163 @@ export async function createSimpleTestkudosEnvironmentV2( }; } +/** + * Run a test case with a simple TESTKUDOS Taler environment, consisting + * of one exchange, one bank and one merchant. + * + * V3 uses the unified Corebank API and allows to choose between + * Fakebank and Libeufin-bank. + */ +export async function createSimpleTestkudosEnvironmentV3( + t: GlobalTestState, + coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS")), + opts: EnvOptions = {}, +): Promise { + const db = await setupDb(t); + + const bc = { + allowRegistrations: true, + currency: "TESTKUDOS", + database: db.connStr, + httpPort: 8082, + }; + + const bank: BankService = opts.withLibeufin === true + ? await LibeufinBankService.create(t, bc) + : await FakebankService.create(t, bc); + + const exchange = ExchangeService.create(t, { + name: "testexchange-1", + currency: "TESTKUDOS", + httpPort: 8081, + database: db.connStr, + }); + + const merchant = await MerchantService.create(t, { + name: "testmerchant-1", + currency: "TESTKUDOS", + httpPort: 8083, + database: db.connStr, + }); + + const receiverName = "Exchange"; + const exchangeBankUsername = "exchange"; + const exchangeBankPassword = "mypw"; + const exchangePlainPayto = opts.withLibeufin === true + ? `payto://iban/SANDBOXX/${generateRandomTestIban()}` + : `payto://x-taler-bank/localhost/${receiverName}` + const exchangeExtendedPayto = `${exchangePlainPayto}?receiver-name=${receiverName}` + const wireGatewayApiBaseUrl = new URL( + "accounts/exchange/taler-wire-gateway/", + bank.corebankApiBaseUrl, + ).href; + + const exchangeBankAccount = { + wireGatewayApiBaseUrl, + accountName: exchangeBankUsername, + accountPassword: exchangeBankPassword, + accountPaytoUri: exchangeExtendedPayto, + } + + exchange.addBankAccount("1", exchangeBankAccount); + + bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri); + + if (opts.additionalBankConfig) { + opts.additionalBankConfig(bank); + } + await bank.start(); + + await bank.pingUntilAvailable(); + + const bankClient = new TalerCorebankApiClient(bank.corebankApiBaseUrl, { + auth: { + username: "admin", + password: "adminpw", + }, + }); + + await bankClient.registerAccountExtended({ + name: receiverName, + password: exchangeBankPassword, + username: exchangeBankUsername, + is_taler_exchange: true, + payto_uri: exchangePlainPayto, + }); + + const ageMaskSpec = opts.ageMaskSpec; + + if (ageMaskSpec) { + exchange.enableAgeRestrictions(ageMaskSpec); + // Enable age restriction for all coins. + exchange.addCoinConfigList( + coinConfig.map((x) => ({ + ...x, + name: `${x.name}-age`, + ageRestricted: true, + })), + ); + // For mixed age restrictions, we also offer coins without age restrictions + if (opts.mixedAgeRestriction) { + exchange.addCoinConfigList( + coinConfig.map((x) => ({ ...x, ageRestricted: false })), + ); + } + } else { + exchange.addCoinConfigList(coinConfig); + } + + if (opts.additionalExchangeConfig) { + opts.additionalExchangeConfig(exchange); + } + await exchange.start(); + await exchange.pingUntilAvailable(); + + merchant.addExchange(exchange); + + if (opts.additionalMerchantConfig) { + opts.additionalMerchantConfig(merchant); + } + await merchant.start(); + await merchant.pingUntilAvailable(); + + await merchant.addInstanceWithWireAccount({ + id: "default", + name: "Default Instance", + paytoUris: [generateRandomPayto("merchant-default")], + defaultWireTransferDelay: Duration.toTalerProtocolDuration( + Duration.fromSpec({ minutes: 1 }), + ), + }); + + await merchant.addInstanceWithWireAccount({ + id: "minst1", + name: "minst1", + paytoUris: [generateRandomPayto("minst1")], + defaultWireTransferDelay: Duration.toTalerProtocolDuration( + Duration.fromSpec({ minutes: 1 }), + ), + }); + + const { walletClient, walletService } = await createWalletDaemonWithClient( + t, + { name: "wallet", persistent: true }, + ); + + console.log("setup done!"); + + return { + commonDb: db, + exchange, + merchant, + walletClient, + walletService, + bank, + bankClient, + exchangeBankAccount, + }; +} + export interface CreateWalletArgs { handleNotification?(wn: WalletNotification): void; name: string; @@ -621,6 +785,77 @@ export async function withdrawViaBankV2( }; } +/** + * Withdraw via a bank with the testing API enabled. + * Uses the new Corebank API. + */ +export async function withdrawViaBankV3( + t: GlobalTestState, + p: { + walletClient: WalletClient; + bankClient: TalerCorebankApiClient, + exchange: ExchangeServiceInterface; + amount: AmountString | string; + restrictAge?: number; + }, +): Promise { + const { walletClient: wallet, bankClient, exchange, amount } = p; + + console.log("line 804") + + const user = await bankClient.createRandomBankUser(); + const bankClient2 = new TalerCorebankApiClient(bankClient.baseUrl, { + auth: { + username: user.username, + password: user.password, + } + }); + const wop = await bankClient2.createWithdrawalOperation(user.username, amount); + + console.log("line 815") + + // Hand it to the wallet + + await wallet.client.call(WalletApiOperation.GetWithdrawalDetailsForUri, { + talerWithdrawUri: wop.taler_withdraw_uri, + restrictAge: p.restrictAge, + }); + + console.log("line 824") + + // Withdraw (AKA select) + + const acceptRes = await wallet.client.call( + WalletApiOperation.AcceptBankIntegratedWithdrawal, + { + exchangeBaseUrl: exchange.baseUrl, + talerWithdrawUri: wop.taler_withdraw_uri, + restrictAge: p.restrictAge, + }, + ); + + console.log("line 837") + + const withdrawalFinishedCond = wallet.waitForNotificationCond( + (x) => + x.type === NotificationType.TransactionStateTransition && + x.newTxState.major === TransactionMajorState.Done && + x.transactionId === acceptRes.transactionId, + ); + + console.log("line 846") + + // Confirm it + + await bankClient2.confirmWithdrawalOperation(user.username, { + withdrawalOperationId: wop.withdrawal_id, + }); + + return { + withdrawalFinishedCond, + }; +} + export async function applyTimeTravelV2( timetravelOffsetMs: number, s: { diff --git a/packages/taler-harness/src/integrationtests/test-payment.ts b/packages/taler-harness/src/integrationtests/test-payment.ts index 9d1ce0e22..aaf83dd4b 100644 --- a/packages/taler-harness/src/integrationtests/test-payment.ts +++ b/packages/taler-harness/src/integrationtests/test-payment.ts @@ -20,8 +20,8 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { GlobalTestState } from "../harness/harness.js"; import { - createSimpleTestkudosEnvironmentV2, - withdrawViaBankV2, + createSimpleTestkudosEnvironmentV3, + withdrawViaBankV3, makeTestPaymentV2, } from "../harness/helpers.js"; import { j2s } from "@gnu-taler/taler-util"; @@ -32,15 +32,20 @@ import { j2s } from "@gnu-taler/taler-util"; export async function runPaymentTest(t: GlobalTestState) { // Set up test environment - const { walletClient, bank, exchange, merchant } = - await createSimpleTestkudosEnvironmentV2(t); + const { walletClient, bankClient, exchange, merchant } = + await createSimpleTestkudosEnvironmentV3(t, undefined, { + withLibeufin: false, + }); // Withdraw digital cash into the wallet. - - await withdrawViaBankV2(t, { walletClient, bank, exchange, amount: "TESTKUDOS:20" }); + + t.assertTrue(bankClient !== undefined); + await withdrawViaBankV3(t, { walletClient, bankClient, exchange, amount: "TESTKUDOS:20" }); await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); + console.log("line 51") + const order = { summary: "Buy me!", amount: "TESTKUDOS:5", -- cgit v1.2.3