diff options
author | Christian Blättler <blatc2@bfh.ch> | 2024-06-13 11:35:52 +0200 |
---|---|---|
committer | Christian Blättler <blatc2@bfh.ch> | 2024-06-13 11:35:52 +0200 |
commit | eb964dfae0a12f9a90eb066d610f627538f8997c (patch) | |
tree | 26a6cd74c9a29edce05b2dcd51cf497374bf8e30 /packages/taler-harness/src | |
parent | 9d0fc80a905e02a0a0b63dd547daac6e7b17fb52 (diff) | |
parent | f9d4ff5b43e48a07ac81d7e7ef800ddb12f5f90a (diff) | |
download | wallet-core-eb964dfae0a12f9a90eb066d610f627538f8997c.tar.xz |
Merge branch 'master' into feature/tokens
Diffstat (limited to 'packages/taler-harness/src')
15 files changed, 473 insertions, 291 deletions
diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts index 136ec3d15..4fc462ddf 100644 --- a/packages/taler-harness/src/harness/harness.ts +++ b/packages/taler-harness/src/harness/harness.ts @@ -274,6 +274,7 @@ export class GlobalTestState { procs: ProcessWrapper[]; servers: http.Server[]; inShutdown: boolean = false; + stepSet: Set<string> = new Set(); constructor(params: GlobalTestParams) { this.testDir = params.testDir; this.procs = []; @@ -423,6 +424,9 @@ export class GlobalTestState { // Now we just log, later we may report the steps that were done // to easily see where the test hangs. console.info(`STEP: ${stepName}`); + if (this.stepSet.has(stepName)) { + throw Error(`duplicate step (${stepName})`); + } } } diff --git a/packages/taler-harness/src/harness/helpers.ts b/packages/taler-harness/src/harness/helpers.ts index 4e3ce66b9..d194b0d36 100644 --- a/packages/taler-harness/src/harness/helpers.ts +++ b/packages/taler-harness/src/harness/helpers.ts @@ -116,6 +116,8 @@ export interface EnvOptions { mixedAgeRestriction?: boolean; + skipWireFeeCreation?: boolean; + additionalExchangeConfig?(e: ExchangeService): void; additionalMerchantConfig?(m: MerchantService): void; additionalBankConfig?(b: BankService): void; @@ -466,11 +468,12 @@ export async function createSimpleTestkudosEnvironmentV3( bank.corebankApiBaseUrl, ).href; - const exchangeBankAccount = { + const exchangeBankAccount: HarnessExchangeBankAccount = { wireGatewayApiBaseUrl, accountName: exchangeBankUsername, accountPassword: exchangeBankPassword, accountPaytoUri: exchangePaytoUri, + skipWireFeeCreation: opts.skipWireFeeCreation === true, }; await exchange.addBankAccount("1", exchangeBankAccount); diff --git a/packages/taler-harness/src/integrationtests/test-currency-scope.ts b/packages/taler-harness/src/integrationtests/test-currency-scope.ts index 69e45f678..34d18d87d 100644 --- a/packages/taler-harness/src/integrationtests/test-currency-scope.ts +++ b/packages/taler-harness/src/integrationtests/test-currency-scope.ts @@ -17,13 +17,14 @@ /** * Imports. */ -import { Duration, j2s } from "@gnu-taler/taler-util"; +import { Duration, TalerCorebankApiClient, j2s } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; import { + BankService, ExchangeService, - FakebankService, GlobalTestState, + HarnessExchangeBankAccount, MerchantService, generateRandomPayto, setupDb, @@ -31,6 +32,7 @@ import { import { createWalletDaemonWithClient, withdrawViaBankV2, + withdrawViaBankV3, } from "../harness/helpers.js"; /** @@ -44,7 +46,7 @@ export async function runCurrencyScopeTest(t: GlobalTestState) { nameSuffix: "exchange2", }); - const bank = await FakebankService.create(t, { + const bank = await BankService.create(t, { allowRegistrations: true, currency: "TESTKUDOS", database: dbDefault.connStr, @@ -72,17 +74,25 @@ export async function runCurrencyScopeTest(t: GlobalTestState) { database: dbDefault.connStr, }); - const exchangeOneBankAccount = await bank.createExchangeAccount( - "myexchange", - "x", - ); - await exchangeOne.addBankAccount("1", exchangeOneBankAccount); - - const exchangeTwoBankAccount = await bank.createExchangeAccount( - "myexchange2", - "x", - ); - await exchangeTwo.addBankAccount("1", exchangeTwoBankAccount); + let exchangeOneBankAccount: HarnessExchangeBankAccount = { + wireGatewayApiBaseUrl: new URL( + "accounts/myexchange/taler-wire-gateway/", + bank.corebankApiBaseUrl, + ).href, + accountName: "myexchange", + accountPassword: "x", + accountPaytoUri: generateRandomPayto("myexchange"), + }; + + let exchangeTwoBankAccount: HarnessExchangeBankAccount = { + wireGatewayApiBaseUrl: new URL( + "accounts/myexchange2/taler-wire-gateway/", + bank.corebankApiBaseUrl, + ).href, + accountName: "myexchange2", + accountPassword: "x", + accountPaytoUri: generateRandomPayto("myexchange2"), + }; bank.setSuggestedExchange( exchangeOne, @@ -93,6 +103,31 @@ export async function runCurrencyScopeTest(t: GlobalTestState) { await bank.pingUntilAvailable(); + const bankClient = new TalerCorebankApiClient(bank.corebankApiBaseUrl, { + auth: { + username: "admin", + password: "adminpw", + }, + }); + + await bankClient.registerAccountExtended({ + name: exchangeOneBankAccount.accountName, + username: exchangeOneBankAccount.accountName, + password: exchangeOneBankAccount.accountPassword, + is_taler_exchange: true, + payto_uri: exchangeOneBankAccount.accountPaytoUri, + }); + await exchangeOne.addBankAccount("1", exchangeOneBankAccount); + + await bankClient.registerAccountExtended({ + name: exchangeTwoBankAccount.accountName, + username: exchangeTwoBankAccount.accountName, + password: exchangeTwoBankAccount.accountPassword, + is_taler_exchange: true, + payto_uri: exchangeTwoBankAccount.accountPaytoUri, + }); + await exchangeTwo.addBankAccount("1", exchangeTwoBankAccount); + // Set up the first exchange exchangeOne.addOfferedCoins(defaultCoinConfig); @@ -139,16 +174,16 @@ export async function runCurrencyScopeTest(t: GlobalTestState) { // Withdraw digital cash into the wallet. - const w1 = await withdrawViaBankV2(t, { + const w1 = await withdrawViaBankV3(t, { walletClient, - bank, + bankClient, exchange: exchangeOne, amount: "TESTKUDOS:6", }); - const w2 = await withdrawViaBankV2(t, { + const w2 = await withdrawViaBankV3(t, { walletClient, - bank, + bankClient, exchange: exchangeTwo, amount: "TESTKUDOS:6", }); diff --git a/packages/taler-harness/src/integrationtests/test-multiexchange.ts b/packages/taler-harness/src/integrationtests/test-multiexchange.ts index b5cf0770f..26e843073 100644 --- a/packages/taler-harness/src/integrationtests/test-multiexchange.ts +++ b/packages/taler-harness/src/integrationtests/test-multiexchange.ts @@ -17,13 +17,14 @@ /** * Imports. */ -import { Duration, TalerMerchantApi } from "@gnu-taler/taler-util"; +import { Duration, TalerCorebankApiClient, TalerMerchantApi } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; import { + BankService, ExchangeService, - FakebankService, GlobalTestState, + HarnessExchangeBankAccount, MerchantService, generateRandomPayto, setupDb, @@ -32,6 +33,7 @@ import { createWalletDaemonWithClient, makeTestPaymentV2, withdrawViaBankV2, + withdrawViaBankV3, } from "../harness/helpers.js"; /** @@ -45,7 +47,7 @@ export async function runMultiExchangeTest(t: GlobalTestState) { nameSuffix: "exchange2", }); - const bank = await FakebankService.create(t, { + const bank = await BankService.create(t, { allowRegistrations: true, currency: "TESTKUDOS", database: dbDefault.connStr, @@ -73,17 +75,25 @@ export async function runMultiExchangeTest(t: GlobalTestState) { database: dbDefault.connStr, }); - const exchangeOneBankAccount = await bank.createExchangeAccount( - "myexchange", - "x", - ); - await exchangeOne.addBankAccount("1", exchangeOneBankAccount); + let exchangeOneBankAccount: HarnessExchangeBankAccount = { + wireGatewayApiBaseUrl: new URL( + "accounts/myexchange/taler-wire-gateway/", + bank.corebankApiBaseUrl, + ).href, + accountName: "myexchange", + accountPassword: "x", + accountPaytoUri: generateRandomPayto("myexchange"), + }; - const exchangeTwoBankAccount = await bank.createExchangeAccount( - "myexchange2", - "x", - ); - await exchangeTwo.addBankAccount("1", exchangeTwoBankAccount); + let exchangeTwoBankAccount: HarnessExchangeBankAccount = { + wireGatewayApiBaseUrl: new URL( + "accounts/myexchange2/taler-wire-gateway/", + bank.corebankApiBaseUrl, + ).href, + accountName: "myexchange2", + accountPassword: "x", + accountPaytoUri: generateRandomPayto("myexchange2"), + }; bank.setSuggestedExchange( exchangeOne, @@ -94,6 +104,31 @@ export async function runMultiExchangeTest(t: GlobalTestState) { await bank.pingUntilAvailable(); + const bankClient = new TalerCorebankApiClient(bank.corebankApiBaseUrl, { + auth: { + username: "admin", + password: "adminpw", + }, + }); + + await bankClient.registerAccountExtended({ + name: exchangeOneBankAccount.accountName, + username: exchangeOneBankAccount.accountName, + password: exchangeOneBankAccount.accountPassword, + is_taler_exchange: true, + payto_uri: exchangeOneBankAccount.accountPaytoUri, + }); + await exchangeOne.addBankAccount("1", exchangeOneBankAccount); + + await bankClient.registerAccountExtended({ + name: exchangeTwoBankAccount.accountName, + username: exchangeTwoBankAccount.accountName, + password: exchangeTwoBankAccount.accountPassword, + is_taler_exchange: true, + payto_uri: exchangeTwoBankAccount.accountPaytoUri, + }); + await exchangeTwo.addBankAccount("1", exchangeTwoBankAccount); + // Set up the first exchange exchangeOne.addOfferedCoins(defaultCoinConfig); @@ -141,16 +176,16 @@ export async function runMultiExchangeTest(t: GlobalTestState) { // Withdraw digital cash into the wallet. - await withdrawViaBankV2(t, { + await withdrawViaBankV3(t, { walletClient, - bank, + bankClient, exchange: exchangeOne, amount: "TESTKUDOS:6", }); - await withdrawViaBankV2(t, { + await withdrawViaBankV3(t, { walletClient, - bank, + bankClient, exchange: exchangeTwo, amount: "TESTKUDOS:6", }); diff --git a/packages/taler-harness/src/integrationtests/test-payment-template.ts b/packages/taler-harness/src/integrationtests/test-payment-template.ts index fc4cd1198..af92d43c5 100644 --- a/packages/taler-harness/src/integrationtests/test-payment-template.ts +++ b/packages/taler-harness/src/integrationtests/test-payment-template.ts @@ -93,7 +93,9 @@ export async function runPaymentTemplateTest(t: GlobalTestState) { WalletApiOperation.PreparePayForTemplate, { talerPayTemplateUri, - templateParams: {}, + templateParams: { + amount: "TESTKUDOS:1", + }, }, ); diff --git a/packages/taler-harness/src/integrationtests/test-refund-auto.ts b/packages/taler-harness/src/integrationtests/test-refund-auto.ts index 5fcfa066a..6e02071af 100644 --- a/packages/taler-harness/src/integrationtests/test-refund-auto.ts +++ b/packages/taler-harness/src/integrationtests/test-refund-auto.ts @@ -17,7 +17,12 @@ /** * Imports. */ -import { Duration, MerchantApiClient } from "@gnu-taler/taler-util"; +import { + Duration, + MerchantApiClient, + TransactionMajorState, + TransactionMinorState, +} from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { GlobalTestState } from "../harness/harness.js"; import { @@ -47,67 +52,134 @@ export async function runRefundAutoTest(t: GlobalTestState) { await wres.withdrawalFinishedCond; - // Set up order. - const orderResp = await merchantClient.createOrder({ - order: { - summary: "Buy me!", - amount: "TESTKUDOS:5", - fulfillment_url: "taler://fulfillment-success/thx", - auto_refund: { - d_us: 3000 * 1000, + // Test case where the auto-refund happens + { + // Set up order. + const orderResp = await merchantClient.createOrder({ + order: { + summary: "Buy me!", + amount: "TESTKUDOS:5", + fulfillment_url: "taler://fulfillment-success/thx", + auto_refund: { + d_us: 3000 * 1000, + }, }, - }, - refund_delay: Duration.toTalerProtocolDuration( - Duration.fromSpec({ minutes: 5 }), - ), - }); + refund_delay: Duration.toTalerProtocolDuration( + Duration.fromSpec({ minutes: 5 }), + ), + }); - let orderStatus = await merchantClient.queryPrivateOrderStatus({ - orderId: orderResp.order_id, - }); + let orderStatus = await merchantClient.queryPrivateOrderStatus({ + orderId: orderResp.order_id, + }); - t.assertTrue(orderStatus.order_status === "unpaid"); + t.assertTrue(orderStatus.order_status === "unpaid"); - // Make wallet pay for the order + // Make wallet pay for the order - const r1 = await walletClient.call(WalletApiOperation.PreparePayForUri, { - talerPayUri: orderStatus.taler_pay_uri, - }); + const r1 = await walletClient.call(WalletApiOperation.PreparePayForUri, { + talerPayUri: orderStatus.taler_pay_uri, + }); - await walletClient.call(WalletApiOperation.ConfirmPay, { - transactionId: r1.transactionId, - }); + await walletClient.call(WalletApiOperation.ConfirmPay, { + transactionId: r1.transactionId, + }); - // Check if payment was successful. + // Check if payment was successful. - orderStatus = await merchantClient.queryPrivateOrderStatus({ - orderId: orderResp.order_id, - }); + orderStatus = await merchantClient.queryPrivateOrderStatus({ + orderId: orderResp.order_id, + }); - t.assertTrue(orderStatus.order_status === "paid"); + t.assertTrue(orderStatus.order_status === "paid"); - const ref = await merchantClient.giveRefund({ - amount: "TESTKUDOS:5", - instance: "default", - justification: "foo", - orderId: orderResp.order_id, - }); + const ref = await merchantClient.giveRefund({ + amount: "TESTKUDOS:5", + instance: "default", + justification: "foo", + orderId: orderResp.order_id, + }); + + console.log(ref); + + // The wallet should now automatically pick up the refund. + await walletClient.call( + WalletApiOperation.TestingWaitTransactionsFinal, + {}, + ); + + const transactions = await walletClient.call( + WalletApiOperation.GetTransactions, + { + sort: "stable-ascending", + }, + ); + console.log(JSON.stringify(transactions, undefined, 2)); + + const transactionTypes = transactions.transactions.map((x) => x.type); + t.assertDeepEqual(transactionTypes, ["withdrawal", "payment", "refund"]); + } + + // Now test the case where the auto-refund just expires + + { + // Set up order. + const orderResp = await merchantClient.createOrder({ + order: { + summary: "Buy me!", + amount: "TESTKUDOS:5", + fulfillment_url: "taler://fulfillment-success/thx", + auto_refund: { + d_us: 3000 * 1000, + }, + }, + refund_delay: Duration.toTalerProtocolDuration( + Duration.fromSpec({ minutes: 5 }), + ), + }); + + let orderStatus = await merchantClient.queryPrivateOrderStatus({ + orderId: orderResp.order_id, + }); + + t.assertTrue(orderStatus.order_status === "unpaid"); - console.log(ref); + // Make wallet pay for the order - // The wallet should now automatically pick up the refund. - await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); + const r1 = await walletClient.call(WalletApiOperation.PreparePayForUri, { + talerPayUri: orderStatus.taler_pay_uri, + }); - const transactions = await walletClient.call( - WalletApiOperation.GetTransactions, - {}, - ); - console.log(JSON.stringify(transactions, undefined, 2)); + await walletClient.call(WalletApiOperation.ConfirmPay, { + transactionId: r1.transactionId, + }); - const transactionTypes = transactions.transactions.map((x) => x.type); - t.assertDeepEqual(transactionTypes, ["withdrawal", "payment", "refund"]); + // Check if payment was successful. - await t.shutdown(); + orderStatus = await merchantClient.queryPrivateOrderStatus({ + orderId: orderResp.order_id, + }); + + t.assertTrue(orderStatus.order_status === "paid"); + + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: r1.transactionId, + txState: { + major: TransactionMajorState.Pending, + minor: TransactionMinorState.AutoRefund, + }, + }); + // Only time-travel the wallet + await walletClient.call(WalletApiOperation.TestingSetTimetravel, { + offsetMs: 5000, + }); + await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: r1.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }); + } } runRefundAutoTest.suites = ["wallet"]; diff --git a/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts b/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts index e6c84b75d..046bd5aed 100644 --- a/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts +++ b/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts @@ -24,11 +24,12 @@ import { NotificationType, PreparePayResultType, TalerCorebankApiClient, + j2s, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { makeNoFeeCoinConfig } from "../harness/denomStructures.js"; import { - BankService, + BankService, ExchangeService, GlobalTestState, MerchantService, @@ -78,7 +79,10 @@ export async function runTimetravelAutorefreshTest(t: GlobalTestState) { await exchange.addBankAccount("1", { accountName: exchangeBankUsername, accountPassword: exchangeBankPassword, - wireGatewayApiBaseUrl: new URL("accounts/exchange/taler-wire-gateway/", bank.baseUrl).href, + wireGatewayApiBaseUrl: new URL( + "accounts/exchange/taler-wire-gateway/", + bank.baseUrl, + ).href, accountPaytoUri: exchangePaytoUri, }); @@ -129,29 +133,42 @@ export async function runTimetravelAutorefreshTest(t: GlobalTestState) { const { walletClient } = await createWalletDaemonWithClient(t, { name: "w1", + persistent: true, }); const merchantClient = new MerchantApiClient(merchant.makeInstanceBaseUrl()); - // Withdraw digital cash into the wallet. + t.logStep("exchangeUpdated1Cond"); + // Withdraw digital cash into the wallet. + t.logStep("Withdraw digital cash into the wallet."); const wres = await withdrawViaBankV3(t, { walletClient, bankClient, exchange, amount: "TESTKUDOS:15", }); + t.logStep("wait"); await wres.withdrawalFinishedCond; - const exchangeUpdated1Cond = walletClient.waitForNotificationCond( (x) => - x.type === NotificationType.ExchangeStateTransition && - x.exchangeBaseUrl === exchange.baseUrl, + { + t.logStep(`EXCHANGE UPDATE, ${j2s(x)}`) + return x.type === NotificationType.ExchangeStateTransition && + x.exchangeBaseUrl === exchange.baseUrl + } ); + t.logStep("waiting tx"); + await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); + { + const balance = await walletClient.call(WalletApiOperation.GetBalances, {}); + t.assertAmountEquals(balance.balances[0].available, "TESTKUDOS:15"); + } + // Travel into the future, the deposit expiration is two years // into the future. - console.log("applying first time travel"); + t.logStep("applying first time travel"); await applyTimeTravelV2( Duration.toMilliseconds(Duration.fromSpec({ days: 400 })), { @@ -162,9 +179,16 @@ export async function runTimetravelAutorefreshTest(t: GlobalTestState) { ); // The time travel should cause exchanges to update. + t.logStep("The time travel should cause exchanges to update"); await exchangeUpdated1Cond; + t.logStep("exchange updated, waiting for tx"); await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); + { + const balance = await walletClient.call(WalletApiOperation.GetBalances, {}); + t.assertAmountEquals(balance.balances[0].available, "TESTKUDOS:15"); + } + t.logStep("withdrawing second time"); const wres2 = await withdrawViaBankV3(t, { walletClient, bankClient, @@ -173,8 +197,14 @@ export async function runTimetravelAutorefreshTest(t: GlobalTestState) { }); await wres2.withdrawalFinishedCond; + t.logStep("witdrawn, waiting tx"); await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); + { + const balance = await walletClient.call(WalletApiOperation.GetBalances, {}); + t.assertAmountEquals(balance.balances[0].available, "TESTKUDOS:35"); + } + const exchangeUpdated2Cond = walletClient.waitForNotificationCond( (x) => x.type === NotificationType.ExchangeStateTransition && @@ -183,7 +213,7 @@ export async function runTimetravelAutorefreshTest(t: GlobalTestState) { // Travel into the future, the deposit expiration is two years // into the future. - console.log("applying second time travel"); + t.logStep("applying second time travel"); await applyTimeTravelV2( Duration.toMilliseconds(Duration.fromSpec({ years: 2, months: 6 })), { @@ -194,8 +224,13 @@ export async function runTimetravelAutorefreshTest(t: GlobalTestState) { ); // The time travel should cause exchanges to update. + t.logStep("The time travel should cause exchanges to update."); await exchangeUpdated2Cond; await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); + { + const balance = await walletClient.call(WalletApiOperation.GetBalances, {}); + t.assertAmountEquals(balance.balances[0].available, "TESTKUDOS:35"); + } // At this point, the original coins should've been refreshed. // It would be too late to refresh them now, as we're past diff --git a/packages/taler-harness/src/integrationtests/test-wallet-denom-expire.ts b/packages/taler-harness/src/integrationtests/test-wallet-denom-expire.ts index b9d028efd..a2573eda1 100644 --- a/packages/taler-harness/src/integrationtests/test-wallet-denom-expire.ts +++ b/packages/taler-harness/src/integrationtests/test-wallet-denom-expire.ts @@ -17,21 +17,16 @@ /** * Imports. */ -import { Duration, Logger, NotificationType, TalerCorebankApiClient, j2s } from "@gnu-taler/taler-util"; +import { Duration, Logger, NotificationType, j2s } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { makeNoFeeCoinConfig } from "../harness/denomStructures.js"; import { - BankService, - ExchangeService, - FakebankService, GlobalTestState, - MerchantService, - generateRandomPayto, setupDb, } from "../harness/harness.js"; import { applyTimeTravelV2, - createWalletDaemonWithClient, + createSimpleTestkudosEnvironmentV3, withdrawViaBankV3, } from "../harness/helpers.js"; @@ -45,89 +40,14 @@ export async function runWalletDenomExpireTest(t: GlobalTestState) { const db = await setupDb(t); - const bank = await BankService.create(t, { - allowRegistrations: true, - currency: "TESTKUDOS", - database: db.connStr, - httpPort: 8082, - }); - - 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, - }); - - let receiverName = "Exchange"; - let exchangeBankUsername = "exchange"; - let exchangeBankPassword = "mypw"; - let exchangePaytoUri = generateRandomPayto(exchangeBankUsername); - - await exchange.addBankAccount("1", { - accountName: exchangeBankUsername, - accountPassword: exchangeBankPassword, - wireGatewayApiBaseUrl: new URL("accounts/exchange/taler-wire-gateway/", bank.baseUrl).href, - accountPaytoUri: exchangePaytoUri, - }); - - bank.setSuggestedExchange(exchange, exchangePaytoUri); - - 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: exchangePaytoUri, - }); - - exchange.addCoinConfigList(makeNoFeeCoinConfig("TESTKUDOS")); - - await exchange.start(); - await exchange.pingUntilAvailable(); - - merchant.addExchange(exchange); - - await merchant.start(); - await merchant.pingUntilAvailable(); - - console.log("merchant started, configuring instances"); - - await merchant.addInstanceWithWireAccount({ - id: "default", - name: "Default Instance", - paytoUris: [generateRandomPayto("merchant-default")], - }); + const coinConfig = makeNoFeeCoinConfig("TESTKUDOS"); - await merchant.addInstanceWithWireAccount({ - id: "minst1", - name: "minst1", - paytoUris: [generateRandomPayto("minst1")], - }); - - console.log("setup done!"); - - const { walletClient } = await createWalletDaemonWithClient(t, { - name: "default", - }); + const { + walletClient, + bankClient, + exchange, + merchant, + } = await createSimpleTestkudosEnvironmentV3(t, coinConfig, {}); // Withdraw digital cash into the wallet. diff --git a/packages/taler-harness/src/integrationtests/test-wallet-exchange-update.ts b/packages/taler-harness/src/integrationtests/test-wallet-exchange-update.ts index b36e6ef61..3a1b467c3 100644 --- a/packages/taler-harness/src/integrationtests/test-wallet-exchange-update.ts +++ b/packages/taler-harness/src/integrationtests/test-wallet-exchange-update.ts @@ -21,6 +21,7 @@ import { AmountString, ExchangeUpdateStatus, NotificationType, + TalerCorebankApiClient, j2s, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; @@ -30,11 +31,14 @@ import { ExchangeService, FakebankService, GlobalTestState, + HarnessExchangeBankAccount, + generateRandomPayto, setupDb, } from "../harness/harness.js"; import { createWalletDaemonWithClient, withdrawViaBankV2, + withdrawViaBankV3, } from "../harness/helpers.js"; /** @@ -51,7 +55,7 @@ export async function runWalletExchangeUpdateTest( nameSuffix: "two", }); - const bank = await FakebankService.create(t, { + const bank = await BankService.create(t, { allowRegistrations: true, currency: "TESTKUDOS", database: db.connStr, @@ -75,10 +79,27 @@ export async function runWalletExchangeUpdateTest( database: db2.connStr, }); - const exchangeBankAccount = await bank.createExchangeAccount( - "myexchange", - "x", - ); + const bankClient = new TalerCorebankApiClient(bank.corebankApiBaseUrl, { + auth: { + username: "admin", + password: "adminpw", + }, + }); + + // const exchangeBankAccount = await bank.createExchangeAccount( + // "myexchange", + // "x", + // ); + + let exchangeBankAccount: HarnessExchangeBankAccount = { + wireGatewayApiBaseUrl: new URL( + "accounts/myexchange/taler-wire-gateway/", + bank.corebankApiBaseUrl, + ).href, + accountName: "myexchange", + accountPassword: "x", + accountPaytoUri: generateRandomPayto("myexchange"), + }; await exchangeOne.addBankAccount("1", exchangeBankAccount); await exchangeTwo.addBankAccount("1", exchangeBankAccount); @@ -88,6 +109,14 @@ export async function runWalletExchangeUpdateTest( await bank.start(); + bankClient.registerAccountExtended({ + name: exchangeBankAccount.accountName, + username: exchangeBankAccount.accountName, + password: exchangeBankAccount.accountPassword, + is_taler_exchange: true, + payto_uri: exchangeBankAccount.accountPaytoUri, + }); + exchangeOne.addCoinConfigList(defaultCoinConfig.map((x) => x("TESTKUDOS"))); exchangeTwo.addCoinConfigList(defaultCoinConfig.map((x) => x("TESTKUDOS"))); @@ -108,9 +137,9 @@ export async function runWalletExchangeUpdateTest( t.assertDeepEqual(exchangesListResult.exchanges.length, 0); - const wres = await withdrawViaBankV2(t, { + const wres = await withdrawViaBankV3(t, { walletClient, - bank, + bankClient, exchange: exchangeOne, amount: "TESTKUDOS:10", }); diff --git a/packages/taler-harness/src/integrationtests/test-wallet-insufficient-balance.ts b/packages/taler-harness/src/integrationtests/test-wallet-insufficient-balance.ts index ac1244446..4062e186d 100644 --- a/packages/taler-harness/src/integrationtests/test-wallet-insufficient-balance.ts +++ b/packages/taler-harness/src/integrationtests/test-wallet-insufficient-balance.ts @@ -22,71 +22,32 @@ import { Duration, PaymentInsufficientBalanceDetails, TalerErrorCode, - WalletNotification, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js"; import { - ExchangeService, - FakebankService, GlobalTestState, - MerchantService, - WalletClient, - WalletService, generateRandomPayto, setupDb, } from "../harness/harness.js"; -import { withdrawViaBankV2 } from "../harness/helpers.js"; +import { createSimpleTestkudosEnvironmentV3, withdrawViaBankV3 } from "../harness/helpers.js"; export async function runWalletInsufficientBalanceTest(t: GlobalTestState) { // Set up test environment const db = await setupDb(t); - const bank = await FakebankService.create(t, { - allowRegistrations: true, - currency: "TESTKUDOS", - database: db.connStr, - httpPort: 8082, - }); - - 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 exchangeBankAccount = await bank.createExchangeAccount( - "myexchange", - "x", - ); - exchangeBankAccount.skipWireFeeCreation = true; - exchange.addBankAccount("1", exchangeBankAccount); - - bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri); - - await bank.start(); - - await bank.pingUntilAvailable(); - const coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS")); - exchange.addCoinConfigList(coinConfig); - - await exchange.start(); - await exchange.pingUntilAvailable(); - merchant.addExchange(exchange); - - await merchant.start(); - await merchant.pingUntilAvailable(); + let { + bankClient, + exchange, + merchant, + walletService, + walletClient, + } = await createSimpleTestkudosEnvironmentV3(t, coinConfig, { + skipWireFeeCreation: true, + }); await merchant.addInstanceWithWireAccount({ id: "default", @@ -106,24 +67,6 @@ export async function runWalletInsufficientBalanceTest(t: GlobalTestState) { ), }); - const walletService = new WalletService(t, { - name: "wallet", - useInMemoryDb: true, - }); - await walletService.start(); - await walletService.pingUntilAvailable(); - - const allNotifications: WalletNotification[] = []; - - const walletClient = new WalletClient({ - name: "wallet", - unixPath: walletService.socketPath, - onNotification(n) { - console.log("got notification", n); - allNotifications.push(n); - }, - }); - await walletClient.connect(); await walletClient.client.call(WalletApiOperation.InitWallet, { config: { testing: { @@ -132,9 +75,9 @@ export async function runWalletInsufficientBalanceTest(t: GlobalTestState) { }, }); - const wres = await withdrawViaBankV2(t, { + const wres = await withdrawViaBankV3(t, { amount: "TESTKUDOS:10", - bank, + bankClient, exchange, walletClient, }); @@ -146,10 +89,12 @@ export async function runWalletInsufficientBalanceTest(t: GlobalTestState) { depositPaytoUri: "payto://x-taler-bank/localhost/foobar", }); }); + t.assertDeepEqual( exc.errorDetail.code, TalerErrorCode.WALLET_DEPOSIT_GROUP_INSUFFICIENT_BALANCE, ); + const insufficientBalanceDetails: PaymentInsufficientBalanceDetails = exc.errorDetail.insufficientBalanceDetails; diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts index a13095883..3ec2a3bcd 100644 --- a/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts +++ b/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts @@ -46,7 +46,7 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) { "TESTKUDOS:10", ); - // Hand it to the wallet + t.logStep("Hand it to the wallet") const r1 = await walletClient.client.call( WalletApiOperation.GetWithdrawalDetailsForUri, @@ -55,7 +55,7 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) { }, ); - // Withdraw + t.logStep("Withdraw") const r2 = await walletClient.client.call( WalletApiOperation.AcceptBankIntegratedWithdrawal, @@ -65,6 +65,7 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) { }, ); + t.logStep("wait confirmed") const withdrawalBankConfirmedCond = walletClient.waitForNotificationCond( (x) => { return ( @@ -76,6 +77,7 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) { }, ); + t.logStep("wait finished") const withdrawalFinishedCond = walletClient.waitForNotificationCond((x) => { return ( x.type === NotificationType.TransactionStateTransition && @@ -84,6 +86,7 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) { ); }); + t.logStep("wait withdraw coins") const withdrawalReserveReadyCond = walletClient.waitForNotificationCond( (x) => { return ( @@ -95,7 +98,7 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) { }, ); - // Do it twice to check idempotency + t.logStep("Do it twice to check idempotency") const r3 = await walletClient.client.call( WalletApiOperation.AcceptBankIntegratedWithdrawal, { @@ -104,9 +107,10 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) { }, ); + t.logStep("stop wirewatch") await exchange.stopWirewatch(); - // Check status before withdrawal is confirmed by bank. + t.logStep("Check status before withdrawal is confirmed by bank.") { const txn = await walletClient.client.call( WalletApiOperation.GetTransactions, @@ -122,7 +126,7 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) { t.assertTrue(tx0.withdrawalDetails.reserveIsReady === false); } - // Confirm it + t.logStep("Confirm it") await bankClient.confirmWithdrawalOperation(user.username, { withdrawalOperationId: wop.withdrawal_id, @@ -132,6 +136,7 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) { // Check status after withdrawal is confirmed by bank, // but before funds are wired to the exchange. + t.logStep("Check status after withdrawal") { const txn = await walletClient.client.call( WalletApiOperation.GetTransactions, @@ -147,11 +152,13 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) { t.assertTrue(tx0.withdrawalDetails.reserveIsReady === false); } + t.logStep("start wirewatch") await exchange.startWirewatch(); + t.logStep("wait reserve") await withdrawalReserveReadyCond; - // Check status after funds were wired. + t.logStep("Check status after funds were wired.") { const txn = await walletClient.client.call( WalletApiOperation.GetTransactions, @@ -169,7 +176,7 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) { await withdrawalFinishedCond; - // Check balance + t.logStep("Check balance") const balResp = await walletClient.client.call( WalletApiOperation.GetBalances, diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-conversion.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-conversion.ts index 615feafa7..c55e1faf0 100644 --- a/packages/taler-harness/src/integrationtests/test-withdrawal-conversion.ts +++ b/packages/taler-harness/src/integrationtests/test-withdrawal-conversion.ts @@ -33,9 +33,11 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import * as http from "node:http"; import { defaultCoinConfig } from "../harness/denomStructures.js"; import { + BankService, ExchangeService, FakebankService, GlobalTestState, + HarnessExchangeBankAccount, MerchantService, generateRandomPayto, setupDb, @@ -135,7 +137,7 @@ export async function runWithdrawalConversionTest(t: GlobalTestState) { const db = await setupDb(t); - const bank = await FakebankService.create(t, { + const bank = await BankService.create(t, { allowRegistrations: true, currency: "TESTKUDOS", database: db.connStr, @@ -156,17 +158,40 @@ export async function runWithdrawalConversionTest(t: GlobalTestState) { database: db.connStr, }); - const exchangeBankAccount = await bank.createExchangeAccount( - "myexchange", - "x", - ); - exchangeBankAccount.conversionUrl = "http://localhost:8071/"; + let exchangeBankAccount: HarnessExchangeBankAccount = { + wireGatewayApiBaseUrl: new URL( + "accounts/myexchange/taler-wire-gateway/", + bank.corebankApiBaseUrl, + ).href, + accountName: "myexchange", + accountPassword: "x", + accountPaytoUri: generateRandomPayto("myexchange"), + conversionUrl: "http://localhost:8071/", + }; + await exchange.addBankAccount("1", exchangeBankAccount); await bank.start(); await bank.pingUntilAvailable(); + const bankClientAuth = { + username: "admin", + password: "adminpw", + }; + + const bankClient = new TalerCorebankApiClient(bank.corebankApiBaseUrl, { + auth: bankClientAuth, + }); + + await bankClient.registerAccountExtended({ + name: exchangeBankAccount.accountName, + username: exchangeBankAccount.accountName, + password: exchangeBankAccount.accountPassword, + is_taler_exchange: true, + payto_uri: exchangeBankAccount.accountPaytoUri, + }); + exchange.addOfferedCoins(defaultCoinConfig); await exchange.start(); @@ -194,7 +219,7 @@ export async function runWithdrawalConversionTest(t: GlobalTestState) { ), }); - const { walletClient, walletService } = await createWalletDaemonWithClient( + const { walletClient } = await createWalletDaemonWithClient( t, { name: "wallet" }, ); @@ -203,11 +228,7 @@ export async function runWithdrawalConversionTest(t: GlobalTestState) { // Create a withdrawal operation - const bankAccessApiClient = new TalerCorebankApiClient( - bank.corebankApiBaseUrl, - ); - - const user = await bankAccessApiClient.createRandomBankUser(); + const user = await bankClient.createRandomBankUser(); await walletClient.call(WalletApiOperation.AddExchange, { exchangeBaseUrl: exchange.baseUrl, @@ -277,10 +298,7 @@ export async function runWithdrawalConversionTest(t: GlobalTestState) { const wireGatewayApiClient = new WireGatewayApiClient( exchangeBankAccount.wireGatewayApiBaseUrl, { - auth: { - username: exchangeBankAccount.accountName, - password: exchangeBankAccount.accountPassword, - }, + auth: bankClientAuth, }, ); diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts index 1c65de7d9..0657d2da7 100644 --- a/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts +++ b/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts @@ -90,7 +90,10 @@ export async function runWithdrawalFeesTest(t: GlobalTestState) { await exchange.addBankAccount("1", { accountName: exchangeBankUsername, accountPassword: exchangeBankPassword, - wireGatewayApiBaseUrl: new URL("accounts/exchange/taler-wire-gateway/", bank.baseUrl).href, + wireGatewayApiBaseUrl: new URL( + "accounts/exchange/taler-wire-gateway/", + bank.baseUrl, + ).href, accountPaytoUri: exchangePaytoUri, }); @@ -133,12 +136,9 @@ export async function runWithdrawalFeesTest(t: GlobalTestState) { const user = await bankClient.createRandomBankUser(); bankClient.setAuth(user); - const wop = await bankClient.createWithdrawalOperation( - user.username, - amount, - ); + const wop = await bankClient.createWithdrawalOperation(user.username, amount); - // Hand it to the wallet + t.logStep("Hand it to the wallet") const details = await wallet.client.call( WalletApiOperation.GetWithdrawalDetailsForUri, @@ -149,10 +149,13 @@ export async function runWithdrawalFeesTest(t: GlobalTestState) { console.log(j2s(details)); + const myAmount = details.amount; + t.assertTrue(!!myAmount); + const amountDetails = await wallet.client.call( WalletApiOperation.GetWithdrawalDetailsForAmount, { - amount: details.amount, + amount: myAmount, exchangeBaseUrl: details.possibleExchanges[0].exchangeBaseUrl, }, ); @@ -162,23 +165,25 @@ export async function runWithdrawalFeesTest(t: GlobalTestState) { t.assertAmountEquals(amountDetails.amountEffective, "TESTKUDOS:5"); t.assertAmountEquals(amountDetails.amountRaw, "TESTKUDOS:7.5"); + t.logStep("Complete all pending operations") + await wallet.runPending(); - // Withdraw (AKA select) + t.logStep("Withdraw (AKA select)") await wallet.client.call(WalletApiOperation.AcceptBankIntegratedWithdrawal, { exchangeBaseUrl: exchange.baseUrl, talerWithdrawUri: wop.taler_withdraw_uri, }); - // Confirm it + t.logStep("Confirm it") await bankClient.confirmWithdrawalOperation(user.username, { withdrawalOperationId: wop.withdrawal_id, }); await wallet.runUntilDone(); - // Check balance + t.logStep("Check balance") const balResp = await wallet.client.call(WalletApiOperation.GetBalances, {}); console.log(j2s(balResp)); diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-flex.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-flex.ts new file mode 100644 index 000000000..ffc7249b8 --- /dev/null +++ b/packages/taler-harness/src/integrationtests/test-withdrawal-flex.ts @@ -0,0 +1,70 @@ +/* + 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 { j2s } from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { GlobalTestState } from "../harness/harness.js"; +import { createSimpleTestkudosEnvironmentV3 } from "../harness/helpers.js"; + +/** + * Run test for bank-integrated withdrawal with flexible amount, + * i.e. the amount is chosen by the wallet. + */ +export async function runWithdrawalFlexTest(t: GlobalTestState) { + // Set up test environment + + const { walletClient, bankClient, exchange } = + await createSimpleTestkudosEnvironmentV3(t); + + // Create a withdrawal operation + const user = await bankClient.createRandomBankUser(); + bankClient.setAuth(user); + const wop = await bankClient.createWithdrawalOperation( + user.username, + undefined, + ); + + const r1 = await walletClient.call( + WalletApiOperation.GetWithdrawalDetailsForUri, + { + talerWithdrawUri: wop.taler_withdraw_uri, + }, + ); + + console.log(j2s(r1)); + + // Withdraw + + const r2 = await walletClient.call( + WalletApiOperation.AcceptBankIntegratedWithdrawal, + { + exchangeBaseUrl: exchange.baseUrl, + talerWithdrawUri: wop.taler_withdraw_uri, + amount: "TESTKUDOS:10", + }, + ); + + await bankClient.confirmWithdrawalOperation(user.username, { + withdrawalOperationId: wop.withdrawal_id, + }); + + await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {}); +} + +runWithdrawalFlexTest.suites = ["wallet"]; diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts index eb2ae7fa6..4588310b1 100644 --- a/packages/taler-harness/src/integrationtests/testrunner.ts +++ b/packages/taler-harness/src/integrationtests/testrunner.ts @@ -113,14 +113,15 @@ import { runWalletRefreshTest } from "./test-wallet-refresh.js"; import { runWalletWirefeesTest } from "./test-wallet-wirefees.js"; import { runWallettestingTest } from "./test-wallettesting.js"; import { runWithdrawalAbortBankTest } from "./test-withdrawal-abort-bank.js"; +import { runWithdrawalAmountTest } from "./test-withdrawal-amount.js"; import { runWithdrawalBankIntegratedTest } from "./test-withdrawal-bank-integrated.js"; import { runWithdrawalConversionTest } from "./test-withdrawal-conversion.js"; import { runWithdrawalFakebankTest } from "./test-withdrawal-fakebank.js"; import { runWithdrawalFeesTest } from "./test-withdrawal-fees.js"; +import { runWithdrawalFlexTest } from "./test-withdrawal-flex.js"; import { runWithdrawalHandoverTest } from "./test-withdrawal-handover.js"; import { runWithdrawalHugeTest } from "./test-withdrawal-huge.js"; import { runWithdrawalManualTest } from "./test-withdrawal-manual.js"; -import { runWithdrawalAmountTest } from "./test-withdrawal-amount.js"; /** * Test runner. @@ -232,6 +233,7 @@ const allTests: TestMainFunction[] = [ runPeerPushLargeTest, runWithdrawalHandoverTest, runWithdrawalAmountTest, + runWithdrawalFlexTest, ]; export interface TestRunSpec { |