aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-cli
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2022-12-23 12:59:29 +0100
committerFlorian Dold <florian@dold.me>2022-12-23 13:19:41 +0100
commit083c4cf5d96314c44dd716cf3cc931e95b651bbd (patch)
tree7f15a46224d5dfe495e26dc6ec66996c889498ff /packages/taler-wallet-cli
parentd98711cb51d13bb2da3682014c7c6e75d7fbb4f0 (diff)
downloadwallet-core-083c4cf5d96314c44dd716cf3cc931e95b651bbd.tar.xz
spill extra functionality from wallet-cli into taler-harness
We want to keep taler-wallet-cli smaller and have fewer dependencies.
Diffstat (limited to 'packages/taler-wallet-cli')
-rw-r--r--packages/taler-wallet-cli/assets/.gitkeep0
-rwxr-xr-xpackages/taler-wallet-cli/build.mjs11
-rw-r--r--packages/taler-wallet-cli/package.json2
-rw-r--r--packages/taler-wallet-cli/src/assets.ts52
-rw-r--r--packages/taler-wallet-cli/src/bench1.ts189
-rw-r--r--packages/taler-wallet-cli/src/bench2.ts170
-rw-r--r--packages/taler-wallet-cli/src/bench3.ts205
-rw-r--r--packages/taler-wallet-cli/src/benchMerchantIDGenerator.ts83
-rw-r--r--packages/taler-wallet-cli/src/env-full.ts101
-rw-r--r--packages/taler-wallet-cli/src/env1.ts70
-rw-r--r--packages/taler-wallet-cli/src/harness/denomStructures.ts157
-rw-r--r--packages/taler-wallet-cli/src/harness/faultInjection.ts256
-rw-r--r--packages/taler-wallet-cli/src/harness/harness.ts2024
-rw-r--r--packages/taler-wallet-cli/src/harness/helpers.ts444
-rw-r--r--packages/taler-wallet-cli/src/harness/libeufin-apis.ts872
-rw-r--r--packages/taler-wallet-cli/src/harness/libeufin.ts910
-rw-r--r--packages/taler-wallet-cli/src/harness/merchantApiTypes.ts337
-rw-r--r--packages/taler-wallet-cli/src/harness/sync.ts119
-rw-r--r--packages/taler-wallet-cli/src/index.ts273
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/scenario-prompt-payment.ts60
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-merchant.ts201
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-mixed-merchant.ts116
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-peer.ts92
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts136
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-claim-loop.ts79
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-clause-schnorr.ts97
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-denom-unoffered.ts126
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-deposit.ts71
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-exchange-management.ts285
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-exchange-timetravel.ts240
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-fee-regression.ts200
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-forced-selection.ts87
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-bankaccount.ts109
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-bankconnection.ts56
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-facade-bad-request.ts71
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-facade.ts70
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-permissions.ts64
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-sandbox-camt.ts76
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-sandbox-transactions.ts69
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-scheduling.ts106
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-users.ts63
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-bad-gateway.ts74
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-basic.ts308
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-c5x.ts147
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-facade-anastasis.ts169
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-keyrotation.ts79
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-nexus-balance.ts118
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-refund-multiple-users.ts104
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-refund.ts101
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-sandbox-wire-transfer-cli.ts85
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-libeufin-tutorial.ts128
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-merchant-exchange-confusion.ts243
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-delete.ts129
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-urls.ts189
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-merchant-instances.ts184
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-merchant-longpolling.ts162
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-merchant-refund-api.ts303
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts620
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-pay-paid.ts222
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-payment-claim.ts110
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-payment-fault.ts222
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-payment-forgettable.ts81
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-payment-idempotency.ts121
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-payment-multiple.ts163
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-payment-on-demo.ts114
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-payment-transient.ts185
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-payment-zero.ts72
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-payment.ts77
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-paywall-flow.ts252
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-peer-to-peer-pull.ts101
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-peer-to-peer-push.ts119
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-refund-auto.ts105
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-refund-gone.ts124
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-refund-incremental.ts202
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-refund.ts106
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-revocation.ts215
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-timetravel-autorefresh.ts216
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-timetravel-withdraw.ts98
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-tipping.ts129
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-wallet-backup-basic.ts168
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-wallet-backup-doublespend.ts174
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-wallet-balance.ts144
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-wallet-cryptoworker.ts55
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-wallet-dbless.ts112
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-wallettesting.ts233
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-withdrawal-abort-bank.ts84
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-withdrawal-bank-integrated.ts91
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-withdrawal-fakebank.ts97
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-withdrawal-high.ts99
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/test-withdrawal-manual.ts84
-rw-r--r--packages/taler-wallet-cli/src/integrationtests/testrunner.ts496
-rw-r--r--packages/taler-wallet-cli/src/lint.ts534
92 files changed, 9 insertions, 17288 deletions
diff --git a/packages/taler-wallet-cli/assets/.gitkeep b/packages/taler-wallet-cli/assets/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
--- a/packages/taler-wallet-cli/assets/.gitkeep
+++ /dev/null
diff --git a/packages/taler-wallet-cli/build.mjs b/packages/taler-wallet-cli/build.mjs
index b6b3f4a16..14b626815 100755
--- a/packages/taler-wallet-cli/build.mjs
+++ b/packages/taler-wallet-cli/build.mjs
@@ -53,17 +53,15 @@ function git_hash() {
export const buildConfig = {
entryPoints: ["src/index.ts"],
- outfile: "dist/taler-wallet-cli.cjs",
+ outfile: "dist/taler-wallet-cli.mjs",
bundle: true,
minify: false,
target: [
- 'es6'
+ 'es2020'
],
- format: 'cjs',
- platform: 'node',
+ format: 'esm',
+ platform: 'neutral',
sourcemap: true,
- jsxFactory: 'h',
- jsxFragment: 'Fragment',
define: {
'__VERSION__': `"${_package.version}"`,
'__GIT_HASH__': `"${GIT_HASH}"`,
@@ -76,4 +74,3 @@ esbuild
console.log(e)
process.exit(1)
});
-
diff --git a/packages/taler-wallet-cli/package.json b/packages/taler-wallet-cli/package.json
index 455c5d0cb..8069cc5dd 100644
--- a/packages/taler-wallet-cli/package.json
+++ b/packages/taler-wallet-cli/package.json
@@ -35,7 +35,7 @@
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.3.0",
"@rollup/plugin-replace": "^4.0.0",
- "@types/node": "^18.8.5",
+ "@types/node": "^18.11.17",
"prettier": "^2.5.1",
"rimraf": "^3.0.2",
"rollup": "^2.79.0",
diff --git a/packages/taler-wallet-cli/src/assets.ts b/packages/taler-wallet-cli/src/assets.ts
deleted file mode 100644
index 8e9306780..000000000
--- a/packages/taler-wallet-cli/src/assets.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 path from "path";
-import fs from "fs";
-
-const assetFileUrl = import.meta.url;
-
-/**
- * Resolve an asset name into an absolute filename.
- *
- * The asset file should be placed in the "assets" directory
- * at the top level of the package (i.e. next to package.json).
- */
-export function resolveAsset(name: string): string {
- const n = path.basename(assetFileUrl);
- const d = path.dirname(assetFileUrl);
- let assetPath: string;
- // Currently both asset paths are the same.
- // This might change if the file that contains "resolveAsset"
- // ever moves. Thus, we're keeping the case distinction.
- if (n.endsWith("assets.js")) {
- // We're not bundled. Path is relative to the current file.
- assetPath = path.resolve(path.join(d, "..", "assets", name));
- } else if (n.endsWith("taler-wallet-cli.js")) {
- // We're bundled. Currently, this path is the same
- // FIXME: Take into account some ASSETS environment variable?
- assetPath = path.resolve(path.join(d, "..", "assets", name));
- } else {
- throw Error("Can't resolve asset (unknown)");
- }
- if (!fs.existsSync(assetPath)) {
- throw Error(`Asset '${name} not found'`);
- }
- return assetPath;
-}
diff --git a/packages/taler-wallet-cli/src/bench1.ts b/packages/taler-wallet-cli/src/bench1.ts
deleted file mode 100644
index 84786d25a..000000000
--- a/packages/taler-wallet-cli/src/bench1.ts
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 {
- buildCodecForObject,
- codecForNumber,
- codecForString,
- codecForBoolean,
- codecOptional,
- j2s,
- Logger,
-} from "@gnu-taler/taler-util";
-import {
- getDefaultNodeWallet2,
- NodeHttpLib,
- WalletApiOperation,
- Wallet,
- AccessStats,
-} from "@gnu-taler/taler-wallet-core";
-
-/**
- * Entry point for the benchmark.
- *
- * The benchmark runs against an existing Taler deployment and does not
- * set up its own services.
- */
-export async function runBench1(configJson: any): Promise<void> {
- const logger = new Logger("Bench1");
-
- // Validate the configuration file for this benchmark.
- const b1conf = codecForBench1Config().decode(configJson);
-
- const myHttpLib = new NodeHttpLib();
- myHttpLib.setThrottling(false);
-
- const numIter = b1conf.iterations ?? 1;
- const numDeposits = b1conf.deposits ?? 5;
- const restartWallet = b1conf.restartAfter ?? 20;
-
- const withdrawOnly = b1conf.withdrawOnly ?? false;
- const withdrawAmount = (numDeposits + 1) * 10;
-
- logger.info(
- `Starting Benchmark iterations=${numIter} deposits=${numDeposits}`,
- );
-
- const trustExchange = !!process.env["TALER_WALLET_INSECURE_TRUST_EXCHANGE"];
- if (trustExchange) {
- logger.info("trusting exchange (not validating signatures)");
- } else {
- logger.info("not trusting exchange (validating signatures)");
- }
- const batchWithdrawal = !!process.env["TALER_WALLET_BATCH_WITHDRAWAL"];
-
- let wallet = {} as Wallet;
- let getDbStats: () => AccessStats;
-
- for (let i = 0; i < numIter; i++) {
- // Create a new wallet in each iteration
- // otherwise the TPS go down
- // my assumption is that the in-memory db file gets too large
- if (i % restartWallet == 0) {
- if (Object.keys(wallet).length !== 0) {
- wallet.stop();
- console.log("wallet DB stats", j2s(getDbStats!()));
- }
-
- const res = await getDefaultNodeWallet2({
- // No persistent DB storage.
- persistentStoragePath: undefined,
- httpLib: myHttpLib,
- });
- wallet = res.wallet;
- getDbStats = res.getDbStats;
- if (trustExchange) {
- wallet.setInsecureTrustExchange();
- }
- wallet.setBatchWithdrawal(batchWithdrawal);
- await wallet.client.call(WalletApiOperation.InitWallet, {});
- }
-
- logger.trace(`Starting withdrawal amount=${withdrawAmount}`);
- let start = Date.now();
-
- await wallet.client.call(WalletApiOperation.WithdrawFakebank, {
- amount: b1conf.currency + ":" + withdrawAmount,
- bank: b1conf.bank,
- exchange: b1conf.exchange,
- });
-
- await wallet.runTaskLoop({
- stopWhenDone: true,
- });
-
- logger.info(
- `Finished withdrawal amount=${withdrawAmount} time=${Date.now() - start}`,
- );
-
- if (!withdrawOnly) {
- for (let i = 0; i < numDeposits; i++) {
- logger.trace(`Starting deposit amount=10`);
- start = Date.now();
-
- await wallet.client.call(WalletApiOperation.CreateDepositGroup, {
- amount: b1conf.currency + ":10",
- depositPaytoUri: b1conf.payto,
- });
-
- await wallet.runTaskLoop({
- stopWhenDone: true,
- });
-
- logger.info(`Finished deposit amount=10 time=${Date.now() - start}`);
- }
- }
- }
-
- wallet.stop();
- console.log("wallet DB stats", j2s(getDbStats!()));
-}
-
-/**
- * Format of the configuration file passed to the benchmark
- */
-interface Bench1Config {
- /**
- * Base URL of the bank.
- */
- bank: string;
-
- /**
- * Payto url for deposits.
- */
- payto: string;
-
- /**
- * Base URL of the exchange.
- */
- exchange: string;
-
- /**
- * How many withdraw/deposit iterations should be made?
- * Defaults to 1.
- */
- iterations?: number;
-
- currency: string;
-
- deposits?: number;
-
- /**
- * How any iterations run until the wallet db gets purged
- * Defaults to 20.
- */
- restartAfter?: number;
-
- withdrawOnly?: boolean;
-}
-
-/**
- * Schema validation codec for Bench1Config.
- */
-const codecForBench1Config = () =>
- buildCodecForObject<Bench1Config>()
- .property("bank", codecForString())
- .property("payto", codecForString())
- .property("exchange", codecForString())
- .property("iterations", codecOptional(codecForNumber()))
- .property("deposits", codecOptional(codecForNumber()))
- .property("currency", codecForString())
- .property("restartAfter", codecOptional(codecForNumber()))
- .property("withdrawOnly", codecOptional(codecForBoolean()))
- .build("Bench1Config");
diff --git a/packages/taler-wallet-cli/src/bench2.ts b/packages/taler-wallet-cli/src/bench2.ts
deleted file mode 100644
index 196737436..000000000
--- a/packages/taler-wallet-cli/src/bench2.ts
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022 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 {
- buildCodecForObject,
- codecForNumber,
- codecForString,
- codecOptional,
- Logger,
-} from "@gnu-taler/taler-util";
-import {
- checkReserve,
- createFakebankReserve,
- CryptoDispatcher,
- depositCoin,
- downloadExchangeInfo,
- findDenomOrThrow,
- NodeHttpLib,
- refreshCoin,
- SynchronousCryptoWorkerFactoryNode,
- withdrawCoin,
-} from "@gnu-taler/taler-wallet-core";
-
-/**
- * Entry point for the benchmark.
- *
- * The benchmark runs against an existing Taler deployment and does not
- * set up its own services.
- */
-export async function runBench2(configJson: any): Promise<void> {
- const logger = new Logger("Bench2");
-
- // Validate the configuration file for this benchmark.
- const benchConf = codecForBench2Config().decode(configJson);
- const curr = benchConf.currency;
- const cryptoDisp = new CryptoDispatcher(new SynchronousCryptoWorkerFactoryNode());
- const cryptoApi = cryptoDisp.cryptoApi;
-
- const http = new NodeHttpLib();
- http.setThrottling(false);
-
- const numIter = benchConf.iterations ?? 1;
- const numDeposits = benchConf.deposits ?? 5;
-
- const reserveAmount = (numDeposits + 1) * 10;
-
- for (let i = 0; i < numIter; i++) {
- const exchangeInfo = await downloadExchangeInfo(benchConf.exchange, http);
-
- const reserveKeyPair = await cryptoApi.createEddsaKeypair({});
-
- console.log("creating fakebank reserve");
-
- await createFakebankReserve({
- amount: `${curr}:${reserveAmount}`,
- exchangeInfo,
- fakebankBaseUrl: benchConf.bank,
- http,
- reservePub: reserveKeyPair.pub,
- });
-
- console.log("waiting for reserve");
-
- await checkReserve(http, benchConf.exchange, reserveKeyPair.pub);
-
- console.log("reserve found");
-
- const d1 = findDenomOrThrow(exchangeInfo, `${curr}:8`);
-
- for (let j = 0; j < numDeposits; j++) {
- console.log("withdrawing coin");
- const coin = await withdrawCoin({
- http,
- cryptoApi,
- reserveKeyPair: {
- reservePriv: reserveKeyPair.priv,
- reservePub: reserveKeyPair.pub,
- },
- denom: d1,
- exchangeBaseUrl: benchConf.exchange,
- });
-
- console.log("depositing coin");
-
- await depositCoin({
- amount: `${curr}:4`,
- coin: coin,
- cryptoApi,
- exchangeBaseUrl: benchConf.exchange,
- http,
- depositPayto: benchConf.payto,
- });
-
- const refreshDenoms = [
- findDenomOrThrow(exchangeInfo, `${curr}:1`),
- findDenomOrThrow(exchangeInfo, `${curr}:1`),
- ];
-
- console.log("refreshing coin");
-
- await refreshCoin({
- oldCoin: coin,
- cryptoApi,
- http,
- newDenoms: refreshDenoms,
- });
-
- console.log("refresh done");
- }
- }
-}
-
-/**
- * Format of the configuration file passed to the benchmark
- */
-interface Bench2Config {
- /**
- * Base URL of the bank.
- */
- bank: string;
-
- /**
- * Payto url for deposits.
- */
- payto: string;
-
- /**
- * Base URL of the exchange.
- */
- exchange: string;
-
- /**
- * How many withdraw/deposit iterations should be made?
- * Defaults to 1.
- */
- iterations?: number;
-
- currency: string;
-
- deposits?: number;
-}
-
-/**
- * Schema validation codec for Bench1Config.
- */
-const codecForBench2Config = () =>
- buildCodecForObject<Bench2Config>()
- .property("bank", codecForString())
- .property("payto", codecForString())
- .property("exchange", codecForString())
- .property("iterations", codecOptional(codecForNumber()))
- .property("deposits", codecOptional(codecForNumber()))
- .property("currency", codecForString())
- .build("Bench2Config");
diff --git a/packages/taler-wallet-cli/src/bench3.ts b/packages/taler-wallet-cli/src/bench3.ts
deleted file mode 100644
index 6041c525c..000000000
--- a/packages/taler-wallet-cli/src/bench3.ts
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 {
- buildCodecForObject,
- codecForNumber,
- codecForString,
- codecOptional,
- j2s,
- Logger,
-} from "@gnu-taler/taler-util";
-import {
- getDefaultNodeWallet2,
- NodeHttpLib,
- WalletApiOperation,
- Wallet,
- AccessStats,
-} from "@gnu-taler/taler-wallet-core";
-import benchMerchantIDGenerator from "./benchMerchantIDGenerator.js";
-
-/**
- * Entry point for the benchmark.
- *
- * The benchmark runs against an existing Taler deployment and does not
- * set up its own services.
- */
-export async function runBench3(configJson: any): Promise<void> {
- const logger = new Logger("Bench3");
-
- // Validate the configuration file for this benchmark.
- const b3conf = codecForBench3Config().decode(configJson);
-
- if (!b3conf.paytoTemplate.includes("${id")) {
- throw new Error("Payto template url must contain '${id}' placeholder");
- }
-
- const myHttpLib = new NodeHttpLib();
- myHttpLib.setThrottling(false);
-
- const numIter = b3conf.iterations ?? 1;
- const numDeposits = b3conf.deposits ?? 5;
- const restartWallet = b3conf.restartAfter ?? 20;
-
- const withdrawAmount = (numDeposits + 1) * 10;
-
- const IDGenerator = benchMerchantIDGenerator(b3conf.randomAlg, b3conf.numMerchants ?? 100);
-
- logger.info(
- `Starting Benchmark iterations=${numIter} deposits=${numDeposits} with ${b3conf.randomAlg} merchant selection`,
- );
-
- const trustExchange = !!process.env["TALER_WALLET_INSECURE_TRUST_EXCHANGE"];
- if (trustExchange) {
- logger.info("trusting exchange (not validating signatures)");
- } else {
- logger.info("not trusting exchange (validating signatures)");
- }
- const batchWithdrawal = !!process.env["TALER_WALLET_BATCH_WITHDRAWAL"];
-
- let wallet = {} as Wallet;
- let getDbStats: () => AccessStats;
-
- for (let i = 0; i < numIter; i++) {
- // Create a new wallet in each iteration
- // otherwise the TPS go down
- // my assumption is that the in-memory db file gets too large
- if (i % restartWallet == 0) {
- if (Object.keys(wallet).length !== 0) {
- wallet.stop();
- console.log("wallet DB stats", j2s(getDbStats!()));
- }
-
- const res = await getDefaultNodeWallet2({
- // No persistent DB storage.
- persistentStoragePath: undefined,
- httpLib: myHttpLib,
- });
- wallet = res.wallet;
- getDbStats = res.getDbStats;
- if (trustExchange) {
- wallet.setInsecureTrustExchange();
- }
- wallet.setBatchWithdrawal(batchWithdrawal);
- await wallet.client.call(WalletApiOperation.InitWallet, {});
- }
-
- logger.trace(`Starting withdrawal amount=${withdrawAmount}`);
- let start = Date.now();
-
- await wallet.client.call(WalletApiOperation.WithdrawFakebank, {
- amount: b3conf.currency + ":" + withdrawAmount,
- bank: b3conf.bank,
- exchange: b3conf.exchange,
- });
-
- await wallet.runTaskLoop({
- stopWhenDone: true,
- });
-
- logger.info(
- `Finished withdrawal amount=${withdrawAmount} time=${Date.now() - start}`,
- );
-
- for (let i = 0; i < numDeposits; i++) {
- logger.trace(`Starting deposit amount=10`);
- start = Date.now();
-
- let merchID = IDGenerator.getRandomMerchantID();
- let payto = b3conf.paytoTemplate.replace("${id}", merchID.toString());
-
- await wallet.client.call(WalletApiOperation.CreateDepositGroup, {
- amount: b3conf.currency + ":10",
- depositPaytoUri: payto,
- });
-
- await wallet.runTaskLoop({
- stopWhenDone: true,
- });
-
- logger.info(`Finished deposit amount=10 time=${Date.now() - start}`);
- }
- }
-
- wallet.stop();
- console.log("wallet DB stats", j2s(getDbStats!()));
-}
-
-/**
- * Format of the configuration file passed to the benchmark
- */
-interface Bench3Config {
- /**
- * Base URL of the bank.
- */
- bank: string;
-
- /**
- * Payto url template for deposits, must contain '${id}' for replacements.
- */
- paytoTemplate: string;
-
- /**
- * Base URL of the exchange.
- */
- exchange: string;
-
- /**
- * How many withdraw/deposit iterations should be made?
- * Defaults to 1.
- */
- iterations?: number;
-
- currency: string;
-
- deposits?: number;
-
- /**
- * How any iterations run until the wallet db gets purged
- * Defaults to 20.
- */
- restartAfter?: number;
-
- /**
- * Number of merchants to select from randomly
- */
- numMerchants?: number;
-
- /**
- * Which random generator to use.
- * Possible values: 'zipf', 'rand'
- */
- randomAlg: string;
-}
-
-/**
- * Schema validation codec for Bench1Config.
- */
-const codecForBench3Config = () =>
- buildCodecForObject<Bench3Config>()
- .property("bank", codecForString())
- .property("paytoTemplate", codecForString())
- .property("numMerchants", codecOptional(codecForNumber()))
- .property("randomAlg", codecForString())
- .property("exchange", codecForString())
- .property("iterations", codecOptional(codecForNumber()))
- .property("deposits", codecOptional(codecForNumber()))
- .property("currency", codecForString())
- .property("restartAfter", codecOptional(codecForNumber()))
- .build("Bench1Config");
diff --git a/packages/taler-wallet-cli/src/benchMerchantIDGenerator.ts b/packages/taler-wallet-cli/src/benchMerchantIDGenerator.ts
deleted file mode 100644
index b83c12bb8..000000000
--- a/packages/taler-wallet-cli/src/benchMerchantIDGenerator.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022 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/>
-
- @author: Boss Marco
- */
-
-const getRandomInt = function(max: number) {
- return Math.floor(Math.random() * max);
-}
-
-abstract class BenchMerchantIDGenerator {
- abstract getRandomMerchantID(): number
-}
-
-class ZipfGenerator extends BenchMerchantIDGenerator {
-
- weights: number[];
- total_weight: number;
-
- constructor(numMerchants: number) {
- super();
- this.weights = new Array<number>(numMerchants);
- for (var i = 0; i < this.weights.length; i++) {
- /* we use integers (floor), make sure we have big enough values
- * by multiplying with
- * numMerchants again */
- this.weights[i] = Math.floor((numMerchants/(i+1)) * numMerchants);
- }
- this.total_weight = this.weights.reduce((p, n) => p + n);
- }
-
- getRandomMerchantID(): number {
- let random = getRandomInt(this.total_weight);
- let current = 0;
-
- for (var i = 0; i < this.weights.length; i++) {
- current += this.weights[i];
- if (random <= current) {
- return i+1;
- }
- }
-
- /* should never come here */
- return getRandomInt(this.weights.length);
- }
-}
-
-class RandomGenerator extends BenchMerchantIDGenerator {
-
- max: number
-
- constructor(numMerchants: number) {
- super();
- this.max = numMerchants
- }
-
- getRandomMerchantID() {
- return getRandomInt(this.max);
- }
-}
-
-export default function(type: string, maxID: number): BenchMerchantIDGenerator {
- switch (type) {
- case "zipf":
- return new ZipfGenerator(maxID);
- case "rand":
- return new RandomGenerator(maxID);
- default:
- throw new Error("Valid types are 'zipf' and 'rand'");
- }
-}
diff --git a/packages/taler-wallet-cli/src/env-full.ts b/packages/taler-wallet-cli/src/env-full.ts
deleted file mode 100644
index 3a684db0b..000000000
--- a/packages/taler-wallet-cli/src/env-full.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 { Duration, j2s, URL } from "@gnu-taler/taler-util";
-import { CoinConfig, defaultCoinConfig } from "./harness/denomStructures.js";
-import {
- GlobalTestState,
- setupDb,
- ExchangeService,
- FakebankService,
- MerchantService,
- getPayto,
-} from "./harness/harness.js";
-
-/**
- * Entry point for the full Taler test environment.
- */
-export async function runEnvFull(t: GlobalTestState): Promise<void> {
- 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",
- );
- console.log("exchange bank account", j2s(exchangeBankAccount));
- 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();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- defaultWireTransferDelay: Duration.toTalerProtocolDuration(
- Duration.fromSpec({ minutes: 1 }),
- ),
- });
-
- await merchant.addInstance({
- id: "minst1",
- name: "minst1",
- paytoUris: [getPayto("minst1")],
- defaultWireTransferDelay: Duration.toTalerProtocolDuration(
- Duration.fromSpec({ minutes: 1 }),
- ),
- });
-
- console.log("setup done!");
-}
diff --git a/packages/taler-wallet-cli/src/env1.ts b/packages/taler-wallet-cli/src/env1.ts
deleted file mode 100644
index aec0b7b8f..000000000
--- a/packages/taler-wallet-cli/src/env1.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 { URL } from "@gnu-taler/taler-util";
-import { CoinConfig, defaultCoinConfig } from "./harness/denomStructures.js";
-import {
- GlobalTestState,
- setupDb,
- ExchangeService,
- FakebankService,
-} from "./harness/harness.js";
-
-/**
- * Entry point for the benchmark.
- *
- * The benchmark runs against an existing Taler deployment and does not
- * set up its own services.
- */
-export async function runEnv1(t: GlobalTestState): Promise<void> {
- const db = await setupDb(t);
-
- const bank = await FakebankService.create(t, {
- currency: "TESTKUDOS",
- httpPort: 8082,
- allowRegistrations: true,
- database: db.connStr,
- });
-
- const exchange = ExchangeService.create(t, {
- name: "testexchange-1",
- currency: "TESTKUDOS",
- httpPort: 8081,
- database: db.connStr,
- });
-
- exchange.addBankAccount("1", {
- accountName: "exchange",
- accountPassword: "x",
- wireGatewayApiBaseUrl: new URL("/exchange/", bank.baseUrl).href,
- accountPaytoUri: "payto://x-taler-bank/localhost/exchange",
- });
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- const coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS"));
- exchange.addCoinConfigList(coinConfig);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- console.log("setup done!");
-}
diff --git a/packages/taler-wallet-cli/src/harness/denomStructures.ts b/packages/taler-wallet-cli/src/harness/denomStructures.ts
deleted file mode 100644
index b12857c7e..000000000
--- a/packages/taler-wallet-cli/src/harness/denomStructures.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- 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/>
- */
-
-export interface CoinCoinfigCommon {
- name: string;
- value: string;
- durationWithdraw: string;
- durationSpend: string;
- durationLegal: string;
- feeWithdraw: string;
- feeDeposit: string;
- feeRefresh: string;
- feeRefund: string;
- ageRestricted?: boolean;
-}
-
-export interface CoinConfigRsa extends CoinCoinfigCommon {
- cipher: "RSA";
- rsaKeySize: number;
-}
-
-/**
- * Clause Schnorr coin config.
- */
-export interface CoinConfigCs extends CoinCoinfigCommon {
- cipher: "CS";
-}
-
-export type CoinConfig = CoinConfigRsa | CoinConfigCs;
-
-const coinRsaCommon = {
- cipher: "RSA" as const,
- durationLegal: "3 years",
- durationSpend: "2 years",
- durationWithdraw: "7 days",
- rsaKeySize: 1024,
-};
-
-export const coin_ct1 = (curr: string): CoinConfig => ({
- ...coinRsaCommon,
- name: `${curr}_ct1`,
- value: `${curr}:0.01`,
- feeDeposit: `${curr}:0.00`,
- feeRefresh: `${curr}:0.01`,
- feeRefund: `${curr}:0.00`,
- feeWithdraw: `${curr}:0.01`,
-});
-
-export const coin_ct10 = (curr: string): CoinConfig => ({
- ...coinRsaCommon,
- name: `${curr}_ct10`,
- value: `${curr}:0.10`,
- feeDeposit: `${curr}:0.01`,
- feeRefresh: `${curr}:0.01`,
- feeRefund: `${curr}:0.00`,
- feeWithdraw: `${curr}:0.01`,
-});
-
-export const coin_u1 = (curr: string): CoinConfig => ({
- ...coinRsaCommon,
- name: `${curr}_u1`,
- value: `${curr}:1`,
- feeDeposit: `${curr}:0.02`,
- feeRefresh: `${curr}:0.02`,
- feeRefund: `${curr}:0.02`,
- feeWithdraw: `${curr}:0.02`,
-});
-
-export const coin_u2 = (curr: string): CoinConfig => ({
- ...coinRsaCommon,
- name: `${curr}_u2`,
- value: `${curr}:2`,
- feeDeposit: `${curr}:0.02`,
- feeRefresh: `${curr}:0.02`,
- feeRefund: `${curr}:0.02`,
- feeWithdraw: `${curr}:0.02`,
-});
-
-export const coin_u4 = (curr: string): CoinConfig => ({
- ...coinRsaCommon,
- name: `${curr}_u4`,
- value: `${curr}:4`,
- feeDeposit: `${curr}:0.02`,
- feeRefresh: `${curr}:0.02`,
- feeRefund: `${curr}:0.02`,
- feeWithdraw: `${curr}:0.02`,
-});
-
-export const coin_u8 = (curr: string): CoinConfig => ({
- ...coinRsaCommon,
- name: `${curr}_u8`,
- value: `${curr}:8`,
- feeDeposit: `${curr}:0.16`,
- feeRefresh: `${curr}:0.16`,
- feeRefund: `${curr}:0.16`,
- feeWithdraw: `${curr}:0.16`,
-});
-
-const coin_u10 = (curr: string): CoinConfig => ({
- ...coinRsaCommon,
- name: `${curr}_u10`,
- value: `${curr}:10`,
- feeDeposit: `${curr}:0.2`,
- feeRefresh: `${curr}:0.2`,
- feeRefund: `${curr}:0.2`,
- feeWithdraw: `${curr}:0.2`,
-});
-
-export const defaultCoinConfig = [
- coin_ct1,
- coin_ct10,
- coin_u1,
- coin_u2,
- coin_u4,
- coin_u8,
- coin_u10,
-];
-
-export function makeNoFeeCoinConfig(curr: string): CoinConfig[] {
- const cc: CoinConfig[] = [];
-
- for (let i = 0; i < 16; i++) {
- const ct = 2 ** i;
-
- const unit = Math.floor(ct / 100);
- const cent = ct % 100;
-
- cc.push({
- cipher: "RSA",
- durationLegal: "3 years",
- durationSpend: "2 years",
- durationWithdraw: "7 days",
- rsaKeySize: 1024,
- name: `${curr}-u${i}`,
- feeDeposit: `${curr}:0`,
- feeRefresh: `${curr}:0`,
- feeRefund: `${curr}:0`,
- feeWithdraw: `${curr}:0`,
- value: `${curr}:${unit}.${cent}`,
- });
- }
-
- return cc;
-}
diff --git a/packages/taler-wallet-cli/src/harness/faultInjection.ts b/packages/taler-wallet-cli/src/harness/faultInjection.ts
deleted file mode 100644
index 4c3d0c123..000000000
--- a/packages/taler-wallet-cli/src/harness/faultInjection.ts
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- 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/>
- */
-
-/**
- * Fault injection proxy.
- *
- * @author Florian Dold <dold@taler.net>
- */
-
-/**
- * Imports
- */
-import * as http from "http";
-import { URL } from "url";
-import {
- GlobalTestState,
- ExchangeService,
- ExchangeServiceInterface,
- MerchantServiceInterface,
- MerchantService,
-} from "../harness/harness.js";
-
-export interface FaultProxyConfig {
- inboundPort: number;
- targetPort: number;
-}
-
-/**
- * Fault injection context. Modified by fault injection functions.
- */
-export interface FaultInjectionRequestContext {
- requestUrl: string;
- method: string;
- requestHeaders: Record<string, string | string[] | undefined>;
- requestBody?: Buffer;
- dropRequest: boolean;
-}
-
-export interface FaultInjectionResponseContext {
- request: FaultInjectionRequestContext;
- statusCode: number;
- responseHeaders: Record<string, string | string[] | undefined>;
- responseBody: Buffer | undefined;
- dropResponse: boolean;
-}
-
-export interface FaultSpec {
- modifyRequest?: (ctx: FaultInjectionRequestContext) => Promise<void>;
- modifyResponse?: (ctx: FaultInjectionResponseContext) => Promise<void>;
-}
-
-export class FaultProxy {
- constructor(
- private globalTestState: GlobalTestState,
- private faultProxyConfig: FaultProxyConfig,
- ) {}
-
- private currentFaultSpecs: FaultSpec[] = [];
-
- start() {
- const server = http.createServer((req, res) => {
- const requestChunks: Buffer[] = [];
- const requestUrl = `http://localhost:${this.faultProxyConfig.inboundPort}${req.url}`;
- console.log("request for", new URL(requestUrl));
- req.on("data", (chunk) => {
- requestChunks.push(chunk);
- });
- req.on("end", async () => {
- console.log("end of data");
- let requestBuffer: Buffer | undefined;
- if (requestChunks.length > 0) {
- requestBuffer = Buffer.concat(requestChunks);
- }
- console.log("full request body", requestBuffer);
-
- const faultReqContext: FaultInjectionRequestContext = {
- dropRequest: false,
- method: req.method!!,
- requestHeaders: req.headers,
- requestUrl,
- requestBody: requestBuffer,
- };
-
- for (const faultSpec of this.currentFaultSpecs) {
- if (faultSpec.modifyRequest) {
- await faultSpec.modifyRequest(faultReqContext);
- }
- }
-
- if (faultReqContext.dropRequest) {
- res.destroy();
- return;
- }
-
- const faultedUrl = new URL(faultReqContext.requestUrl);
-
- const proxyRequest = http.request({
- method: faultReqContext.method,
- host: "localhost",
- port: this.faultProxyConfig.targetPort,
- path: faultedUrl.pathname + faultedUrl.search,
- headers: faultReqContext.requestHeaders,
- });
-
- console.log(
- `proxying request to target path '${
- faultedUrl.pathname + faultedUrl.search
- }'`,
- );
-
- if (faultReqContext.requestBody) {
- proxyRequest.write(faultReqContext.requestBody);
- }
- proxyRequest.end();
- proxyRequest.on("response", (proxyResp) => {
- console.log("gotten response from target", proxyResp.statusCode);
- const respChunks: Buffer[] = [];
- proxyResp.on("data", (proxyRespData) => {
- respChunks.push(proxyRespData);
- });
- proxyResp.on("end", async () => {
- console.log("end of target response");
- let responseBuffer: Buffer | undefined;
- if (respChunks.length > 0) {
- responseBuffer = Buffer.concat(respChunks);
- }
- const faultRespContext: FaultInjectionResponseContext = {
- request: faultReqContext,
- dropResponse: false,
- responseBody: responseBuffer,
- responseHeaders: proxyResp.headers,
- statusCode: proxyResp.statusCode!!,
- };
- for (const faultSpec of this.currentFaultSpecs) {
- const modResponse = faultSpec.modifyResponse;
- if (modResponse) {
- await modResponse(faultRespContext);
- }
- }
- if (faultRespContext.dropResponse) {
- req.destroy();
- return;
- }
- if (faultRespContext.responseBody) {
- // We must accommodate for potentially changed content length
- faultRespContext.responseHeaders[
- "content-length"
- ] = `${faultRespContext.responseBody.byteLength}`;
- }
- console.log("writing response head");
- res.writeHead(
- faultRespContext.statusCode,
- http.STATUS_CODES[faultRespContext.statusCode],
- faultRespContext.responseHeaders,
- );
- if (faultRespContext.responseBody) {
- res.write(faultRespContext.responseBody);
- }
- res.end();
- });
- });
- });
- });
-
- server.listen(this.faultProxyConfig.inboundPort);
- this.globalTestState.servers.push(server);
- }
-
- addFault(f: FaultSpec) {
- this.currentFaultSpecs.push(f);
- }
-
- clearAllFaults() {
- this.currentFaultSpecs = [];
- }
-}
-
-export class FaultInjectedExchangeService implements ExchangeServiceInterface {
- baseUrl: string;
- port: number;
- faultProxy: FaultProxy;
-
- get name(): string {
- return this.innerExchange.name;
- }
-
- get masterPub(): string {
- return this.innerExchange.masterPub;
- }
-
- private innerExchange: ExchangeService;
-
- constructor(
- t: GlobalTestState,
- e: ExchangeService,
- proxyInboundPort: number,
- ) {
- this.innerExchange = e;
- this.faultProxy = new FaultProxy(t, {
- inboundPort: proxyInboundPort,
- targetPort: e.port,
- });
- this.faultProxy.start();
-
- const exchangeUrl = new URL(e.baseUrl);
- exchangeUrl.port = `${proxyInboundPort}`;
- this.baseUrl = exchangeUrl.href;
- this.port = proxyInboundPort;
- }
-}
-
-export class FaultInjectedMerchantService implements MerchantServiceInterface {
- baseUrl: string;
- port: number;
- faultProxy: FaultProxy;
-
- get name(): string {
- return this.innerMerchant.name;
- }
-
- private innerMerchant: MerchantService;
- private inboundPort: number;
-
- constructor(
- t: GlobalTestState,
- m: MerchantService,
- proxyInboundPort: number,
- ) {
- this.innerMerchant = m;
- this.faultProxy = new FaultProxy(t, {
- inboundPort: proxyInboundPort,
- targetPort: m.port,
- });
- this.faultProxy.start();
- this.inboundPort = proxyInboundPort;
- }
-
- makeInstanceBaseUrl(instanceName?: string | undefined): string {
- const url = new URL(this.innerMerchant.makeInstanceBaseUrl(instanceName));
- url.port = `${this.inboundPort}`;
- return url.href;
- }
-}
diff --git a/packages/taler-wallet-cli/src/harness/harness.ts b/packages/taler-wallet-cli/src/harness/harness.ts
deleted file mode 100644
index 6f722dc8d..000000000
--- a/packages/taler-wallet-cli/src/harness/harness.ts
+++ /dev/null
@@ -1,2024 +0,0 @@
-/*
- 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/>
- */
-
-/**
- * Test harness for various GNU Taler components.
- * Also provides a fault-injection proxy.
- *
- * @author Florian Dold <dold@taler.net>
- */
-
-const logger = new Logger("harness.ts");
-
-/**
- * Imports
- */
-import {
- AmountJson,
- Amounts,
- AmountString,
- Configuration,
- CoreApiResponse,
- createEddsaKeyPair,
- Duration,
- eddsaGetPublic,
- EddsaKeyPair,
- encodeCrock,
- hash,
- j2s,
- Logger,
- parsePaytoUri,
- stringToBytes,
- TalerProtocolDuration,
-} from "@gnu-taler/taler-util";
-import {
- BankAccessApi,
- BankApi,
- BankServiceHandle,
- HarnessExchangeBankAccount,
- NodeHttpLib,
- openPromise,
- TalerError,
- WalletCoreApiClient,
-} from "@gnu-taler/taler-wallet-core";
-import { deepStrictEqual } from "assert";
-import axiosImp, { AxiosError } from "axios";
-import { ChildProcess, spawn } from "child_process";
-import * as child_process from "child_process";
-import * as fs from "fs";
-import * as http from "http";
-import * as path from "path";
-import * as readline from "readline";
-import { URL } from "url";
-import * as util from "util";
-import { CoinConfig } from "./denomStructures.js";
-import { LibeufinNexusApi, LibeufinSandboxApi } from "./libeufin-apis.js";
-import {
- codecForMerchantOrderPrivateStatusResponse,
- codecForPostOrderResponse,
- MerchantInstancesResponse,
- MerchantOrderPrivateStatusResponse,
- PostOrderRequest,
- PostOrderResponse,
- TipCreateConfirmation,
- TipCreateRequest,
- TippingReserveStatus,
-} from "./merchantApiTypes.js";
-
-const exec = util.promisify(child_process.exec);
-
-const axios = axiosImp.default;
-
-export async function delayMs(ms: number): Promise<void> {
- return new Promise((resolve, reject) => {
- setTimeout(() => resolve(), ms);
- });
-}
-
-export interface WithAuthorization {
- Authorization?: string;
-}
-
-interface WaitResult {
- code: number | null;
- signal: NodeJS.Signals | null;
-}
-
-/**
- * Run a shell command, return stdout.
- */
-export async function sh(
- t: GlobalTestState,
- logName: string,
- command: string,
- env: { [index: string]: string | undefined } = process.env,
-): Promise<string> {
- logger.info(`running command ${command}`);
- return new Promise((resolve, reject) => {
- const stdoutChunks: Buffer[] = [];
- const proc = spawn(command, {
- stdio: ["inherit", "pipe", "pipe"],
- shell: true,
- env: env,
- });
- proc.stdout.on("data", (x) => {
- if (x instanceof Buffer) {
- stdoutChunks.push(x);
- } else {
- throw Error("unexpected data chunk type");
- }
- });
- const stderrLogFileName = path.join(t.testDir, `${logName}-stderr.log`);
- const stderrLog = fs.createWriteStream(stderrLogFileName, {
- flags: "a",
- });
- proc.stderr.pipe(stderrLog);
- proc.on("exit", (code, signal) => {
- logger.info(`child process exited (${code} / ${signal})`);
- if (code != 0) {
- reject(Error(`Unexpected exit code ${code} for '${command}'`));
- return;
- }
- const b = Buffer.concat(stdoutChunks).toString("utf-8");
- resolve(b);
- });
- proc.on("error", () => {
- reject(Error("Child process had error"));
- });
- });
-}
-
-function shellescape(args: string[]) {
- const ret = args.map((s) => {
- if (/[^A-Za-z0-9_\/:=-]/.test(s)) {
- s = "'" + s.replace(/'/g, "'\\''") + "'";
- s = s.replace(/^(?:'')+/g, "").replace(/\\'''/g, "\\'");
- }
- return s;
- });
- return ret.join(" ");
-}
-
-/**
- * Run a shell command, return stdout.
- *
- * Log stderr to a log file.
- */
-export async function runCommand(
- t: GlobalTestState,
- logName: string,
- command: string,
- args: string[],
- env: { [index: string]: string | undefined } = process.env,
-): Promise<string> {
- logger.info(`running command ${shellescape([command, ...args])}`);
- return new Promise((resolve, reject) => {
- const stdoutChunks: Buffer[] = [];
- const proc = spawn(command, args, {
- stdio: ["inherit", "pipe", "pipe"],
- shell: false,
- env: env,
- });
- proc.stdout.on("data", (x) => {
- if (x instanceof Buffer) {
- stdoutChunks.push(x);
- } else {
- throw Error("unexpected data chunk type");
- }
- });
- const stderrLogFileName = path.join(t.testDir, `${logName}-stderr.log`);
- const stderrLog = fs.createWriteStream(stderrLogFileName, {
- flags: "a",
- });
- proc.stderr.pipe(stderrLog);
- proc.on("exit", (code, signal) => {
- logger.info(`child process exited (${code} / ${signal})`);
- if (code != 0) {
- reject(Error(`Unexpected exit code ${code} for '${command}'`));
- return;
- }
- const b = Buffer.concat(stdoutChunks).toString("utf-8");
- resolve(b);
- });
- proc.on("error", () => {
- reject(Error("Child process had error"));
- });
- });
-}
-
-export class ProcessWrapper {
- private waitPromise: Promise<WaitResult>;
- constructor(public proc: ChildProcess) {
- this.waitPromise = new Promise((resolve, reject) => {
- proc.on("exit", (code, signal) => {
- resolve({ code, signal });
- });
- proc.on("error", (err) => {
- reject(err);
- });
- });
- }
-
- wait(): Promise<WaitResult> {
- return this.waitPromise;
- }
-}
-
-export class GlobalTestParams {
- testDir: string;
-}
-
-export class GlobalTestState {
- testDir: string;
- procs: ProcessWrapper[];
- servers: http.Server[];
- inShutdown: boolean = false;
- constructor(params: GlobalTestParams) {
- this.testDir = params.testDir;
- this.procs = [];
- this.servers = [];
- }
-
- async assertThrowsTalerErrorAsync(
- block: () => Promise<void>,
- ): Promise<TalerError> {
- try {
- await block();
- } catch (e) {
- if (e instanceof TalerError) {
- return e;
- }
- throw Error(`expected TalerError to be thrown, but got ${e}`);
- }
- throw Error(
- `expected TalerError to be thrown, but block finished without throwing`,
- );
- }
-
- async assertThrowsAsync(block: () => Promise<void>): Promise<any> {
- try {
- await block();
- } catch (e) {
- return e;
- }
- throw Error(
- `expected exception to be thrown, but block finished without throwing`,
- );
- }
-
- assertAxiosError(e: any): asserts e is AxiosError {
- if (!e.isAxiosError) {
- throw Error("expected axios error");
- }
- }
-
- assertTrue(b: boolean): asserts b {
- if (!b) {
- throw Error("test assertion failed");
- }
- }
-
- assertDeepEqual<T>(actual: any, expected: T): asserts actual is T {
- deepStrictEqual(actual, expected);
- }
-
- assertAmountEquals(
- amtActual: string | AmountJson,
- amtExpected: string | AmountJson,
- ): void {
- if (Amounts.cmp(amtActual, amtExpected) != 0) {
- throw Error(
- `test assertion failed: expected ${Amounts.stringify(
- amtExpected,
- )} but got ${Amounts.stringify(amtActual)}`,
- );
- }
- }
-
- assertAmountLeq(a: string | AmountJson, b: string | AmountJson): void {
- if (Amounts.cmp(a, b) > 0) {
- throw Error(
- `test assertion failed: expected ${Amounts.stringify(
- a,
- )} to be less or equal (leq) than ${Amounts.stringify(b)}`,
- );
- }
- }
-
- shutdownSync(): void {
- for (const s of this.servers) {
- s.close();
- s.removeAllListeners();
- }
- for (const p of this.procs) {
- if (p.proc.exitCode == null) {
- p.proc.kill("SIGTERM");
- }
- }
- }
-
- spawnService(
- command: string,
- args: string[],
- logName: string,
- env: { [index: string]: string | undefined } = process.env,
- ): ProcessWrapper {
- logger.info(
- `spawning process (${logName}): ${shellescape([command, ...args])}`,
- );
- const proc = spawn(command, args, {
- stdio: ["inherit", "pipe", "pipe"],
- env: env,
- });
- logger.info(`spawned process (${logName}) with pid ${proc.pid}`);
- proc.on("error", (err) => {
- logger.warn(`could not start process (${command})`, err);
- });
- proc.on("exit", (code, signal) => {
- logger.warn(`process ${logName} exited ${j2s({ code, signal })}`);
- });
- const stderrLogFileName = this.testDir + `/${logName}-stderr.log`;
- const stderrLog = fs.createWriteStream(stderrLogFileName, {
- flags: "a",
- });
- proc.stderr.pipe(stderrLog);
- const stdoutLogFileName = this.testDir + `/${logName}-stdout.log`;
- const stdoutLog = fs.createWriteStream(stdoutLogFileName, {
- flags: "a",
- });
- proc.stdout.pipe(stdoutLog);
- const procWrap = new ProcessWrapper(proc);
- this.procs.push(procWrap);
- return procWrap;
- }
-
- async shutdown(): Promise<void> {
- if (this.inShutdown) {
- return;
- }
- if (shouldLingerInTest()) {
- logger.info("refusing to shut down, lingering was requested");
- return;
- }
- this.inShutdown = true;
- logger.info("shutting down");
- for (const s of this.servers) {
- s.close();
- s.removeAllListeners();
- }
- for (const p of this.procs) {
- if (p.proc.exitCode == null) {
- logger.info(`killing process ${p.proc.pid}`);
- p.proc.kill("SIGTERM");
- await p.wait();
- }
- }
- }
-}
-
-export function shouldLingerInTest(): boolean {
- return !!process.env["TALER_TEST_LINGER"];
-}
-
-export interface TalerConfigSection {
- options: Record<string, string | undefined>;
-}
-
-export interface TalerConfig {
- sections: Record<string, TalerConfigSection>;
-}
-
-export interface DbInfo {
- /**
- * Postgres connection string.
- */
- connStr: string;
-
- dbname: string;
-}
-
-export async function setupDb(gc: GlobalTestState): Promise<DbInfo> {
- const dbname = "taler-integrationtest";
- await exec(`dropdb "${dbname}" || true`);
- await exec(`createdb "${dbname}"`);
- return {
- connStr: `postgres:///${dbname}`,
- dbname,
- };
-}
-
-export interface BankConfig {
- currency: string;
- httpPort: number;
- database: string;
- allowRegistrations: boolean;
- maxDebt?: string;
-}
-
-export interface FakeBankConfig {
- currency: string;
- httpPort: number;
-}
-
-function setTalerPaths(config: Configuration, home: string) {
- config.setString("paths", "taler_home", home);
- // We need to make sure that the path of taler_runtime_dir isn't too long,
- // as it contains unix domain sockets (108 character limit).
- const runDir = fs.mkdtempSync("/tmp/taler-test-");
- config.setString("paths", "taler_runtime_dir", runDir);
- config.setString(
- "paths",
- "taler_data_home",
- "$TALER_HOME/.local/share/taler/",
- );
- config.setString("paths", "taler_config_home", "$TALER_HOME/.config/taler/");
- config.setString("paths", "taler_cache_home", "$TALER_HOME/.config/taler/");
-}
-
-function setCoin(config: Configuration, c: CoinConfig) {
- const s = `coin_${c.name}`;
- config.setString(s, "value", c.value);
- config.setString(s, "duration_withdraw", c.durationWithdraw);
- config.setString(s, "duration_spend", c.durationSpend);
- config.setString(s, "duration_legal", c.durationLegal);
- config.setString(s, "fee_deposit", c.feeDeposit);
- config.setString(s, "fee_withdraw", c.feeWithdraw);
- config.setString(s, "fee_refresh", c.feeRefresh);
- config.setString(s, "fee_refund", c.feeRefund);
- if (c.ageRestricted) {
- config.setString(s, "age_restricted", "yes");
- }
- if (c.cipher === "RSA") {
- config.setString(s, "rsa_keysize", `${c.rsaKeySize}`);
- config.setString(s, "cipher", "RSA");
- } else if (c.cipher === "CS") {
- config.setString(s, "cipher", "CS");
- } else {
- throw new Error();
- }
-}
-
-/**
- * Send an HTTP request until it succeeds or the process dies.
- */
-export async function pingProc(
- proc: ProcessWrapper | undefined,
- url: string,
- serviceName: string,
-): Promise<void> {
- if (!proc || proc.proc.exitCode !== null) {
- throw Error(`service process ${serviceName} not started, can't ping`);
- }
- while (true) {
- try {
- logger.info(`pinging ${serviceName} at ${url}`);
- const resp = await axios.get(url);
- logger.info(`service ${serviceName} available`);
- return;
- } catch (e: any) {
- logger.info(`service ${serviceName} not ready:`, e.toString());
- //console.log(e);
- await delayMs(1000);
- }
- if (!proc || proc.proc.exitCode != null || proc.proc.signalCode != null) {
- throw Error(`service process ${serviceName} stopped unexpectedly`);
- }
- }
-}
-
-class BankServiceBase {
- proc: ProcessWrapper | undefined;
-
- protected constructor(
- protected globalTestState: GlobalTestState,
- protected bankConfig: BankConfig,
- protected configFile: string,
- ) {}
-}
-
-/**
- * Work in progress. The key point is that both Sandbox and Nexus
- * will be configured and started by this class.
- */
-class LibEuFinBankService extends BankServiceBase implements BankServiceHandle {
- sandboxProc: ProcessWrapper | undefined;
- nexusProc: ProcessWrapper | undefined;
-
- http = new NodeHttpLib();
-
- static async create(
- gc: GlobalTestState,
- bc: BankConfig,
- ): Promise<LibEuFinBankService> {
- return new LibEuFinBankService(gc, bc, "foo");
- }
-
- get port() {
- return this.bankConfig.httpPort;
- }
- get nexusPort() {
- return this.bankConfig.httpPort + 1000;
- }
-
- get nexusDbConn(): string {
- return `jdbc:sqlite:${this.globalTestState.testDir}/libeufin-nexus.sqlite3`;
- }
-
- get sandboxDbConn(): string {
- return `jdbc:sqlite:${this.globalTestState.testDir}/libeufin-sandbox.sqlite3`;
- }
-
- get nexusBaseUrl(): string {
- return `http://localhost:${this.nexusPort}`;
- }
-
- get baseUrlDemobank(): string {
- let url = new URL("demobanks/default/", this.baseUrlNetloc);
- return url.href;
- }
-
- // FIXME: Duplicate? Where is this needed?
- get baseUrlAccessApi(): string {
- let url = new URL("access-api/", this.baseUrlDemobank);
- return url.href;
- }
-
- get bankAccessApiBaseUrl(): string {
- let url = new URL("access-api/", this.baseUrlDemobank);
- return url.href;
- }
-
- get baseUrlNetloc(): string {
- return `http://localhost:${this.bankConfig.httpPort}/`;
- }
-
- get baseUrl(): string {
- return this.baseUrlAccessApi;
- }
-
- async setSuggestedExchange(
- e: ExchangeServiceInterface,
- exchangePayto: string,
- ) {
- await sh(
- this.globalTestState,
- "libeufin-sandbox-set-default-exchange",
- `libeufin-sandbox default-exchange ${e.baseUrl} ${exchangePayto}`,
- {
- ...process.env,
- LIBEUFIN_SANDBOX_DB_CONNECTION: this.sandboxDbConn,
- },
- );
- }
-
- // Create one at both sides: Sandbox and Nexus.
- async createExchangeAccount(
- accountName: string,
- password: string,
- ): Promise<HarnessExchangeBankAccount> {
- logger.info("Create Exchange account(s)!");
- /**
- * Many test cases try to create a Exchange account before
- * starting the bank; that's because the Pybank did it entirely
- * via the configuration file.
- */
- await this.start();
- await this.pingUntilAvailable();
- await LibeufinSandboxApi.createDemobankAccount(accountName, password, {
- baseUrl: this.baseUrlAccessApi,
- });
- let bankAccountLabel = accountName;
- await LibeufinSandboxApi.createDemobankEbicsSubscriber(
- {
- hostID: "talertestEbicsHost",
- userID: "exchangeEbicsUser",
- partnerID: "exchangeEbicsPartner",
- },
- bankAccountLabel,
- { baseUrl: this.baseUrlDemobank },
- );
-
- await LibeufinNexusApi.createUser(
- { baseUrl: this.nexusBaseUrl },
- {
- username: accountName,
- password: password,
- },
- );
- await LibeufinNexusApi.createEbicsBankConnection(
- { baseUrl: this.nexusBaseUrl },
- {
- name: "ebics-connection", // connection name.
- ebicsURL: new URL("ebicsweb", this.baseUrlNetloc).href,
- hostID: "talertestEbicsHost",
- userID: "exchangeEbicsUser",
- partnerID: "exchangeEbicsPartner",
- },
- );
- await LibeufinNexusApi.connectBankConnection(
- { baseUrl: this.nexusBaseUrl },
- "ebics-connection",
- );
- await LibeufinNexusApi.fetchAccounts(
- { baseUrl: this.nexusBaseUrl },
- "ebics-connection",
- );
- await LibeufinNexusApi.importConnectionAccount(
- { baseUrl: this.nexusBaseUrl },
- "ebics-connection", // connection name
- accountName, // offered account label
- `${accountName}-nexus-label`, // bank account label at Nexus
- );
- await LibeufinNexusApi.createTwgFacade(
- { baseUrl: this.nexusBaseUrl },
- {
- name: "exchange-facade",
- connectionName: "ebics-connection",
- accountName: `${accountName}-nexus-label`,
- currency: "EUR",
- reserveTransferLevel: "report",
- },
- );
- await LibeufinNexusApi.postPermission(
- { baseUrl: this.nexusBaseUrl },
- {
- action: "grant",
- permission: {
- subjectId: accountName,
- subjectType: "user",
- resourceType: "facade",
- resourceId: "exchange-facade", // facade name
- permissionName: "facade.talerWireGateway.transfer",
- },
- },
- );
- await LibeufinNexusApi.postPermission(
- { baseUrl: this.nexusBaseUrl },
- {
- action: "grant",
- permission: {
- subjectId: accountName,
- subjectType: "user",
- resourceType: "facade",
- resourceId: "exchange-facade", // facade name
- permissionName: "facade.talerWireGateway.history",
- },
- },
- );
- // Set fetch task.
- await LibeufinNexusApi.postTask(
- { baseUrl: this.nexusBaseUrl },
- `${accountName}-nexus-label`,
- {
- name: "wirewatch-task",
- cronspec: "* * *",
- type: "fetch",
- params: {
- level: "all",
- rangeType: "all",
- },
- },
- );
- await LibeufinNexusApi.postTask(
- { baseUrl: this.nexusBaseUrl },
- `${accountName}-nexus-label`,
- {
- name: "aggregator-task",
- cronspec: "* * *",
- type: "submit",
- params: {},
- },
- );
- let facadesResp = await LibeufinNexusApi.getAllFacades({
- baseUrl: this.nexusBaseUrl,
- });
- let accountInfoResp = await LibeufinSandboxApi.demobankAccountInfo(
- "admin",
- "secret",
- { baseUrl: this.baseUrlAccessApi },
- accountName, // bank account label.
- );
- return {
- accountName: accountName,
- accountPassword: password,
- accountPaytoUri: accountInfoResp.data.paytoUri,
- wireGatewayApiBaseUrl: facadesResp.data.facades[0].baseUrl,
- };
- }
-
- async start(): Promise<void> {
- /**
- * Because many test cases try to create a Exchange bank
- * account _before_ starting the bank (Pybank did it only via
- * the config), it is possible that at this point Sandbox and
- * Nexus are already running. Hence, this method only launches
- * them if they weren't launched earlier.
- */
-
- // Only go ahead if BOTH aren't running.
- if (this.sandboxProc || this.nexusProc) {
- logger.info("Nexus or Sandbox already running, not taking any action.");
- return;
- }
- await sh(
- this.globalTestState,
- "libeufin-sandbox-config-demobank",
- `libeufin-sandbox config --currency=${this.bankConfig.currency} default`,
- {
- ...process.env,
- LIBEUFIN_SANDBOX_DB_CONNECTION: this.sandboxDbConn,
- LIBEUFIN_SANDBOX_ADMIN_PASSWORD: "secret",
- },
- );
- this.sandboxProc = this.globalTestState.spawnService(
- "libeufin-sandbox",
- ["serve", "--port", `${this.port}`],
- "libeufin-sandbox",
- {
- ...process.env,
- LIBEUFIN_SANDBOX_DB_CONNECTION: this.sandboxDbConn,
- LIBEUFIN_SANDBOX_ADMIN_PASSWORD: "secret",
- },
- );
- await runCommand(
- this.globalTestState,
- "libeufin-nexus-superuser",
- "libeufin-nexus",
- ["superuser", "admin", "--password", "test"],
- {
- ...process.env,
- LIBEUFIN_NEXUS_DB_CONNECTION: this.nexusDbConn,
- },
- );
- this.nexusProc = this.globalTestState.spawnService(
- "libeufin-nexus",
- ["serve", "--port", `${this.nexusPort}`],
- "libeufin-nexus",
- {
- ...process.env,
- LIBEUFIN_NEXUS_DB_CONNECTION: this.nexusDbConn,
- },
- );
- // need to wait here, because at this point
- // a Ebics host needs to be created (RESTfully)
- await this.pingUntilAvailable();
- LibeufinSandboxApi.createEbicsHost(
- { baseUrl: this.baseUrlNetloc },
- "talertestEbicsHost",
- );
- }
-
- async pingUntilAvailable(): Promise<void> {
- await pingProc(
- this.sandboxProc,
- `http://localhost:${this.bankConfig.httpPort}`,
- "libeufin-sandbox",
- );
- await pingProc(
- this.nexusProc,
- `${this.nexusBaseUrl}/config`,
- "libeufin-nexus",
- );
- }
-}
-
-/**
- * Implementation of the bank service using the "taler-fakebank-run" tool.
- */
-export class FakebankService
- extends BankServiceBase
- implements BankServiceHandle
-{
- proc: ProcessWrapper | undefined;
-
- http = new NodeHttpLib();
-
- // We store "created" accounts during setup and
- // register them after startup.
- private accounts: {
- accountName: string;
- accountPassword: string;
- }[] = [];
-
- static async create(
- gc: GlobalTestState,
- bc: BankConfig,
- ): Promise<FakebankService> {
- const config = new Configuration();
- setTalerPaths(config, gc.testDir + "/talerhome");
- config.setString("taler", "currency", bc.currency);
- config.setString("bank", "http_port", `${bc.httpPort}`);
- config.setString("bank", "serve", "http");
- config.setString("bank", "max_debt_bank", `${bc.currency}:999999`);
- config.setString("bank", "max_debt", bc.maxDebt ?? `${bc.currency}:100`);
- config.setString("bank", "ram_limit", `${1024}`);
- const cfgFilename = gc.testDir + "/bank.conf";
- config.write(cfgFilename);
-
- return new FakebankService(gc, bc, cfgFilename);
- }
-
- setSuggestedExchange(e: ExchangeServiceInterface, exchangePayto: string) {
- if (!!this.proc) {
- throw Error("Can't set suggested exchange while bank is running.");
- }
- const config = Configuration.load(this.configFile);
- config.setString("bank", "suggested_exchange", e.baseUrl);
- config.write(this.configFile);
- }
-
- get baseUrl(): string {
- return `http://localhost:${this.bankConfig.httpPort}/`;
- }
-
- get bankAccessApiBaseUrl(): string {
- let url = new URL("taler-bank-access/", this.baseUrl);
- return url.href;
- }
-
- async createExchangeAccount(
- accountName: string,
- password: string,
- ): Promise<HarnessExchangeBankAccount> {
- this.accounts.push({
- accountName,
- accountPassword: password,
- });
- return {
- accountName: accountName,
- accountPassword: password,
- accountPaytoUri: getPayto(accountName),
- wireGatewayApiBaseUrl: `http://localhost:${this.bankConfig.httpPort}/taler-wire-gateway/${accountName}/`,
- };
- }
-
- get port() {
- return this.bankConfig.httpPort;
- }
-
- async start(): Promise<void> {
- logger.info("starting fakebank");
- if (this.proc) {
- logger.info("fakebank already running, not starting again");
- return;
- }
- this.proc = this.globalTestState.spawnService(
- "taler-fakebank-run",
- [
- "-c",
- this.configFile,
- "--signup-bonus",
- `${this.bankConfig.currency}:100`,
- ],
- "bank",
- );
- await this.pingUntilAvailable();
- for (const acc of this.accounts) {
- await BankApi.registerAccount(this, acc.accountName, acc.accountPassword);
- }
- }
-
- async pingUntilAvailable(): Promise<void> {
- const url = `http://localhost:${this.bankConfig.httpPort}/taler-bank-integration/config`;
- await pingProc(this.proc, url, "bank");
- }
-}
-
-// Use libeufin bank instead of pybank.
-const useLibeufinBank = false;
-
-export type BankService = BankServiceHandle;
-export const BankService = FakebankService;
-
-export interface ExchangeConfig {
- name: string;
- currency: string;
- roundUnit?: string;
- httpPort: number;
- database: string;
-}
-
-export interface ExchangeServiceInterface {
- readonly baseUrl: string;
- readonly port: number;
- readonly name: string;
- readonly masterPub: string;
-}
-
-export class ExchangeService implements ExchangeServiceInterface {
- static fromExistingConfig(gc: GlobalTestState, exchangeName: string) {
- const cfgFilename = gc.testDir + `/exchange-${exchangeName}.conf`;
- const config = Configuration.load(cfgFilename);
- const ec: ExchangeConfig = {
- currency: config.getString("taler", "currency").required(),
- database: config.getString("exchangedb-postgres", "config").required(),
- httpPort: config.getNumber("exchange", "port").required(),
- name: exchangeName,
- roundUnit: config.getString("taler", "currency_round_unit").required(),
- };
- const privFile = config.getPath("exchange", "master_priv_file").required();
- const eddsaPriv = fs.readFileSync(privFile);
- const keyPair: EddsaKeyPair = {
- eddsaPriv,
- eddsaPub: eddsaGetPublic(eddsaPriv),
- };
- return new ExchangeService(gc, ec, cfgFilename, keyPair);
- }
-
- private currentTimetravel: Duration | undefined;
-
- setTimetravel(t: Duration | undefined): void {
- if (this.isRunning()) {
- throw Error("can't set time travel while the exchange is running");
- }
- this.currentTimetravel = t;
- }
-
- private get timetravelArg(): string | undefined {
- if (this.currentTimetravel && this.currentTimetravel.d_ms !== "forever") {
- // Convert to microseconds
- return `--timetravel=+${this.currentTimetravel.d_ms * 1000}`;
- }
- return undefined;
- }
-
- /**
- * Return an empty array if no time travel is set,
- * and an array with the time travel command line argument
- * otherwise.
- */
- private get timetravelArgArr(): string[] {
- const tta = this.timetravelArg;
- if (tta) {
- return [tta];
- }
- return [];
- }
-
- async runWirewatchOnce() {
- if (useLibeufinBank) {
- // Not even 2 secods showed to be enough!
- await waitMs(4000);
- }
- await runCommand(
- this.globalState,
- `exchange-${this.name}-wirewatch-once`,
- "taler-exchange-wirewatch",
- [...this.timetravelArgArr, "-c", this.configFilename, "-t"],
- );
- }
-
- async runAggregatorOnce() {
- try {
- await runCommand(
- this.globalState,
- `exchange-${this.name}-aggregator-once`,
- "taler-exchange-aggregator",
- [...this.timetravelArgArr, "-c", this.configFilename, "-t", "-y"],
- );
- } catch (e) {
- logger.info(
- "running aggregator with KYC off didn't work, might be old version, running again",
- );
- await runCommand(
- this.globalState,
- `exchange-${this.name}-aggregator-once`,
- "taler-exchange-aggregator",
- [...this.timetravelArgArr, "-c", this.configFilename, "-t"],
- );
- }
- }
-
- async runTransferOnce() {
- await runCommand(
- this.globalState,
- `exchange-${this.name}-transfer-once`,
- "taler-exchange-transfer",
- [...this.timetravelArgArr, "-c", this.configFilename, "-t"],
- );
- }
-
- changeConfig(f: (config: Configuration) => void) {
- const config = Configuration.load(this.configFilename);
- f(config);
- config.write(this.configFilename);
- }
-
- static create(gc: GlobalTestState, e: ExchangeConfig) {
- const config = new Configuration();
- config.setString("taler", "currency", e.currency);
- config.setString(
- "taler",
- "currency_round_unit",
- e.roundUnit ?? `${e.currency}:0.01`,
- );
- setTalerPaths(config, gc.testDir + "/talerhome");
- config.setString(
- "exchange",
- "revocation_dir",
- "${TALER_DATA_HOME}/exchange/revocations",
- );
- config.setString("exchange", "max_keys_caching", "forever");
- config.setString("exchange", "db", "postgres");
- config.setString(
- "exchange-offline",
- "master_priv_file",
- "${TALER_DATA_HOME}/exchange/offline-keys/master.priv",
- );
- config.setString("exchange", "serve", "tcp");
- config.setString("exchange", "port", `${e.httpPort}`);
-
- config.setString("exchangedb-postgres", "config", e.database);
-
- config.setString("taler-exchange-secmod-eddsa", "lookahead_sign", "20 s");
- config.setString("taler-exchange-secmod-rsa", "lookahead_sign", "20 s");
-
- const exchangeMasterKey = createEddsaKeyPair();
-
- config.setString(
- "exchange",
- "master_public_key",
- encodeCrock(exchangeMasterKey.eddsaPub),
- );
-
- const masterPrivFile = config
- .getPath("exchange-offline", "master_priv_file")
- .required();
-
- fs.mkdirSync(path.dirname(masterPrivFile), { recursive: true });
-
- fs.writeFileSync(masterPrivFile, Buffer.from(exchangeMasterKey.eddsaPriv));
-
- const cfgFilename = gc.testDir + `/exchange-${e.name}.conf`;
- config.write(cfgFilename);
- return new ExchangeService(gc, e, cfgFilename, exchangeMasterKey);
- }
-
- addOfferedCoins(offeredCoins: ((curr: string) => CoinConfig)[]) {
- const config = Configuration.load(this.configFilename);
- offeredCoins.forEach((cc) =>
- setCoin(config, cc(this.exchangeConfig.currency)),
- );
- config.write(this.configFilename);
- }
-
- addCoinConfigList(ccs: CoinConfig[]) {
- const config = Configuration.load(this.configFilename);
- ccs.forEach((cc) => setCoin(config, cc));
- config.write(this.configFilename);
- }
-
- enableAgeRestrictions(maskStr: string) {
- const config = Configuration.load(this.configFilename);
- config.setString("exchange-extension-age_restriction", "enabled", "yes");
- config.setString(
- "exchange-extension-age_restriction",
- "age_groups",
- maskStr,
- );
- config.write(this.configFilename);
- }
-
- get masterPub() {
- return encodeCrock(this.keyPair.eddsaPub);
- }
-
- get port() {
- return this.exchangeConfig.httpPort;
- }
-
- async addBankAccount(
- localName: string,
- exchangeBankAccount: HarnessExchangeBankAccount,
- ): Promise<void> {
- const config = Configuration.load(this.configFilename);
- config.setString(
- `exchange-account-${localName}`,
- "wire_response",
- `\${TALER_DATA_HOME}/exchange/account-${localName}.json`,
- );
- config.setString(
- `exchange-account-${localName}`,
- "payto_uri",
- exchangeBankAccount.accountPaytoUri,
- );
- config.setString(`exchange-account-${localName}`, "enable_credit", "yes");
- config.setString(`exchange-account-${localName}`, "enable_debit", "yes");
- config.setString(
- `exchange-accountcredentials-${localName}`,
- "wire_gateway_url",
- exchangeBankAccount.wireGatewayApiBaseUrl,
- );
- config.setString(
- `exchange-accountcredentials-${localName}`,
- "wire_gateway_auth_method",
- "basic",
- );
- config.setString(
- `exchange-accountcredentials-${localName}`,
- "username",
- exchangeBankAccount.accountName,
- );
- config.setString(
- `exchange-accountcredentials-${localName}`,
- "password",
- exchangeBankAccount.accountPassword,
- );
- config.write(this.configFilename);
- }
-
- exchangeHttpProc: ProcessWrapper | undefined;
- exchangeWirewatchProc: ProcessWrapper | undefined;
-
- helperCryptoRsaProc: ProcessWrapper | undefined;
- helperCryptoEddsaProc: ProcessWrapper | undefined;
- helperCryptoCsProc: ProcessWrapper | undefined;
-
- constructor(
- private globalState: GlobalTestState,
- private exchangeConfig: ExchangeConfig,
- private configFilename: string,
- private keyPair: EddsaKeyPair,
- ) {}
-
- get name() {
- return this.exchangeConfig.name;
- }
-
- get baseUrl() {
- return `http://localhost:${this.exchangeConfig.httpPort}/`;
- }
-
- isRunning(): boolean {
- return !!this.exchangeWirewatchProc || !!this.exchangeHttpProc;
- }
-
- async stop(): Promise<void> {
- const wirewatch = this.exchangeWirewatchProc;
- if (wirewatch) {
- wirewatch.proc.kill("SIGTERM");
- await wirewatch.wait();
- this.exchangeWirewatchProc = undefined;
- }
- const httpd = this.exchangeHttpProc;
- if (httpd) {
- httpd.proc.kill("SIGTERM");
- await httpd.wait();
- this.exchangeHttpProc = undefined;
- }
- const cryptoRsa = this.helperCryptoRsaProc;
- if (cryptoRsa) {
- cryptoRsa.proc.kill("SIGTERM");
- await cryptoRsa.wait();
- this.helperCryptoRsaProc = undefined;
- }
- const cryptoEddsa = this.helperCryptoEddsaProc;
- if (cryptoEddsa) {
- cryptoEddsa.proc.kill("SIGTERM");
- await cryptoEddsa.wait();
- this.helperCryptoRsaProc = undefined;
- }
- const cryptoCs = this.helperCryptoCsProc;
- if (cryptoCs) {
- cryptoCs.proc.kill("SIGTERM");
- await cryptoCs.wait();
- this.helperCryptoCsProc = undefined;
- }
- }
-
- /**
- * Update keys signing the keys generated by the security module
- * with the offline signing key.
- */
- async keyup(): Promise<void> {
- await runCommand(
- this.globalState,
- "exchange-offline",
- "taler-exchange-offline",
- ["-c", this.configFilename, "download", "sign", "upload"],
- );
-
- const accounts: string[] = [];
- const accountTargetTypes: Set<string> = new Set();
-
- const config = Configuration.load(this.configFilename);
- for (const sectionName of config.getSectionNames()) {
- if (sectionName.startsWith("EXCHANGE-ACCOUNT-")) {
- const paytoUri = config.getString(sectionName, "payto_uri").required();
- const p = parsePaytoUri(paytoUri);
- if (!p) {
- throw Error(`invalid payto uri in exchange config: ${paytoUri}`);
- }
- accountTargetTypes.add(p?.targetType);
- accounts.push(paytoUri);
- }
- }
-
- logger.info("configuring bank accounts", accounts);
-
- for (const acc of accounts) {
- await runCommand(
- this.globalState,
- "exchange-offline",
- "taler-exchange-offline",
- ["-c", this.configFilename, "enable-account", acc, "upload"],
- );
- }
-
- const year = new Date().getFullYear();
- for (const accTargetType of accountTargetTypes.values()) {
- for (let i = year; i < year + 5; i++) {
- await runCommand(
- this.globalState,
- "exchange-offline",
- "taler-exchange-offline",
- [
- "-c",
- this.configFilename,
- "wire-fee",
- // Year
- `${i}`,
- // Wire method
- accTargetType,
- // Wire fee
- `${this.exchangeConfig.currency}:0.01`,
- // Closing fee
- `${this.exchangeConfig.currency}:0.01`,
- "upload",
- ],
- );
- }
- }
-
- await runCommand(
- this.globalState,
- "exchange-offline",
- "taler-exchange-offline",
- [
- "-c",
- this.configFilename,
- "global-fee",
- // year
- "now",
- // history fee
- `${this.exchangeConfig.currency}:0.01`,
- // account fee
- `${this.exchangeConfig.currency}:0.01`,
- // purse fee
- `${this.exchangeConfig.currency}:0.00`,
- // purse timeout
- "1h",
- // history expiration
- "1year",
- // free purses per account
- "5",
- "upload",
- ],
- );
- }
-
- async revokeDenomination(denomPubHash: string) {
- if (!this.isRunning()) {
- throw Error("exchange must be running when revoking denominations");
- }
- await runCommand(
- this.globalState,
- "exchange-offline",
- "taler-exchange-offline",
- [
- "-c",
- this.configFilename,
- "revoke-denomination",
- denomPubHash,
- "upload",
- ],
- );
- }
-
- async purgeSecmodKeys(): Promise<void> {
- const cfg = Configuration.load(this.configFilename);
- const rsaKeydir = cfg
- .getPath("taler-exchange-secmod-rsa", "KEY_DIR")
- .required();
- const eddsaKeydir = cfg
- .getPath("taler-exchange-secmod-eddsa", "KEY_DIR")
- .required();
- // Be *VERY* careful when changing this, or you will accidentally delete user data.
- await sh(this.globalState, "rm-secmod-keys", `rm -rf ${rsaKeydir}/COIN_*`);
- await sh(this.globalState, "rm-secmod-keys", `rm ${eddsaKeydir}/*`);
- }
-
- async purgeDatabase(): Promise<void> {
- await sh(
- this.globalState,
- "exchange-dbinit",
- `taler-exchange-dbinit -r -c "${this.configFilename}"`,
- );
- }
-
- async start(): Promise<void> {
- if (this.isRunning()) {
- throw Error("exchange is already running");
- }
- await sh(
- this.globalState,
- "exchange-dbinit",
- `taler-exchange-dbinit -c "${this.configFilename}"`,
- );
-
- this.helperCryptoEddsaProc = this.globalState.spawnService(
- "taler-exchange-secmod-eddsa",
- ["-c", this.configFilename, "-LDEBUG", ...this.timetravelArgArr],
- `exchange-crypto-eddsa-${this.name}`,
- );
-
- this.helperCryptoCsProc = this.globalState.spawnService(
- "taler-exchange-secmod-cs",
- ["-c", this.configFilename, "-LDEBUG", ...this.timetravelArgArr],
- `exchange-crypto-cs-${this.name}`,
- );
-
- this.helperCryptoRsaProc = this.globalState.spawnService(
- "taler-exchange-secmod-rsa",
- ["-c", this.configFilename, "-LDEBUG", ...this.timetravelArgArr],
- `exchange-crypto-rsa-${this.name}`,
- );
-
- this.exchangeWirewatchProc = this.globalState.spawnService(
- "taler-exchange-wirewatch",
- ["-c", this.configFilename, ...this.timetravelArgArr],
- `exchange-wirewatch-${this.name}`,
- );
-
- this.exchangeHttpProc = this.globalState.spawnService(
- "taler-exchange-httpd",
- ["-LINFO", "-c", this.configFilename, ...this.timetravelArgArr],
- `exchange-httpd-${this.name}`,
- );
-
- await this.pingUntilAvailable();
- await this.keyup();
- }
-
- async pingUntilAvailable(): Promise<void> {
- // We request /management/keys, since /keys can block
- // when we didn't do the key setup yet.
- const url = `http://localhost:${this.exchangeConfig.httpPort}/management/keys`;
- await pingProc(this.exchangeHttpProc, url, `exchange (${this.name})`);
- }
-}
-
-export interface MerchantConfig {
- name: string;
- currency: string;
- httpPort: number;
- database: string;
-}
-
-export interface PrivateOrderStatusQuery {
- instance?: string;
- orderId: string;
- sessionId?: string;
-}
-
-export interface MerchantServiceInterface {
- makeInstanceBaseUrl(instanceName?: string): string;
- readonly port: number;
- readonly name: string;
-}
-
-export class MerchantApiClient {
- constructor(
- private baseUrl: string,
- public readonly auth: MerchantAuthConfiguration,
- ) {}
-
- async changeAuth(auth: MerchantAuthConfiguration): Promise<void> {
- const url = new URL("private/auth", this.baseUrl);
- await axios.post(url.href, auth, {
- headers: this.makeAuthHeader(),
- });
- }
-
- async deleteInstance(instanceId: string) {
- const url = new URL(`management/instances/${instanceId}`, this.baseUrl);
- await axios.delete(url.href, {
- headers: this.makeAuthHeader(),
- });
- }
-
- async createInstance(req: MerchantInstanceConfig): Promise<void> {
- const url = new URL("management/instances", this.baseUrl);
- await axios.post(url.href, req, {
- headers: this.makeAuthHeader(),
- });
- }
-
- async getInstances(): Promise<MerchantInstancesResponse> {
- const url = new URL("management/instances", this.baseUrl);
- const resp = await axios.get(url.href, {
- headers: this.makeAuthHeader(),
- });
- return resp.data;
- }
-
- async getInstanceFullDetails(instanceId: string): Promise<any> {
- const url = new URL(`management/instances/${instanceId}`, this.baseUrl);
- try {
- const resp = await axios.get(url.href, {
- headers: this.makeAuthHeader(),
- });
- return resp.data;
- } catch (e) {
- throw e;
- }
- }
-
- makeAuthHeader(): Record<string, string> {
- switch (this.auth.method) {
- case "external":
- return {};
- case "token":
- return {
- Authorization: `Bearer ${this.auth.token}`,
- };
- }
- }
-}
-
-/**
- * FIXME: This should be deprecated in favor of MerchantApiClient
- */
-export namespace MerchantPrivateApi {
- export async function createOrder(
- merchantService: MerchantServiceInterface,
- instanceName: string,
- req: PostOrderRequest,
- withAuthorization: WithAuthorization = {},
- ): Promise<PostOrderResponse> {
- const baseUrl = merchantService.makeInstanceBaseUrl(instanceName);
- let url = new URL("private/orders", baseUrl);
- const resp = await axios.post(url.href, req, {
- headers: withAuthorization as Record<string, string>,
- });
- return codecForPostOrderResponse().decode(resp.data);
- }
-
- export async function queryPrivateOrderStatus(
- merchantService: MerchantServiceInterface,
- query: PrivateOrderStatusQuery,
- withAuthorization: WithAuthorization = {},
- ): Promise<MerchantOrderPrivateStatusResponse> {
- const reqUrl = new URL(
- `private/orders/${query.orderId}`,
- merchantService.makeInstanceBaseUrl(query.instance),
- );
- if (query.sessionId) {
- reqUrl.searchParams.set("session_id", query.sessionId);
- }
- const resp = await axios.get(reqUrl.href, {
- headers: withAuthorization as Record<string, string>,
- });
- return codecForMerchantOrderPrivateStatusResponse().decode(resp.data);
- }
-
- export async function giveRefund(
- merchantService: MerchantServiceInterface,
- r: {
- instance: string;
- orderId: string;
- amount: string;
- justification: string;
- },
- ): Promise<{ talerRefundUri: string }> {
- const reqUrl = new URL(
- `private/orders/${r.orderId}/refund`,
- merchantService.makeInstanceBaseUrl(r.instance),
- );
- const resp = await axios.post(reqUrl.href, {
- refund: r.amount,
- reason: r.justification,
- });
- return {
- talerRefundUri: resp.data.taler_refund_uri,
- };
- }
-
- export async function createTippingReserve(
- merchantService: MerchantServiceInterface,
- instance: string,
- req: CreateMerchantTippingReserveRequest,
- ): Promise<CreateMerchantTippingReserveConfirmation> {
- const reqUrl = new URL(
- `private/reserves`,
- merchantService.makeInstanceBaseUrl(instance),
- );
- const resp = await axios.post(reqUrl.href, req);
- // FIXME: validate
- return resp.data;
- }
-
- export async function queryTippingReserves(
- merchantService: MerchantServiceInterface,
- instance: string,
- ): Promise<TippingReserveStatus> {
- const reqUrl = new URL(
- `private/reserves`,
- merchantService.makeInstanceBaseUrl(instance),
- );
- const resp = await axios.get(reqUrl.href);
- // FIXME: validate
- return resp.data;
- }
-
- export async function giveTip(
- merchantService: MerchantServiceInterface,
- instance: string,
- req: TipCreateRequest,
- ): Promise<TipCreateConfirmation> {
- const reqUrl = new URL(
- `private/tips`,
- merchantService.makeInstanceBaseUrl(instance),
- );
- const resp = await axios.post(reqUrl.href, req);
- // FIXME: validate
- return resp.data;
- }
-}
-
-export interface CreateMerchantTippingReserveRequest {
- // Amount that the merchant promises to put into the reserve
- initial_balance: AmountString;
-
- // Exchange the merchant intends to use for tipping
- exchange_url: string;
-
- // Desired wire method, for example "iban" or "x-taler-bank"
- wire_method: string;
-}
-
-export interface CreateMerchantTippingReserveConfirmation {
- // Public key identifying the reserve
- reserve_pub: string;
-
- // Wire account of the exchange where to transfer the funds
- payto_uri: string;
-}
-
-export class MerchantService implements MerchantServiceInterface {
- static fromExistingConfig(gc: GlobalTestState, name: string) {
- const cfgFilename = gc.testDir + `/merchant-${name}.conf`;
- const config = Configuration.load(cfgFilename);
- const mc: MerchantConfig = {
- currency: config.getString("taler", "currency").required(),
- database: config.getString("merchantdb-postgres", "config").required(),
- httpPort: config.getNumber("merchant", "port").required(),
- name,
- };
- return new MerchantService(gc, mc, cfgFilename);
- }
-
- proc: ProcessWrapper | undefined;
-
- constructor(
- private globalState: GlobalTestState,
- private merchantConfig: MerchantConfig,
- private configFilename: string,
- ) {}
-
- private currentTimetravel: Duration | undefined;
-
- private isRunning(): boolean {
- return !!this.proc;
- }
-
- setTimetravel(t: Duration | undefined): void {
- if (this.isRunning()) {
- throw Error("can't set time travel while the exchange is running");
- }
- this.currentTimetravel = t;
- }
-
- private get timetravelArg(): string | undefined {
- if (this.currentTimetravel && this.currentTimetravel.d_ms !== "forever") {
- // Convert to microseconds
- return `--timetravel=+${this.currentTimetravel.d_ms * 1000}`;
- }
- return undefined;
- }
-
- /**
- * Return an empty array if no time travel is set,
- * and an array with the time travel command line argument
- * otherwise.
- */
- private get timetravelArgArr(): string[] {
- const tta = this.timetravelArg;
- if (tta) {
- return [tta];
- }
- return [];
- }
-
- get port(): number {
- return this.merchantConfig.httpPort;
- }
-
- get name(): string {
- return this.merchantConfig.name;
- }
-
- async stop(): Promise<void> {
- const httpd = this.proc;
- if (httpd) {
- httpd.proc.kill("SIGTERM");
- await httpd.wait();
- this.proc = undefined;
- }
- }
-
- async start(): Promise<void> {
- await exec(`taler-merchant-dbinit -c "${this.configFilename}"`);
-
- this.proc = this.globalState.spawnService(
- "taler-merchant-httpd",
- [
- "taler-merchant-httpd",
- "-LDEBUG",
- "-c",
- this.configFilename,
- ...this.timetravelArgArr,
- ],
- `merchant-${this.merchantConfig.name}`,
- );
- }
-
- static async create(
- gc: GlobalTestState,
- mc: MerchantConfig,
- ): Promise<MerchantService> {
- const config = new Configuration();
- config.setString("taler", "currency", mc.currency);
-
- const cfgFilename = gc.testDir + `/merchant-${mc.name}.conf`;
- setTalerPaths(config, gc.testDir + "/talerhome");
- config.setString("merchant", "serve", "tcp");
- config.setString("merchant", "port", `${mc.httpPort}`);
- config.setString(
- "merchant",
- "keyfile",
- "${TALER_DATA_HOME}/merchant/merchant.priv",
- );
- config.setString("merchantdb-postgres", "config", mc.database);
- config.write(cfgFilename);
-
- return new MerchantService(gc, mc, cfgFilename);
- }
-
- addExchange(e: ExchangeServiceInterface): void {
- const config = Configuration.load(this.configFilename);
- config.setString(
- `merchant-exchange-${e.name}`,
- "exchange_base_url",
- e.baseUrl,
- );
- config.setString(
- `merchant-exchange-${e.name}`,
- "currency",
- this.merchantConfig.currency,
- );
- config.setString(`merchant-exchange-${e.name}`, "master_key", e.masterPub);
- config.write(this.configFilename);
- }
-
- async addDefaultInstance(): Promise<void> {
- return await this.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- auth: {
- method: "external",
- },
- });
- }
-
- async addInstance(
- instanceConfig: PartialMerchantInstanceConfig,
- ): Promise<void> {
- if (!this.proc) {
- throw Error("merchant must be running to add instance");
- }
- logger.info("adding instance");
- const url = `http://localhost:${this.merchantConfig.httpPort}/management/instances`;
- const auth = instanceConfig.auth ?? { method: "external" };
-
- const body: MerchantInstanceConfig = {
- auth,
- payto_uris: instanceConfig.paytoUris,
- id: instanceConfig.id,
- name: instanceConfig.name,
- address: instanceConfig.address ?? {},
- jurisdiction: instanceConfig.jurisdiction ?? {},
- default_max_wire_fee:
- instanceConfig.defaultMaxWireFee ??
- `${this.merchantConfig.currency}:1.0`,
- default_wire_fee_amortization:
- instanceConfig.defaultWireFeeAmortization ?? 3,
- default_max_deposit_fee:
- instanceConfig.defaultMaxDepositFee ??
- `${this.merchantConfig.currency}:1.0`,
- default_wire_transfer_delay:
- instanceConfig.defaultWireTransferDelay ??
- Duration.toTalerProtocolDuration(
- Duration.fromSpec({
- days: 1,
- }),
- ),
- default_pay_delay:
- instanceConfig.defaultPayDelay ??
- Duration.toTalerProtocolDuration(Duration.getForever()),
- };
- await axios.post(url, body);
- }
-
- makeInstanceBaseUrl(instanceName?: string): string {
- if (instanceName === undefined || instanceName === "default") {
- return `http://localhost:${this.merchantConfig.httpPort}/`;
- } else {
- return `http://localhost:${this.merchantConfig.httpPort}/instances/${instanceName}/`;
- }
- }
-
- async pingUntilAvailable(): Promise<void> {
- const url = `http://localhost:${this.merchantConfig.httpPort}/config`;
- await pingProc(this.proc, url, `merchant (${this.merchantConfig.name})`);
- }
-}
-
-export interface MerchantAuthConfiguration {
- method: "external" | "token";
- token?: string;
-}
-
-export interface PartialMerchantInstanceConfig {
- auth?: MerchantAuthConfiguration;
- id: string;
- name: string;
- paytoUris: string[];
- address?: unknown;
- jurisdiction?: unknown;
- defaultMaxWireFee?: string;
- defaultMaxDepositFee?: string;
- defaultWireFeeAmortization?: number;
- defaultWireTransferDelay?: TalerProtocolDuration;
- defaultPayDelay?: TalerProtocolDuration;
-}
-
-export interface MerchantInstanceConfig {
- auth: MerchantAuthConfiguration;
- id: string;
- name: string;
- payto_uris: string[];
- address: unknown;
- jurisdiction: unknown;
- default_max_wire_fee: string;
- default_max_deposit_fee: string;
- default_wire_fee_amortization: number;
- default_wire_transfer_delay: TalerProtocolDuration;
- default_pay_delay: TalerProtocolDuration;
-}
-
-type TestStatus = "pass" | "fail" | "skip";
-
-export interface TestRunResult {
- /**
- * Name of the test.
- */
- name: string;
-
- /**
- * How long did the test run?
- */
- timeSec: number;
-
- status: TestStatus;
-
- reason?: string;
-}
-
-export async function runTestWithState(
- gc: GlobalTestState,
- testMain: (t: GlobalTestState) => Promise<void>,
- testName: string,
- linger: boolean = false,
-): Promise<TestRunResult> {
- const startMs = new Date().getTime();
-
- const p = openPromise();
- let status: TestStatus;
-
- const handleSignal = (s: string) => {
- logger.warn(
- `**** received fatal process event, terminating test ${testName}`,
- );
- gc.shutdownSync();
- process.exit(1);
- };
-
- process.on("SIGINT", handleSignal);
- process.on("SIGTERM", handleSignal);
- process.on("unhandledRejection", handleSignal);
- process.on("uncaughtException", handleSignal);
-
- try {
- logger.info("running test in directory", gc.testDir);
- await Promise.race([testMain(gc), p.promise]);
- status = "pass";
- if (linger) {
- const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- terminal: true,
- });
- await new Promise<void>((resolve, reject) => {
- rl.question("Press enter to shut down test.", () => {
- logger.error("Requested shutdown");
- resolve();
- });
- });
- rl.close();
- }
- } catch (e) {
- console.error("FATAL: test failed with exception", e);
- if (e instanceof TalerError) {
- console.error(`error detail: ${j2s(e.errorDetail)}`);
- }
- status = "fail";
- } finally {
- await gc.shutdown();
- }
- const afterMs = new Date().getTime();
- return {
- name: testName,
- timeSec: (afterMs - startMs) / 1000,
- status,
- };
-}
-
-function shellWrap(s: string) {
- return "'" + s.replace("\\", "\\\\").replace("'", "\\'") + "'";
-}
-
-export interface WalletCliOpts {
- cryptoWorkerType?: "sync" | "node-worker-thread";
-}
-
-export class WalletCli {
- private currentTimetravel: Duration | undefined;
- private _client: WalletCoreApiClient;
-
- setTimetravel(d: Duration | undefined) {
- this.currentTimetravel = d;
- }
-
- private get timetravelArg(): string | undefined {
- if (this.currentTimetravel && this.currentTimetravel.d_ms !== "forever") {
- // Convert to microseconds
- return `--timetravel=${this.currentTimetravel.d_ms * 1000}`;
- }
- return undefined;
- }
-
- constructor(
- private globalTestState: GlobalTestState,
- private name: string = "default",
- cliOpts: WalletCliOpts = {},
- ) {
- const self = this;
- this._client = {
- async call(op: any, payload: any): Promise<any> {
- logger.info(
- `calling wallet with timetravel arg ${j2s(self.timetravelArg)}`,
- );
- const cryptoWorkerArg = cliOpts.cryptoWorkerType
- ? `--crypto-worker=${cliOpts.cryptoWorkerType}`
- : "";
- const resp = await sh(
- self.globalTestState,
- `wallet-${self.name}`,
- `taler-wallet-cli ${
- self.timetravelArg ?? ""
- } ${cryptoWorkerArg} --no-throttle -LTRACE --skip-defaults --wallet-db '${
- self.dbfile
- }' api '${op}' ${shellWrap(JSON.stringify(payload))}`,
- );
- logger.info("--- wallet core response ---");
- logger.info(resp);
- logger.info("--- end of response ---");
- let ar: any;
- try {
- ar = JSON.parse(resp) as CoreApiResponse;
- } catch (e) {
- throw new Error("wallet CLI did not return a proper JSON response");
- }
- if (ar.type === "error") {
- throw TalerError.fromUncheckedDetail(ar.error);
- }
- return ar.result;
- },
- };
- }
-
- get dbfile(): string {
- return this.globalTestState.testDir + `/walletdb-${this.name}.json`;
- }
-
- deleteDatabase() {
- fs.unlinkSync(this.dbfile);
- }
-
- private get timetravelArgArr(): string[] {
- const tta = this.timetravelArg;
- if (tta) {
- return [tta];
- }
- return [];
- }
-
- get client(): WalletCoreApiClient {
- return this._client;
- }
-
- async runUntilDone(args: { maxRetries?: number } = {}): Promise<void> {
- await runCommand(
- this.globalTestState,
- `wallet-${this.name}`,
- "taler-wallet-cli",
- [
- "--no-throttle",
- ...this.timetravelArgArr,
- "-LTRACE",
- "--skip-defaults",
- "--wallet-db",
- this.dbfile,
- "run-until-done",
- ...(args.maxRetries ? ["--max-retries", `${args.maxRetries}`] : []),
- ],
- );
- }
-
- async runPending(): Promise<void> {
- await runCommand(
- this.globalTestState,
- `wallet-${this.name}`,
- "taler-wallet-cli",
- [
- "--no-throttle",
- "--skip-defaults",
- "-LTRACE",
- ...this.timetravelArgArr,
- "--wallet-db",
- this.dbfile,
- "advanced",
- "run-pending",
- ],
- );
- }
-}
-
-export function getRandomIban(salt: string | null = null): string {
- function getBban(salt: string | null): string {
- if (!salt) return Math.random().toString().substring(2, 6);
- let hashed = hash(stringToBytes(salt));
- let ret = "";
- for (let i = 0; i < hashed.length; i++) {
- ret += hashed[i].toString();
- }
- return ret.substring(0, 4);
- }
-
- let cc_no_check = "131400"; // == DE00
- let bban = getBban(salt);
- let check_digits = (
- 98 -
- (Number.parseInt(`${bban}${cc_no_check}`) % 97)
- ).toString();
- if (check_digits.length == 1) {
- check_digits = `0${check_digits}`;
- }
- return `DE${check_digits}${bban}`;
-}
-
-export function getWireMethodForTest(): string {
- if (useLibeufinBank) return "iban";
- return "x-taler-bank";
-}
-
-/**
- * Generate a payto address, whose authority depends
- * on whether the banking is served by euFin or Pybank.
- */
-export function getPayto(label: string): string {
- if (useLibeufinBank)
- return `payto://iban/SANDBOXX/${getRandomIban(
- label,
- )}?receiver-name=${label}`;
- return `payto://x-taler-bank/localhost/${label}`;
-}
-
-function waitMs(ms: number): Promise<void> {
- return new Promise((resolve) => setTimeout(resolve, ms));
-}
diff --git a/packages/taler-wallet-cli/src/harness/helpers.ts b/packages/taler-wallet-cli/src/harness/helpers.ts
deleted file mode 100644
index affaccd61..000000000
--- a/packages/taler-wallet-cli/src/harness/helpers.ts
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- 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/>
- */
-
-/**
- * Helpers to create typical test environments.
- *
- * @author Florian Dold <dold@taler.net>
- */
-
-/**
- * Imports
- */
-import {
- AmountString,
- ConfirmPayResultType,
- MerchantContractTerms,
- Duration,
- PreparePayResultType,
-} from "@gnu-taler/taler-util";
-import {
- BankAccessApi,
- BankApi,
- HarnessExchangeBankAccount,
- WalletApiOperation,
-} from "@gnu-taler/taler-wallet-core";
-import { CoinConfig, defaultCoinConfig } from "./denomStructures.js";
-import {
- FaultInjectedExchangeService,
- FaultInjectedMerchantService,
-} from "./faultInjection.js";
-import {
- BankService,
- DbInfo,
- ExchangeService,
- ExchangeServiceInterface,
- getPayto,
- GlobalTestState,
- MerchantPrivateApi,
- MerchantService,
- MerchantServiceInterface,
- setupDb,
- WalletCli,
- WithAuthorization,
-} from "./harness.js";
-
-export interface SimpleTestEnvironment {
- commonDb: DbInfo;
- bank: BankService;
- exchange: ExchangeService;
- exchangeBankAccount: HarnessExchangeBankAccount;
- merchant: MerchantService;
- wallet: WalletCli;
-}
-
-export interface EnvOptions {
- /**
- * If provided, enable age restrictions with the specified age mask string.
- */
- ageMaskSpec?: string;
-
- mixedAgeRestriction?: boolean;
-}
-
-/**
- * Run a test case with a simple TESTKUDOS Taler environment, consisting
- * of one exchange, one bank and one merchant.
- */
-export async function createSimpleTestkudosEnvironment(
- t: GlobalTestState,
- coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS")),
- opts: EnvOptions = {},
-): Promise<SimpleTestEnvironment> {
- 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,
- });
-
- const exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
- exchange.addBankAccount("1", exchangeBankAccount);
-
- bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- 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);
- }
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- defaultWireTransferDelay: Duration.toTalerProtocolDuration(
- Duration.fromSpec({ minutes: 1 }),
- ),
- });
-
- await merchant.addInstance({
- id: "minst1",
- name: "minst1",
- paytoUris: [getPayto("minst1")],
- defaultWireTransferDelay: Duration.toTalerProtocolDuration(
- Duration.fromSpec({ minutes: 1 }),
- ),
- });
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- return {
- commonDb: db,
- exchange,
- merchant,
- wallet,
- bank,
- exchangeBankAccount,
- };
-}
-
-export interface FaultyMerchantTestEnvironment {
- commonDb: DbInfo;
- bank: BankService;
- exchange: ExchangeService;
- faultyExchange: FaultInjectedExchangeService;
- exchangeBankAccount: HarnessExchangeBankAccount;
- merchant: MerchantService;
- faultyMerchant: FaultInjectedMerchantService;
- wallet: WalletCli;
-}
-
-/**
- * Run a test case with a simple TESTKUDOS Taler environment, consisting
- * of one exchange, one bank and one merchant.
- */
-export async function createFaultInjectedMerchantTestkudosEnvironment(
- t: GlobalTestState,
-): Promise<FaultyMerchantTestEnvironment> {
- 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,
- });
-
- const faultyMerchant = new FaultInjectedMerchantService(t, merchant, 9083);
- const faultyExchange = new FaultInjectedExchangeService(t, exchange, 9081);
-
- const exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
- exchange.addBankAccount("1", exchangeBankAccount);
-
- bank.setSuggestedExchange(
- faultyExchange,
- exchangeBankAccount.accountPaytoUri,
- );
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- exchange.addOfferedCoins(defaultCoinConfig);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- merchant.addExchange(faultyExchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- });
-
- await merchant.addInstance({
- id: "minst1",
- name: "minst1",
- paytoUris: [getPayto("minst1")],
- });
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- return {
- commonDb: db,
- exchange,
- merchant,
- wallet,
- bank,
- exchangeBankAccount,
- faultyMerchant,
- faultyExchange,
- };
-}
-
-/**
- * Start withdrawing into the wallet.
- *
- * Only starts the operation, does not wait for it to finish.
- */
-export async function startWithdrawViaBank(
- t: GlobalTestState,
- p: {
- wallet: WalletCli;
- bank: BankService;
- exchange: ExchangeServiceInterface;
- amount: AmountString;
- restrictAge?: number;
- },
-): Promise<void> {
- const { wallet, bank, exchange, amount } = p;
-
- const user = await BankApi.createRandomBankUser(bank);
- const wop = await BankAccessApi.createWithdrawalOperation(bank, user, amount);
-
- // Hand it to the wallet
-
- await wallet.client.call(WalletApiOperation.GetWithdrawalDetailsForUri, {
- talerWithdrawUri: wop.taler_withdraw_uri,
- restrictAge: p.restrictAge,
- });
-
- await wallet.runPending();
-
- // Withdraw (AKA select)
-
- await wallet.client.call(WalletApiOperation.AcceptBankIntegratedWithdrawal, {
- exchangeBaseUrl: exchange.baseUrl,
- talerWithdrawUri: wop.taler_withdraw_uri,
- restrictAge: p.restrictAge,
- });
-
- // Confirm it
-
- await BankApi.confirmWithdrawalOperation(bank, user, wop);
-
- // We do *not* call runPending / runUntilDone on the wallet here.
- // Some tests rely on the final withdraw failing.
-}
-
-/**
- * Withdraw balance.
- */
-export async function withdrawViaBank(
- t: GlobalTestState,
- p: {
- wallet: WalletCli;
- bank: BankService;
- exchange: ExchangeServiceInterface;
- amount: AmountString;
- restrictAge?: number;
- },
-): Promise<void> {
- const { wallet } = p;
-
- await startWithdrawViaBank(t, p);
-
- await wallet.runUntilDone();
-
- // Check balance
-
- await wallet.client.call(WalletApiOperation.GetBalances, {});
-}
-
-export async function applyTimeTravel(
- timetravelDuration: Duration,
- s: {
- exchange?: ExchangeService;
- merchant?: MerchantService;
- wallet?: WalletCli;
- },
-): Promise<void> {
- if (s.exchange) {
- await s.exchange.stop();
- s.exchange.setTimetravel(timetravelDuration);
- await s.exchange.start();
- await s.exchange.pingUntilAvailable();
- }
-
- if (s.merchant) {
- await s.merchant.stop();
- s.merchant.setTimetravel(timetravelDuration);
- await s.merchant.start();
- await s.merchant.pingUntilAvailable();
- }
-
- if (s.wallet) {
- s.wallet.setTimetravel(timetravelDuration);
- }
-}
-
-/**
- * Make a simple payment and check that it succeeded.
- */
-export async function makeTestPayment(
- t: GlobalTestState,
- args: {
- merchant: MerchantServiceInterface;
- wallet: WalletCli;
- order: Partial<MerchantContractTerms>;
- instance?: string;
- },
- auth: WithAuthorization = {},
-): Promise<void> {
- // Set up order.
-
- const { wallet, merchant } = args;
- const instance = args.instance ?? "default";
-
- const orderResp = await MerchantPrivateApi.createOrder(
- merchant,
- instance,
- {
- order: args.order,
- },
- auth,
- );
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(
- merchant,
- {
- orderId: orderResp.order_id,
- },
- auth,
- );
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- // Make wallet pay for the order
-
- const preparePayResult = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: orderStatus.taler_pay_uri,
- },
- );
-
- t.assertTrue(
- preparePayResult.status === PreparePayResultType.PaymentPossible,
- );
-
- const r2 = await wallet.client.call(WalletApiOperation.ConfirmPay, {
- proposalId: preparePayResult.proposalId,
- });
-
- t.assertTrue(r2.type === ConfirmPayResultType.Done);
-
- // Check if payment was successful.
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(
- merchant,
- {
- orderId: orderResp.order_id,
- instance,
- },
- auth,
- );
-
- t.assertTrue(orderStatus.order_status === "paid");
-}
diff --git a/packages/taler-wallet-cli/src/harness/libeufin-apis.ts b/packages/taler-wallet-cli/src/harness/libeufin-apis.ts
deleted file mode 100644
index f55275927..000000000
--- a/packages/taler-wallet-cli/src/harness/libeufin-apis.ts
+++ /dev/null
@@ -1,872 +0,0 @@
-/**
- * This file defines most of the API calls offered
- * by Nexus and Sandbox. They don't have state,
- * therefore got moved away from libeufin.ts where
- * the services get actually started and managed.
- */
-
-import axiosImp from "axios";
-const axios = axiosImp.default;
-import { Logger, URL } from "@gnu-taler/taler-util";
-
-export interface LibeufinSandboxServiceInterface {
- baseUrl: string;
-}
-
-export interface LibeufinNexusServiceInterface {
- baseUrl: string;
-}
-
-export interface CreateEbicsSubscriberRequest {
- hostID: string;
- userID: string;
- partnerID: string;
- systemID?: string;
-}
-
-export interface BankAccountInfo {
- iban: string;
- bic: string;
- name: string;
- label: string;
-}
-
-export interface CreateEbicsBankConnectionRequest {
- name: string; // connection name.
- ebicsURL: string;
- hostID: string;
- userID: string;
- partnerID: string;
- systemID?: string;
-}
-
-export interface UpdateNexusUserRequest {
- newPassword: string;
-}
-
-export interface NexusAuth {
- auth: {
- username: string;
- password: string;
- };
-}
-
-export interface PostNexusTaskRequest {
- name: string;
- cronspec: string;
- type: string; // fetch | submit
- params:
- | {
- level: string; // report | statement | all
- rangeType: string; // all | since-last | previous-days | latest
- }
- | {};
-}
-
-export interface CreateNexusUserRequest {
- username: string;
- password: string;
-}
-
-export interface PostNexusPermissionRequest {
- action: "revoke" | "grant";
- permission: {
- subjectType: string;
- subjectId: string;
- resourceType: string;
- resourceId: string;
- permissionName: string;
- };
-}
-
-export interface CreateAnastasisFacadeRequest {
- name: string;
- connectionName: string;
- accountName: string;
- currency: string;
- reserveTransferLevel: "report" | "statement" | "notification";
-}
-
-export interface CreateTalerWireGatewayFacadeRequest {
- name: string;
- connectionName: string;
- accountName: string;
- currency: string;
- reserveTransferLevel: "report" | "statement" | "notification";
-}
-
-export interface SandboxAccountTransactions {
- payments: {
- accountLabel: string;
- creditorIban: string;
- creditorBic?: string;
- creditorName: string;
- debtorIban: string;
- debtorBic: string;
- debtorName: string;
- amount: string;
- currency: string;
- subject: string;
- date: string;
- creditDebitIndicator: "debit" | "credit";
- accountServicerReference: string;
- }[];
-}
-
-export interface DeleteBankConnectionRequest {
- bankConnectionId: string;
-}
-
-export interface SimulateIncomingTransactionRequest {
- debtorIban: string;
- debtorBic: string;
- debtorName: string;
-
- /**
- * Subject / unstructured remittance info.
- */
- subject: string;
-
- /**
- * Decimal amount without currency.
- */
- amount: string;
-}
-
-export interface CreateEbicsBankAccountRequest {
- subscriber: {
- hostID: string;
- partnerID: string;
- userID: string;
- systemID?: string;
- };
- // IBAN
- iban: string;
- // BIC
- bic: string;
- // human name
- name: string;
- label: string;
-}
-
-export interface LibeufinSandboxAddIncomingRequest {
- creditorIban: string;
- creditorBic: string;
- creditorName: string;
- debtorIban: string;
- debtorBic: string;
- debtorName: string;
- subject: string;
- amount: string;
- currency: string;
- uid: string;
- direction: string;
-}
-
-function getRandomString(): string {
- return Math.random().toString(36).substring(2);
-}
-
-/**
- * APIs spread accross Legacy and Access, it is therefore
- * the "base URL" relative to which API every call addresses.
- */
-export namespace LibeufinSandboxApi {
- // Need Access API base URL.
- export async function demobankAccountInfo(
- username: string,
- password: string,
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- accountLabel: string,
- ) {
- let url = new URL(
- `accounts/${accountLabel}`,
- libeufinSandboxService.baseUrl,
- );
- return await axios.get(url.href, {
- auth: {
- username: username,
- password: password,
- },
- });
- }
-
- // Creates one bank account via the Access API.
- // Need the /demobanks/$id/access-api as the base URL
- export async function createDemobankAccount(
- username: string,
- password: string,
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- iban: string|null = null,
- ) {
- let url = new URL(
- "testing/register",
- libeufinSandboxService.baseUrl
- );
- await axios.post(url.href, {
- username: username,
- password: password,
- iban: iban
- });
- }
- // Need /demobanks/$id as the base URL
- export async function createDemobankEbicsSubscriber(
- req: CreateEbicsSubscriberRequest,
- demobankAccountLabel: string,
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- username: string = "admin",
- password: string = "secret",
- ) {
- // baseUrl should already be pointed to one demobank.
- let url = new URL(
- "ebics/subscribers",
- libeufinSandboxService.baseUrl
- );
- await axios.post(
- url.href,
- {
- userID: req.userID,
- hostID: req.hostID,
- partnerID: req.partnerID,
- demobankAccountLabel: demobankAccountLabel,
- },
- {
- auth: {
- username: "admin",
- password: "secret",
- },
- },
- );
- }
-
- export async function rotateKeys(
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- hostID: string,
- ) {
- const baseUrl = libeufinSandboxService.baseUrl;
- let url = new URL(`admin/ebics/hosts/${hostID}/rotate-keys`, baseUrl);
- await axios.post(
- url.href,
- {},
- {
- auth: {
- username: "admin",
- password: "secret",
- },
- },
- );
- }
- export async function createEbicsHost(
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- hostID: string,
- ) {
- const baseUrl = libeufinSandboxService.baseUrl;
- let url = new URL("admin/ebics/hosts", baseUrl);
- await axios.post(
- url.href,
- {
- hostID,
- ebicsVersion: "2.5",
- },
- {
- auth: {
- username: "admin",
- password: "secret",
- },
- },
- );
- }
-
- export async function createBankAccount(
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- req: BankAccountInfo,
- ) {
- const baseUrl = libeufinSandboxService.baseUrl;
- let url = new URL(`admin/bank-accounts/${req.label}`, baseUrl);
- await axios.post(url.href, req, {
- auth: {
- username: "admin",
- password: "secret",
- },
- });
- }
-
- /**
- * This function is useless. It creates a Ebics subscriber
- * but never gives it a bank account. To be removed
- */
- export async function createEbicsSubscriber(
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- req: CreateEbicsSubscriberRequest,
- ) {
- const baseUrl = libeufinSandboxService.baseUrl;
- let url = new URL("admin/ebics/subscribers", baseUrl);
- await axios.post(url.href, req, {
- auth: {
- username: "admin",
- password: "secret",
- },
- });
- }
-
- /**
- * Create a new bank account and associate it to
- * a existing EBICS subscriber.
- */
- export async function createEbicsBankAccount(
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- req: CreateEbicsBankAccountRequest,
- ) {
- const baseUrl = libeufinSandboxService.baseUrl;
- let url = new URL("admin/ebics/bank-accounts", baseUrl);
- await axios.post(url.href, req, {
- auth: {
- username: "admin",
- password: "secret",
- },
- });
- }
-
- export async function simulateIncomingTransaction(
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- accountLabel: string,
- req: SimulateIncomingTransactionRequest,
- ) {
- const baseUrl = libeufinSandboxService.baseUrl;
- let url = new URL(
- `admin/bank-accounts/${accountLabel}/simulate-incoming-transaction`,
- baseUrl,
- );
- await axios.post(url.href, req, {
- auth: {
- username: "admin",
- password: "secret",
- },
- });
- }
-
- export async function getAccountTransactions(
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- accountLabel: string,
- ): Promise<SandboxAccountTransactions> {
- const baseUrl = libeufinSandboxService.baseUrl;
- let url = new URL(
- `admin/bank-accounts/${accountLabel}/transactions`,
- baseUrl,
- );
- const res = await axios.get(url.href, {
- auth: {
- username: "admin",
- password: "secret",
- },
- });
- return res.data as SandboxAccountTransactions;
- }
-
- export async function getCamt053(
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- accountLabel: string,
- ): Promise<any> {
- const baseUrl = libeufinSandboxService.baseUrl;
- let url = new URL("admin/payments/camt", baseUrl);
- return await axios.post(
- url.href,
- {
- bankaccount: accountLabel,
- type: 53,
- },
- {
- auth: {
- username: "admin",
- password: "secret",
- },
- },
- );
- }
-
- export async function getAccountInfoWithBalance(
- libeufinSandboxService: LibeufinSandboxServiceInterface,
- accountLabel: string,
- ): Promise<any> {
- const baseUrl = libeufinSandboxService.baseUrl;
- let url = new URL(`admin/bank-accounts/${accountLabel}`, baseUrl);
- return await axios.get(url.href, {
- auth: {
- username: "admin",
- password: "secret",
- },
- });
- }
-}
-
-export namespace LibeufinNexusApi {
- export async function getAllConnections(
- nexus: LibeufinNexusServiceInterface,
- ): Promise<any> {
- let url = new URL("bank-connections", nexus.baseUrl);
- const res = await axios.get(url.href, {
- auth: {
- username: "admin",
- password: "test",
- },
- });
- return res;
- }
-
- export async function deleteBankConnection(
- libeufinNexusService: LibeufinNexusServiceInterface,
- req: DeleteBankConnectionRequest,
- ): Promise<any> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL("bank-connections/delete-connection", baseUrl);
- return await axios.post(url.href, req, {
- auth: {
- username: "admin",
- password: "test",
- },
- });
- }
-
- export async function createEbicsBankConnection(
- libeufinNexusService: LibeufinNexusServiceInterface,
- req: CreateEbicsBankConnectionRequest,
- ): Promise<void> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL("bank-connections", baseUrl);
- await axios.post(
- url.href,
- {
- source: "new",
- type: "ebics",
- name: req.name,
- data: {
- ebicsURL: req.ebicsURL,
- hostID: req.hostID,
- userID: req.userID,
- partnerID: req.partnerID,
- systemID: req.systemID,
- },
- },
- {
- auth: {
- username: "admin",
- password: "test",
- },
- },
- );
- }
-
- export async function getBankAccount(
- libeufinNexusService: LibeufinNexusServiceInterface,
- accountName: string,
- ): Promise<any> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`bank-accounts/${accountName}`, baseUrl);
- return await axios.get(url.href, {
- auth: {
- username: "admin",
- password: "test",
- },
- });
- }
-
- export async function submitInitiatedPayment(
- libeufinNexusService: LibeufinNexusServiceInterface,
- accountName: string,
- paymentId: string,
- ): Promise<void> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(
- `bank-accounts/${accountName}/payment-initiations/${paymentId}/submit`,
- baseUrl,
- );
- await axios.post(
- url.href,
- {},
- {
- auth: {
- username: "admin",
- password: "test",
- },
- },
- );
- }
-
- export async function fetchAccounts(
- libeufinNexusService: LibeufinNexusServiceInterface,
- connectionName: string,
- ): Promise<void> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(
- `bank-connections/${connectionName}/fetch-accounts`,
- baseUrl,
- );
- await axios.post(
- url.href,
- {},
- {
- auth: {
- username: "admin",
- password: "test",
- },
- },
- );
- }
-
- export async function importConnectionAccount(
- libeufinNexusService: LibeufinNexusServiceInterface,
- connectionName: string,
- offeredAccountId: string,
- nexusBankAccountId: string,
- ): Promise<void> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(
- `bank-connections/${connectionName}/import-account`,
- baseUrl,
- );
- await axios.post(
- url.href,
- {
- offeredAccountId,
- nexusBankAccountId,
- },
- {
- auth: {
- username: "admin",
- password: "test",
- },
- },
- );
- }
-
- export async function connectBankConnection(
- libeufinNexusService: LibeufinNexusServiceInterface,
- connectionName: string,
- ) {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`bank-connections/${connectionName}/connect`, baseUrl);
- await axios.post(
- url.href,
- {},
- {
- auth: {
- username: "admin",
- password: "test",
- },
- },
- );
- }
-
- export async function getPaymentInitiations(
- libeufinNexusService: LibeufinNexusServiceInterface,
- accountName: string,
- username: string = "admin",
- password: string = "test",
- ): Promise<void> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(
- `/bank-accounts/${accountName}/payment-initiations`,
- baseUrl,
- );
- let response = await axios.get(url.href, {
- auth: {
- username: username,
- password: password,
- },
- });
- console.log(
- `Payment initiations of: ${accountName}`,
- JSON.stringify(response.data, null, 2),
- );
- }
-
- export async function getConfig(
- libeufinNexusService: LibeufinNexusServiceInterface,
- ): Promise<void> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`/config`, baseUrl);
- let response = await axios.get(url.href);
- }
-
- // Uses the Anastasis API to get a list of transactions.
- export async function getAnastasisTransactions(
- libeufinNexusService: LibeufinNexusServiceInterface,
- anastasisBaseUrl: string,
- params: {}, // of the request: {delta: 5, ..}
- username: string = "admin",
- password: string = "test",
- ): Promise<any> {
- let url = new URL("history/incoming", anastasisBaseUrl);
- let response = await axios.get(url.href, {
- params: params,
- auth: {
- username: username,
- password: password,
- },
- });
- return response;
- }
-
- // FIXME: this function should return some structured
- // object that represents a history.
- export async function getAccountTransactions(
- libeufinNexusService: LibeufinNexusServiceInterface,
- accountName: string,
- username: string = "admin",
- password: string = "test",
- ): Promise<any> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`/bank-accounts/${accountName}/transactions`, baseUrl);
- let response = await axios.get(url.href, {
- auth: {
- username: username,
- password: password,
- },
- });
- return response;
- }
-
- export async function fetchTransactions(
- libeufinNexusService: LibeufinNexusServiceInterface,
- accountName: string,
- rangeType: string = "all",
- level: string = "report",
- username: string = "admin",
- password: string = "test",
- ): Promise<any> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(
- `/bank-accounts/${accountName}/fetch-transactions`,
- baseUrl,
- );
- return await axios.post(
- url.href,
- {
- rangeType: rangeType,
- level: level,
- },
- {
- auth: {
- username: username,
- password: password,
- },
- },
- );
- }
-
- export async function changePassword(
- libeufinNexusService: LibeufinNexusServiceInterface,
- username: string,
- req: UpdateNexusUserRequest,
- auth: NexusAuth,
- ) {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`/users/${username}/password`, baseUrl);
- await axios.post(url.href, req, auth);
- }
-
- export async function getUser(
- libeufinNexusService: LibeufinNexusServiceInterface,
- auth: NexusAuth,
- ): Promise<any> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`/user`, baseUrl);
- return await axios.get(url.href, auth);
- }
-
- export async function createUser(
- libeufinNexusService: LibeufinNexusServiceInterface,
- req: CreateNexusUserRequest,
- ) {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`/users`, baseUrl);
- await axios.post(url.href, req, {
- auth: {
- username: "admin",
- password: "test",
- },
- });
- }
-
- export async function getAllPermissions(
- libeufinNexusService: LibeufinNexusServiceInterface,
- ): Promise<any> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`/permissions`, baseUrl);
- return await axios.get(url.href, {
- auth: {
- username: "admin",
- password: "test",
- },
- });
- }
-
- export async function postPermission(
- libeufinNexusService: LibeufinNexusServiceInterface,
- req: PostNexusPermissionRequest,
- ) {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`/permissions`, baseUrl);
- await axios.post(url.href, req, {
- auth: {
- username: "admin",
- password: "test",
- },
- });
- }
-
- export async function getTasks(
- libeufinNexusService: LibeufinNexusServiceInterface,
- bankAccountName: string,
- // When void, the request returns the list of all the
- // tasks under this bank account.
- taskName: string | void,
- ): Promise<any> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`/bank-accounts/${bankAccountName}/schedule`, baseUrl);
- if (taskName) url = new URL(taskName, `${url.href}/`);
-
- // It's caller's responsibility to interpret the response.
- return await axios.get(url.href, {
- auth: {
- username: "admin",
- password: "test",
- },
- });
- }
-
- export async function deleteTask(
- libeufinNexusService: LibeufinNexusServiceInterface,
- bankAccountName: string,
- taskName: string,
- ) {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(
- `/bank-accounts/${bankAccountName}/schedule/${taskName}`,
- baseUrl,
- );
- await axios.delete(url.href, {
- auth: {
- username: "admin",
- password: "test",
- },
- });
- }
-
- export async function postTask(
- libeufinNexusService: LibeufinNexusServiceInterface,
- bankAccountName: string,
- req: PostNexusTaskRequest,
- ): Promise<any> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`/bank-accounts/${bankAccountName}/schedule`, baseUrl);
- return await axios.post(url.href, req, {
- auth: {
- username: "admin",
- password: "test",
- },
- });
- }
-
- export async function deleteFacade(
- libeufinNexusService: LibeufinNexusServiceInterface,
- facadeName: string,
- ): Promise<any> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(`facades/${facadeName}`, baseUrl);
- return await axios.delete(url.href, {
- auth: {
- username: "admin",
- password: "test",
- },
- });
- }
-
- export async function getAllFacades(
- libeufinNexusService: LibeufinNexusServiceInterface,
- ): Promise<any> {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL("facades", baseUrl);
- return await axios.get(url.href, {
- auth: {
- username: "admin",
- password: "test",
- },
- });
- }
-
- export async function createAnastasisFacade(
- libeufinNexusService: LibeufinNexusServiceInterface,
- req: CreateAnastasisFacadeRequest,
- ) {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL("facades", baseUrl);
- await axios.post(
- url.href,
- {
- name: req.name,
- type: "anastasis",
- config: {
- bankAccount: req.accountName,
- bankConnection: req.connectionName,
- currency: req.currency,
- reserveTransferLevel: req.reserveTransferLevel,
- },
- },
- {
- auth: {
- username: "admin",
- password: "test",
- },
- },
- );
- }
-
- export async function createTwgFacade(
- libeufinNexusService: LibeufinNexusServiceInterface,
- req: CreateTalerWireGatewayFacadeRequest,
- ) {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL("facades", baseUrl);
- await axios.post(
- url.href,
- {
- name: req.name,
- type: "taler-wire-gateway",
- config: {
- bankAccount: req.accountName,
- bankConnection: req.connectionName,
- currency: req.currency,
- reserveTransferLevel: req.reserveTransferLevel,
- },
- },
- {
- auth: {
- username: "admin",
- password: "test",
- },
- },
- );
- }
-
- export async function submitAllPaymentInitiations(
- libeufinNexusService: LibeufinNexusServiceInterface,
- accountId: string,
- ) {
- const baseUrl = libeufinNexusService.baseUrl;
- let url = new URL(
- `/bank-accounts/${accountId}/submit-all-payment-initiations`,
- baseUrl,
- );
- await axios.post(
- url.href,
- {},
- {
- auth: {
- username: "admin",
- password: "test",
- },
- },
- );
- }
-}
diff --git a/packages/taler-wallet-cli/src/harness/libeufin.ts b/packages/taler-wallet-cli/src/harness/libeufin.ts
deleted file mode 100644
index 638c8ed90..000000000
--- a/packages/taler-wallet-cli/src/harness/libeufin.ts
+++ /dev/null
@@ -1,910 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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/>
- */
-
-/**
- * This file defines euFin test logic that needs state
- * and that depends on the main harness.ts. The other
- * definitions - mainly helper functions to call RESTful
- * APIs - moved to libeufin-apis.ts. That enables harness.ts
- * to depend on such API calls, in contrast to the previous
- * situation where harness.ts had to include this file causing
- * a circular dependency. */
-
-/**
- * Imports.
- */
-import axios from "axios";
-import { URL, Logger } from "@gnu-taler/taler-util";
-import {
- GlobalTestState,
- DbInfo,
- pingProc,
- ProcessWrapper,
- runCommand,
- setupDb,
- sh,
- getRandomIban,
-} from "../harness/harness.js";
-import {
- LibeufinSandboxApi,
- LibeufinNexusApi,
- CreateEbicsBankAccountRequest,
- LibeufinSandboxServiceInterface,
- CreateTalerWireGatewayFacadeRequest,
- SimulateIncomingTransactionRequest,
- SandboxAccountTransactions,
- DeleteBankConnectionRequest,
- CreateEbicsBankConnectionRequest,
- UpdateNexusUserRequest,
- NexusAuth,
- CreateAnastasisFacadeRequest,
- PostNexusTaskRequest,
- PostNexusPermissionRequest,
- CreateNexusUserRequest,
-} from "../harness/libeufin-apis.js";
-
-
-const logger = new Logger("libeufin.ts");
-
-export { LibeufinSandboxApi, LibeufinNexusApi };
-
-export interface LibeufinServices {
- libeufinSandbox: LibeufinSandboxService;
- libeufinNexus: LibeufinNexusService;
- commonDb: DbInfo;
-}
-
-export interface LibeufinSandboxConfig {
- httpPort: number;
- databaseJdbcUri: string;
-}
-
-export interface LibeufinNexusConfig {
- httpPort: number;
- databaseJdbcUri: string;
-}
-
-interface LibeufinNexusMoneyMovement {
- amount: string;
- creditDebitIndicator: string;
- details: {
- debtor: {
- name: string;
- };
- debtorAccount: {
- iban: string;
- };
- debtorAgent: {
- bic: string;
- };
- creditor: {
- name: string;
- };
- creditorAccount: {
- iban: string;
- };
- creditorAgent: {
- bic: string;
- };
- endToEndId: string;
- unstructuredRemittanceInformation: string;
- };
-}
-
-interface LibeufinNexusBatches {
- batchTransactions: Array<LibeufinNexusMoneyMovement>;
-}
-
-interface LibeufinNexusTransaction {
- amount: string;
- creditDebitIndicator: string;
- status: string;
- bankTransactionCode: string;
- valueDate: string;
- bookingDate: string;
- accountServicerRef: string;
- batches: Array<LibeufinNexusBatches>;
-}
-
-interface LibeufinNexusTransactions {
- transactions: Array<LibeufinNexusTransaction>;
-}
-
-export interface LibeufinCliDetails {
- nexusUrl: string;
- sandboxUrl: string;
- nexusDatabaseUri: string;
- sandboxDatabaseUri: string;
- nexusUser: LibeufinNexusUser;
-}
-
-export interface LibeufinEbicsSubscriberDetails {
- hostId: string;
- partnerId: string;
- userId: string;
-}
-
-export interface LibeufinEbicsConnectionDetails {
- subscriberDetails: LibeufinEbicsSubscriberDetails;
- ebicsUrl: string;
- connectionName: string;
-}
-
-export interface LibeufinBankAccountDetails {
- currency: string;
- iban: string;
- bic: string;
- personName: string;
- accountName: string;
-}
-
-export interface LibeufinNexusUser {
- username: string;
- password: string;
-}
-
-export interface LibeufinBackupFileDetails {
- passphrase: string;
- outputFile: string;
- connectionName: string;
-}
-
-export interface LibeufinKeyLetterDetails {
- outputFile: string;
- connectionName: string;
-}
-
-export interface LibeufinBankAccountImportDetails {
- offeredBankAccountName: string;
- nexusBankAccountName: string;
- connectionName: string;
-}
-
-export interface LibeufinPreparedPaymentDetails {
- creditorIban: string;
- creditorBic: string;
- creditorName: string;
- subject: string;
- amount: string;
- currency: string;
- nexusBankAccountName: string;
-}
-
-export class LibeufinSandboxService implements LibeufinSandboxServiceInterface {
- static async create(
- gc: GlobalTestState,
- sandboxConfig: LibeufinSandboxConfig,
- ): Promise<LibeufinSandboxService> {
- return new LibeufinSandboxService(gc, sandboxConfig);
- }
-
- sandboxProc: ProcessWrapper | undefined;
- globalTestState: GlobalTestState;
-
- constructor(
- gc: GlobalTestState,
- private sandboxConfig: LibeufinSandboxConfig,
- ) {
- this.globalTestState = gc;
- }
-
- get baseUrl(): string {
- return `http://localhost:${this.sandboxConfig.httpPort}/`;
- }
-
- async start(): Promise<void> {
- await sh(
- this.globalTestState,
- "libeufin-sandbox-config",
- "libeufin-sandbox config default",
- {
- ...process.env,
- LIBEUFIN_SANDBOX_DB_CONNECTION: this.sandboxConfig.databaseJdbcUri,
- },
- );
-
- this.sandboxProc = this.globalTestState.spawnService(
- "libeufin-sandbox",
- ["serve", "--port", `${this.sandboxConfig.httpPort}`],
- "libeufin-sandbox",
- {
- ...process.env,
- LIBEUFIN_SANDBOX_DB_CONNECTION: this.sandboxConfig.databaseJdbcUri,
- LIBEUFIN_SANDBOX_ADMIN_PASSWORD: "secret",
- },
- );
- }
-
- async c53tick(): Promise<string> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-sandbox-c53tick",
- "libeufin-sandbox camt053tick",
- {
- ...process.env,
- LIBEUFIN_SANDBOX_DB_CONNECTION: this.sandboxConfig.databaseJdbcUri,
- },
- );
- return stdout;
- }
-
- async makeTransaction(
- debit: string,
- credit: string,
- amount: string, // $currency:x.y
- subject: string,
- ): Promise<string> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-sandbox-maketransfer",
- `libeufin-sandbox make-transaction --debit-account=${debit} --credit-account=${credit} ${amount} "${subject}"`,
- {
- ...process.env,
- LIBEUFIN_SANDBOX_DB_CONNECTION: this.sandboxConfig.databaseJdbcUri,
- },
- );
- return stdout;
- }
-
- async pingUntilAvailable(): Promise<void> {
- const url = this.baseUrl;
- await pingProc(this.sandboxProc, url, "libeufin-sandbox");
- }
-}
-
-export class LibeufinNexusService {
- static async create(
- gc: GlobalTestState,
- nexusConfig: LibeufinNexusConfig,
- ): Promise<LibeufinNexusService> {
- return new LibeufinNexusService(gc, nexusConfig);
- }
-
- nexusProc: ProcessWrapper | undefined;
- globalTestState: GlobalTestState;
-
- constructor(gc: GlobalTestState, private nexusConfig: LibeufinNexusConfig) {
- this.globalTestState = gc;
- }
-
- get baseUrl(): string {
- return `http://localhost:${this.nexusConfig.httpPort}/`;
- }
-
- async start(): Promise<void> {
- await runCommand(
- this.globalTestState,
- "libeufin-nexus-superuser",
- "libeufin-nexus",
- ["superuser", "admin", "--password", "test"],
- {
- ...process.env,
- LIBEUFIN_NEXUS_DB_CONNECTION: this.nexusConfig.databaseJdbcUri,
- },
- );
-
- this.nexusProc = this.globalTestState.spawnService(
- "libeufin-nexus",
- ["serve", "--port", `${this.nexusConfig.httpPort}`],
- "libeufin-nexus",
- {
- ...process.env,
- LIBEUFIN_NEXUS_DB_CONNECTION: this.nexusConfig.databaseJdbcUri,
- },
- );
- }
-
- async pingUntilAvailable(): Promise<void> {
- const url = `${this.baseUrl}config`;
- await pingProc(this.nexusProc, url, "libeufin-nexus");
- }
-
- async createNexusSuperuser(details: LibeufinNexusUser): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-nexus",
- `libeufin-nexus superuser ${details.username} --password=${details.password}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_DB_CONNECTION: this.nexusConfig.databaseJdbcUri,
- },
- );
- console.log(stdout);
- }
-}
-
-export interface TwgAddIncomingRequest {
- amount: string;
- reserve_pub: string;
- debit_account: string;
-}
-
-/**
- * The bundle aims at minimizing the amount of input
- * data that is required to initialize a new user + Ebics
- * connection.
- */
-export class NexusUserBundle {
- userReq: CreateNexusUserRequest;
- connReq: CreateEbicsBankConnectionRequest;
- anastasisReq: CreateAnastasisFacadeRequest;
- twgReq: CreateTalerWireGatewayFacadeRequest;
- twgTransferPermission: PostNexusPermissionRequest;
- twgHistoryPermission: PostNexusPermissionRequest;
- twgAddIncomingPermission: PostNexusPermissionRequest;
- localAccountName: string;
- remoteAccountName: string;
-
- constructor(salt: string, ebicsURL: string) {
- this.userReq = {
- username: `username-${salt}`,
- password: `password-${salt}`,
- };
-
- this.connReq = {
- name: `connection-${salt}`,
- ebicsURL: ebicsURL,
- hostID: `ebicshost,${salt}`,
- partnerID: `ebicspartner,${salt}`,
- userID: `ebicsuser,${salt}`,
- };
-
- this.twgReq = {
- currency: "EUR",
- name: `twg-${salt}`,
- reserveTransferLevel: "report",
- accountName: `local-account-${salt}`,
- connectionName: `connection-${salt}`,
- };
- this.anastasisReq = {
- currency: "EUR",
- name: `anastasis-${salt}`,
- reserveTransferLevel: "report",
- accountName: `local-account-${salt}`,
- connectionName: `connection-${salt}`,
- };
- this.remoteAccountName = `remote-account-${salt}`;
- this.localAccountName = `local-account-${salt}`;
- this.twgTransferPermission = {
- action: "grant",
- permission: {
- subjectId: `username-${salt}`,
- subjectType: "user",
- resourceType: "facade",
- resourceId: `twg-${salt}`,
- permissionName: "facade.talerWireGateway.transfer",
- },
- };
- this.twgHistoryPermission = {
- action: "grant",
- permission: {
- subjectId: `username-${salt}`,
- subjectType: "user",
- resourceType: "facade",
- resourceId: `twg-${salt}`,
- permissionName: "facade.talerWireGateway.history",
- },
- };
- }
-}
-
-/**
- * The bundle aims at minimizing the amount of input
- * data that is required to initialize a new Sandbox
- * customer, associating their bank account with a Ebics
- * subscriber.
- */
-export class SandboxUserBundle {
- ebicsBankAccount: CreateEbicsBankAccountRequest;
- constructor(salt: string) {
- this.ebicsBankAccount = {
- bic: "BELADEBEXXX",
- iban: getRandomIban(),
- label: `remote-account-${salt}`,
- name: `Taler Exchange: ${salt}`,
- subscriber: {
- hostID: `ebicshost,${salt}`,
- partnerID: `ebicspartner,${salt}`,
- userID: `ebicsuser,${salt}`,
- },
- };
- }
-}
-
-export class LibeufinCli {
- cliDetails: LibeufinCliDetails;
- globalTestState: GlobalTestState;
-
- constructor(gc: GlobalTestState, cd: LibeufinCliDetails) {
- this.globalTestState = gc;
- this.cliDetails = cd;
- }
-
- env(): any {
- return {
- ...process.env,
- LIBEUFIN_SANDBOX_URL: this.cliDetails.sandboxUrl,
- LIBEUFIN_SANDBOX_USERNAME: "admin",
- LIBEUFIN_SANDBOX_PASSWORD: "secret",
- };
- }
-
- async checkSandbox(): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-checksandbox",
- "libeufin-cli sandbox check",
- this.env(),
- );
- }
-
- async registerBankCustomer(username: string, password: string): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-registercustomer",
- "libeufin-cli sandbox demobank register --name='Test Customer'",
- {
- ...process.env,
- LIBEUFIN_SANDBOX_URL: this.cliDetails.sandboxUrl + "/demobanks/default",
- LIBEUFIN_SANDBOX_USERNAME: username,
- LIBEUFIN_SANDBOX_PASSWORD: password,
- },
- );
- console.log(stdout);
- }
-
- async createEbicsHost(hostId: string): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-createebicshost",
- `libeufin-cli sandbox ebicshost create --host-id=${hostId}`,
- this.env(),
- );
- console.log(stdout);
- }
-
- async createEbicsSubscriber(
- details: LibeufinEbicsSubscriberDetails,
- ): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-createebicssubscriber",
- "libeufin-cli sandbox ebicssubscriber create" +
- ` --host-id=${details.hostId}` +
- ` --partner-id=${details.partnerId}` +
- ` --user-id=${details.userId}`,
- this.env(),
- );
- console.log(stdout);
- }
-
- async createEbicsBankAccount(
- sd: LibeufinEbicsSubscriberDetails,
- bankAccountDetails: LibeufinBankAccountDetails,
- ): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-createebicsbankaccount",
- "libeufin-cli sandbox ebicsbankaccount create" +
- ` --iban=${bankAccountDetails.iban}` +
- ` --bic=${bankAccountDetails.bic}` +
- ` --person-name='${bankAccountDetails.personName}'` +
- ` --account-name=${bankAccountDetails.accountName}` +
- ` --ebics-host-id=${sd.hostId}` +
- ` --ebics-partner-id=${sd.partnerId}` +
- ` --ebics-user-id=${sd.userId}`,
- this.env(),
- );
- console.log(stdout);
- }
-
- async generateTransactions(accountName: string): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-generatetransactions",
- `libeufin-cli sandbox bankaccount generate-transactions ${accountName}`,
- this.env(),
- );
- console.log(stdout);
- }
-
- async showSandboxTransactions(accountName: string): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-showsandboxtransactions",
- `libeufin-cli sandbox bankaccount transactions ${accountName}`,
- this.env(),
- );
- console.log(stdout);
- }
-
- async createEbicsConnection(
- connectionDetails: LibeufinEbicsConnectionDetails,
- ): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-createebicsconnection",
- `libeufin-cli connections new-ebics-connection` +
- ` --ebics-url=${connectionDetails.ebicsUrl}` +
- ` --host-id=${connectionDetails.subscriberDetails.hostId}` +
- ` --partner-id=${connectionDetails.subscriberDetails.partnerId}` +
- ` --ebics-user-id=${connectionDetails.subscriberDetails.userId}` +
- ` ${connectionDetails.connectionName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async createBackupFile(details: LibeufinBackupFileDetails): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-createbackupfile",
- `libeufin-cli connections export-backup` +
- ` --passphrase=${details.passphrase}` +
- ` --output-file=${details.outputFile}` +
- ` ${details.connectionName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async createKeyLetter(details: LibeufinKeyLetterDetails): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-createkeyletter",
- `libeufin-cli connections get-key-letter` +
- ` ${details.connectionName} ${details.outputFile}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async connect(connectionName: string): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-connect",
- `libeufin-cli connections connect ${connectionName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async downloadBankAccounts(connectionName: string): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-downloadbankaccounts",
- `libeufin-cli connections download-bank-accounts ${connectionName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async listOfferedBankAccounts(connectionName: string): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-listofferedbankaccounts",
- `libeufin-cli connections list-offered-bank-accounts ${connectionName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async importBankAccount(
- importDetails: LibeufinBankAccountImportDetails,
- ): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-importbankaccount",
- "libeufin-cli connections import-bank-account" +
- ` --offered-account-id=${importDetails.offeredBankAccountName}` +
- ` --nexus-bank-account-id=${importDetails.nexusBankAccountName}` +
- ` ${importDetails.connectionName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async fetchTransactions(bankAccountName: string): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-fetchtransactions",
- `libeufin-cli accounts fetch-transactions ${bankAccountName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async transactions(bankAccountName: string): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-transactions",
- `libeufin-cli accounts transactions ${bankAccountName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async preparePayment(details: LibeufinPreparedPaymentDetails): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-preparepayment",
- `libeufin-cli accounts prepare-payment` +
- ` --creditor-iban=${details.creditorIban}` +
- ` --creditor-bic=${details.creditorBic}` +
- ` --creditor-name='${details.creditorName}'` +
- ` --payment-subject='${details.subject}'` +
- ` --payment-amount=${details.currency}:${details.amount}` +
- ` ${details.nexusBankAccountName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async submitPayment(
- details: LibeufinPreparedPaymentDetails,
- paymentUuid: string,
- ): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-submitpayments",
- `libeufin-cli accounts submit-payments` +
- ` --payment-uuid=${paymentUuid}` +
- ` ${details.nexusBankAccountName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async newAnastasisFacade(req: NewAnastasisFacadeReq): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-new-anastasis-facade",
- `libeufin-cli facades new-anastasis-facade` +
- ` --currency ${req.currency}` +
- ` --facade-name ${req.facadeName}` +
- ` ${req.connectionName} ${req.accountName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async newTalerWireGatewayFacade(req: NewTalerWireGatewayReq): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-new-taler-wire-gateway-facade",
- `libeufin-cli facades new-taler-wire-gateway-facade` +
- ` --currency ${req.currency}` +
- ` --facade-name ${req.facadeName}` +
- ` ${req.connectionName} ${req.accountName}`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-
- async listFacades(): Promise<void> {
- const stdout = await sh(
- this.globalTestState,
- "libeufin-cli-facades-list",
- `libeufin-cli facades list`,
- {
- ...process.env,
- LIBEUFIN_NEXUS_URL: this.cliDetails.nexusUrl,
- LIBEUFIN_NEXUS_USERNAME: this.cliDetails.nexusUser.username,
- LIBEUFIN_NEXUS_PASSWORD: this.cliDetails.nexusUser.password,
- },
- );
- console.log(stdout);
- }
-}
-
-interface NewAnastasisFacadeReq {
- facadeName: string;
- connectionName: string;
- accountName: string;
- currency: string;
-}
-
-interface NewTalerWireGatewayReq {
- facadeName: string;
- connectionName: string;
- accountName: string;
- currency: string;
-}
-
-/**
- * Launch Nexus and Sandbox AND creates users / facades / bank accounts /
- * .. all that's required to start making bank traffic.
- */
-export async function launchLibeufinServices(
- t: GlobalTestState,
- nexusUserBundle: NexusUserBundle[],
- sandboxUserBundle: SandboxUserBundle[] = [],
- withFacades: string[] = [], // takes only "twg" and/or "anastasis"
-): Promise<LibeufinServices> {
- const db = await setupDb(t);
-
- const libeufinSandbox = await LibeufinSandboxService.create(t, {
- httpPort: 5010,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-sandbox.sqlite3`,
- });
-
- await libeufinSandbox.start();
- await libeufinSandbox.pingUntilAvailable();
-
- const libeufinNexus = await LibeufinNexusService.create(t, {
- httpPort: 5011,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-nexus.sqlite3`,
- });
-
- await libeufinNexus.start();
- await libeufinNexus.pingUntilAvailable();
- console.log("Libeufin services launched!");
-
- for (let sb of sandboxUserBundle) {
- await LibeufinSandboxApi.createEbicsHost(
- libeufinSandbox,
- sb.ebicsBankAccount.subscriber.hostID,
- );
- await LibeufinSandboxApi.createEbicsSubscriber(
- libeufinSandbox,
- sb.ebicsBankAccount.subscriber,
- );
- await LibeufinSandboxApi.createDemobankAccount(
- sb.ebicsBankAccount.label,
- "password-unused",
- { baseUrl: libeufinSandbox.baseUrl + "/demobanks/default/access-api/" }
- );
- await LibeufinSandboxApi.createDemobankEbicsSubscriber(
- sb.ebicsBankAccount.subscriber,
- sb.ebicsBankAccount.label,
- { baseUrl: libeufinSandbox.baseUrl + "/demobanks/default/" }
- );
- }
- console.log("Sandbox user(s) / account(s) / subscriber(s): created");
-
- for (let nb of nexusUserBundle) {
- await LibeufinNexusApi.createEbicsBankConnection(libeufinNexus, nb.connReq);
- await LibeufinNexusApi.connectBankConnection(
- libeufinNexus,
- nb.connReq.name,
- );
- await LibeufinNexusApi.fetchAccounts(libeufinNexus, nb.connReq.name);
- await LibeufinNexusApi.importConnectionAccount(
- libeufinNexus,
- nb.connReq.name,
- nb.remoteAccountName,
- nb.localAccountName,
- );
- await LibeufinNexusApi.createUser(libeufinNexus, nb.userReq);
- for (let facade of withFacades) {
- switch (facade) {
- case "twg":
- await LibeufinNexusApi.createTwgFacade(libeufinNexus, nb.twgReq);
- await LibeufinNexusApi.postPermission(
- libeufinNexus,
- nb.twgTransferPermission,
- );
- await LibeufinNexusApi.postPermission(
- libeufinNexus,
- nb.twgHistoryPermission,
- );
- break;
- case "anastasis":
- await LibeufinNexusApi.createAnastasisFacade(
- libeufinNexus,
- nb.anastasisReq,
- );
- }
- }
- }
- console.log(
- "Nexus user(s) / connection(s) / facade(s) / permission(s): created",
- );
-
- return {
- commonDb: db,
- libeufinNexus: libeufinNexus,
- libeufinSandbox: libeufinSandbox,
- };
-}
-
-/**
- * Helper function that searches a payment among
- * a list, as returned by Nexus. The key is just
- * the payment subject.
- */
-export function findNexusPayment(
- key: string,
- payments: LibeufinNexusTransactions,
-): LibeufinNexusMoneyMovement | void {
- let transactions = payments["transactions"];
- for (let i = 0; i < transactions.length; i++) {
- let batches = transactions[i]["batches"];
- for (let y = 0; y < batches.length; y++) {
- let movements = batches[y]["batchTransactions"];
- for (let z = 0; z < movements.length; z++) {
- let movement = movements[z];
- if (movement["details"]["unstructuredRemittanceInformation"] == key)
- return movement;
- }
- }
- }
-}
diff --git a/packages/taler-wallet-cli/src/harness/merchantApiTypes.ts b/packages/taler-wallet-cli/src/harness/merchantApiTypes.ts
deleted file mode 100644
index 2a59b0160..000000000
--- a/packages/taler-wallet-cli/src/harness/merchantApiTypes.ts
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- 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/>
- */
-
-/**
- * Test harness for various GNU Taler components.
- * Also provides a fault-injection proxy.
- *
- * @author Florian Dold <dold@taler.net>
- */
-
-/**
- * Imports.
- */
-import {
- MerchantContractTerms,
- Duration,
- Codec,
- buildCodecForObject,
- codecForString,
- codecOptional,
- codecForConstString,
- codecForBoolean,
- codecForNumber,
- codecForMerchantContractTerms,
- codecForAny,
- buildCodecForUnion,
- AmountString,
- AbsoluteTime,
- CoinPublicKeyString,
- EddsaPublicKeyString,
- codecForAmountString,
- TalerProtocolDuration,
- codecForTimestamp,
- TalerProtocolTimestamp,
-} from "@gnu-taler/taler-util";
-
-export interface PostOrderRequest {
- // The order must at least contain the minimal
- // order detail, but can override all
- order: Partial<MerchantContractTerms>;
-
- // if set, the backend will then set the refund deadline to the current
- // time plus the specified delay.
- refund_delay?: TalerProtocolDuration;
-
- // specifies the payment target preferred by the client. Can be used
- // to select among the various (active) wire methods supported by the instance.
- payment_target?: string;
-
- // FIXME: some fields are missing
-
- // Should a token for claiming the order be generated?
- // False can make sense if the ORDER_ID is sufficiently
- // high entropy to prevent adversarial claims (like it is
- // if the backend auto-generates one). Default is 'true'.
- create_token?: boolean;
-}
-
-export type ClaimToken = string;
-
-export interface PostOrderResponse {
- order_id: string;
- token?: ClaimToken;
-}
-
-export const codecForPostOrderResponse = (): Codec<PostOrderResponse> =>
- buildCodecForObject<PostOrderResponse>()
- .property("order_id", codecForString())
- .property("token", codecOptional(codecForString()))
- .build("PostOrderResponse");
-
-
-export const codecForRefundDetails = (): Codec<RefundDetails> =>
- buildCodecForObject<RefundDetails>()
- .property("reason", codecForString())
- .property("pending", codecForBoolean())
- .property("amount", codecForString())
- .property("timestamp", codecForTimestamp)
- .build("PostOrderResponse");
-
-export const codecForCheckPaymentPaidResponse =
- (): Codec<CheckPaymentPaidResponse> =>
- buildCodecForObject<CheckPaymentPaidResponse>()
- .property("order_status_url", codecForString())
- .property("order_status", codecForConstString("paid"))
- .property("refunded", codecForBoolean())
- .property("wired", codecForBoolean())
- .property("deposit_total", codecForAmountString())
- .property("exchange_ec", codecForNumber())
- .property("exchange_hc", codecForNumber())
- .property("refund_amount", codecForAmountString())
- .property("contract_terms", codecForMerchantContractTerms())
- // FIXME: specify
- .property("wire_details", codecForAny())
- .property("wire_reports", codecForAny())
- .property("refund_details", codecForAny())
- .build("CheckPaymentPaidResponse");
-
-export const codecForCheckPaymentUnpaidResponse =
- (): Codec<CheckPaymentUnpaidResponse> =>
- buildCodecForObject<CheckPaymentUnpaidResponse>()
- .property("order_status", codecForConstString("unpaid"))
- .property("taler_pay_uri", codecForString())
- .property("order_status_url", codecForString())
- .property("already_paid_order_id", codecOptional(codecForString()))
- .build("CheckPaymentPaidResponse");
-
-export const codecForCheckPaymentClaimedResponse =
- (): Codec<CheckPaymentClaimedResponse> =>
- buildCodecForObject<CheckPaymentClaimedResponse>()
- .property("order_status", codecForConstString("claimed"))
- .property("contract_terms", codecForMerchantContractTerms())
- .build("CheckPaymentClaimedResponse");
-
-export const codecForMerchantOrderPrivateStatusResponse =
- (): Codec<MerchantOrderPrivateStatusResponse> =>
- buildCodecForUnion<MerchantOrderPrivateStatusResponse>()
- .discriminateOn("order_status")
- .alternative("paid", codecForCheckPaymentPaidResponse())
- .alternative("unpaid", codecForCheckPaymentUnpaidResponse())
- .alternative("claimed", codecForCheckPaymentClaimedResponse())
- .build("MerchantOrderPrivateStatusResponse");
-
-export type MerchantOrderPrivateStatusResponse =
- | CheckPaymentPaidResponse
- | CheckPaymentUnpaidResponse
- | CheckPaymentClaimedResponse;
-
-export interface CheckPaymentClaimedResponse {
- // Wallet claimed the order, but didn't pay yet.
- order_status: "claimed";
-
- contract_terms: MerchantContractTerms;
-}
-
-export interface CheckPaymentPaidResponse {
- // did the customer pay for this contract
- order_status: "paid";
-
- // Was the payment refunded (even partially)
- refunded: boolean;
-
- // Did the exchange wire us the funds
- wired: boolean;
-
- // Total amount the exchange deposited into our bank account
- // for this contract, excluding fees.
- deposit_total: AmountString;
-
- // Numeric error code indicating errors the exchange
- // encountered tracking the wire transfer for this purchase (before
- // we even got to specific coin issues).
- // 0 if there were no issues.
- exchange_ec: number;
-
- // HTTP status code returned by the exchange when we asked for
- // information to track the wire transfer for this purchase.
- // 0 if there were no issues.
- exchange_hc: number;
-
- // Total amount that was refunded, 0 if refunded is false.
- refund_amount: AmountString;
-
- // Contract terms
- contract_terms: MerchantContractTerms;
-
- // Ihe wire transfer status from the exchange for this order if available, otherwise empty array
- wire_details: TransactionWireTransfer[];
-
- // Reports about trouble obtaining wire transfer details, empty array if no trouble were encountered.
- wire_reports: TransactionWireReport[];
-
- // The refund details for this order. One entry per
- // refunded coin; empty array if there are no refunds.
- refund_details: RefundDetails[];
-
- order_status_url: string;
-}
-
-export interface CheckPaymentUnpaidResponse {
- order_status: "unpaid";
-
- // URI that the wallet must process to complete the payment.
- taler_pay_uri: string;
-
- order_status_url: string;
-
- // Alternative order ID which was paid for already in the same session.
- // Only given if the same product was purchased before in the same session.
- already_paid_order_id?: string;
-
- // We do we NOT return the contract terms here because they may not
- // exist in case the wallet did not yet claim them.
-}
-
-export interface RefundDetails {
- // Reason given for the refund
- reason: string;
-
- // when was the refund approved
- timestamp: TalerProtocolTimestamp;
-
- // has not been taken yet
- pending: boolean;
-
- // Total amount that was refunded (minus a refund fee).
- amount: AmountString;
-}
-
-export interface TransactionWireTransfer {
- // Responsible exchange
- exchange_url: string;
-
- // 32-byte wire transfer identifier
- wtid: string;
-
- // execution time of the wire transfer
- execution_time: AbsoluteTime;
-
- // Total amount that has been wire transferred
- // to the merchant
- amount: AmountString;
-
- // Was this transfer confirmed by the merchant via the
- // POST /transfers API, or is it merely claimed by the exchange?
- confirmed: boolean;
-}
-
-export interface TransactionWireReport {
- // Numerical error code
- code: number;
-
- // Human-readable error description
- hint: string;
-
- // Numerical error code from the exchange.
- exchange_ec: number;
-
- // HTTP status code received from the exchange.
- exchange_hc: number;
-
- // Public key of the coin for which we got the exchange error.
- coin_pub: CoinPublicKeyString;
-}
-
-export interface TippingReserveStatus {
- // Array of all known reserves (possibly empty!)
- reserves: ReserveStatusEntry[];
-}
-
-export interface ReserveStatusEntry {
- // Public key of the reserve
- reserve_pub: string;
-
- // Timestamp when it was established
- creation_time: AbsoluteTime;
-
- // Timestamp when it expires
- expiration_time: AbsoluteTime;
-
- // Initial amount as per reserve creation call
- merchant_initial_amount: AmountString;
-
- // Initial amount as per exchange, 0 if exchange did
- // not confirm reserve creation yet.
- exchange_initial_amount: AmountString;
-
- // Amount picked up so far.
- pickup_amount: AmountString;
-
- // Amount approved for tips that exceeds the pickup_amount.
- committed_amount: AmountString;
-
- // Is this reserve active (false if it was deleted but not purged)
- active: boolean;
-}
-
-export interface TipCreateConfirmation {
- // Unique tip identifier for the tip that was created.
- tip_id: string;
-
- // taler://tip URI for the tip
- taler_tip_uri: string;
-
- // URL that will directly trigger processing
- // the tip when the browser is redirected to it
- tip_status_url: string;
-
- // when does the tip expire
- tip_expiration: AbsoluteTime;
-}
-
-export interface TipCreateRequest {
- // Amount that the customer should be tipped
- amount: AmountString;
-
- // Justification for giving the tip
- justification: string;
-
- // URL that the user should be directed to after tipping,
- // will be included in the tip_token.
- next_url: string;
-}
-
-export interface MerchantInstancesResponse {
- // List of instances that are present in the backend (see Instance)
- instances: MerchantInstanceDetail[];
-}
-
-export interface MerchantInstanceDetail {
- // Merchant name corresponding to this instance.
- name: string;
-
- // Merchant instance this response is about ($INSTANCE)
- id: string;
-
- // Public key of the merchant/instance, in Crockford Base32 encoding.
- merchant_pub: EddsaPublicKeyString;
-
- // List of the payment targets supported by this instance. Clients can
- // specify the desired payment target in /order requests. Note that
- // front-ends do not have to support wallets selecting payment targets.
- payment_targets: string[];
-}
diff --git a/packages/taler-wallet-cli/src/harness/sync.ts b/packages/taler-wallet-cli/src/harness/sync.ts
deleted file mode 100644
index a9e8de412..000000000
--- a/packages/taler-wallet-cli/src/harness/sync.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 { URL } from "@gnu-taler/taler-util";
-import * as fs from "fs";
-import * as util from "util";
-import {
- GlobalTestState,
- pingProc,
- ProcessWrapper,
-} from "../harness/harness.js";
-import { Configuration } from "@gnu-taler/taler-util";
-import * as child_process from "child_process";
-
-const exec = util.promisify(child_process.exec);
-
-export interface SyncConfig {
- /**
- * Human-readable name used in the test harness logs.
- */
- name: string;
-
- httpPort: number;
-
- /**
- * Database connection string (only postgres is supported).
- */
- database: string;
-
- annualFee: string;
-
- currency: string;
-
- uploadLimitMb: number;
-
- /**
- * Fulfillment URL used for contract terms related to
- * sync.
- */
- fulfillmentUrl: string;
-
- paymentBackendUrl: string;
-}
-
-function setSyncPaths(config: Configuration, home: string) {
- config.setString("paths", "sync_home", home);
- // We need to make sure that the path of taler_runtime_dir isn't too long,
- // as it contains unix domain sockets (108 character limit).
- const runDir = fs.mkdtempSync("/tmp/taler-test-");
- config.setString("paths", "sync_runtime_dir", runDir);
- config.setString("paths", "sync_data_home", "$SYNC_HOME/.local/share/sync/");
- config.setString("paths", "sync_config_home", "$SYNC_HOME/.config/sync/");
- config.setString("paths", "sync_cache_home", "$SYNC_HOME/.config/sync/");
-}
-
-export class SyncService {
- static async create(
- gc: GlobalTestState,
- sc: SyncConfig,
- ): Promise<SyncService> {
- const config = new Configuration();
-
- const cfgFilename = gc.testDir + `/sync-${sc.name}.conf`;
- setSyncPaths(config, gc.testDir + "/synchome");
- config.setString("taler", "currency", sc.currency);
- config.setString("sync", "serve", "tcp");
- config.setString("sync", "port", `${sc.httpPort}`);
- config.setString("sync", "db", "postgres");
- config.setString("syncdb-postgres", "config", sc.database);
- config.setString("sync", "payment_backend_url", sc.paymentBackendUrl);
- config.setString("sync", "upload_limit_mb", `${sc.uploadLimitMb}`);
- config.write(cfgFilename);
-
- return new SyncService(gc, sc, cfgFilename);
- }
-
- proc: ProcessWrapper | undefined;
-
- get baseUrl(): string {
- return `http://localhost:${this.syncConfig.httpPort}/`;
- }
-
- async start(): Promise<void> {
- await exec(`sync-dbinit -c "${this.configFilename}"`);
-
- this.proc = this.globalState.spawnService(
- "sync-httpd",
- ["-LDEBUG", "-c", this.configFilename],
- `sync-${this.syncConfig.name}`,
- );
- }
-
- async pingUntilAvailable(): Promise<void> {
- const url = new URL("config", this.baseUrl).href;
- await pingProc(this.proc, url, "sync");
- }
-
- constructor(
- private globalState: GlobalTestState,
- private syncConfig: SyncConfig,
- private configFilename: string,
- ) { }
-}
diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts
index 8fad3bdbf..90dc2fdd1 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -17,20 +17,13 @@
/**
* Imports.
*/
-import { deepStrictEqual } from "assert";
-import fs from "fs";
-import os from "os";
-import path from "path";
-// Polyfill for encoding which isn't present globally in older nodejs versions
import {
addPaytoQueryParams,
AgeRestriction,
- Amounts,
classifyTalerUri,
clk,
codecForList,
codecForString,
- Configuration,
decodeCrock,
encodeCrock,
getRandomBytes,
@@ -39,12 +32,11 @@ import {
parsePaytoUri,
PreparePayResultType,
RecoveryMergeStrategy,
- rsaBlind,
setDangerousTimetravel,
setGlobalLogLevelFromString,
TalerUriType,
- parseDevExperimentUri,
} from "@gnu-taler/taler-util";
+import type { TalerCryptoInterface } from "@gnu-taler/taler-wallet-core";
import {
CryptoDispatcher,
getDefaultNodeWallet,
@@ -60,20 +52,8 @@ import {
WalletCoreApiClient,
walletCoreDebugFlags,
} from "@gnu-taler/taler-wallet-core";
-import type { TalerCryptoInterface } from "@gnu-taler/taler-wallet-core";
-import { TextDecoder, TextEncoder } from "util";
-import { runBench1 } from "./bench1.js";
-import { runBench2 } from "./bench2.js";
-import { runBench3 } from "./bench3.js";
-import { runEnv1 } from "./env1.js";
-import { GlobalTestState, runTestWithState } from "./harness/harness.js";
-import { getTestInfo, runTests } from "./integrationtests/testrunner.js";
-import { lintExchangeDeployment } from "./lint.js";
-import { runEnvFull } from "./env-full.js";
-// @ts-ignore
-global.TextEncoder = TextEncoder;
-// @ts-ignore
-global.TextDecoder = TextDecoder;
+import fs from "fs";
+import os from "os";
// This module also serves as the entry point for the crypto
// thread worker, and thus must expose these two handlers.
@@ -895,75 +875,6 @@ advancedCli
});
advancedCli
- .subcommand("bench1", "bench1", {
- help: "Run the 'bench1' benchmark",
- })
- .requiredOption("configJson", ["--config-json"], clk.STRING)
- .action(async (args) => {
- let config: any;
- try {
- config = JSON.parse(args.bench1.configJson);
- } catch (e) {
- console.log("Could not parse config JSON");
- }
- await runBench1(config);
- });
-
-advancedCli
- .subcommand("bench2", "bench2", {
- help: "Run the 'bench2' benchmark",
- })
- .requiredOption("configJson", ["--config-json"], clk.STRING)
- .action(async (args) => {
- let config: any;
- try {
- config = JSON.parse(args.bench2.configJson);
- } catch (e) {
- console.log("Could not parse config JSON");
- }
- await runBench2(config);
- });
-
-advancedCli
- .subcommand("bench3", "bench3", {
- help: "Run the 'bench3' benchmark",
- })
- .requiredOption("configJson", ["--config-json"], clk.STRING)
- .action(async (args) => {
- let config: any;
- try {
- config = JSON.parse(args.bench3.configJson);
- } catch (e) {
- console.log("Could not parse config JSON");
- }
- await runBench3(config);
- });
-
-advancedCli
- .subcommand("envFull", "env-full", {
- help: "Run a test environment for bench1",
- })
- .action(async (args) => {
- const testDir = fs.mkdtempSync(path.join(os.tmpdir(), "taler-env-full-"));
- const testState = new GlobalTestState({
- testDir,
- });
- await runTestWithState(testState, runEnvFull, "env-full", true);
- });
-
-advancedCli
- .subcommand("env1", "env1", {
- help: "Run a test environment for bench1",
- })
- .action(async (args) => {
- const testDir = fs.mkdtempSync(path.join(os.tmpdir(), "taler-env1-"));
- const testState = new GlobalTestState({
- testDir,
- });
- await runTestWithState(testState, runEnv1, "env1", true);
- });
-
-advancedCli
.subcommand("withdrawFakebank", "withdraw-fakebank", {
help: "Withdraw via a fakebank.",
})
@@ -992,7 +903,7 @@ advancedCli
})
.action((args) => {
const enc = fs.readFileSync(0, "utf8");
- fs.writeFileSync(1, decodeCrock(enc.trim()));
+ console.log(decodeCrock(enc.trim()));
});
advancedCli
@@ -1207,92 +1118,6 @@ advancedCli
});
});
-const deploymentCli = walletCli.subcommand("deploymentArgs", "deployment", {
- help: "Subcommands for handling GNU Taler deployments.",
-});
-
-deploymentCli
- .subcommand("lintExchange", "lint-exchange", {
- help: "Run checks on the exchange deployment.",
- })
- .flag("cont", ["--continue"], {
- help: "Continue after errors if possible",
- })
- .flag("debug", ["--debug"], {
- help: "Output extra debug info",
- })
- .action(async (args) => {
- await lintExchangeDeployment(
- args.lintExchange.debug,
- args.lintExchange.cont,
- );
- });
-
-deploymentCli
- .subcommand("coincfg", "gen-coin-config", {
- help: "Generate a coin/denomination configuration for the exchange.",
- })
- .requiredOption("minAmount", ["--min-amount"], clk.STRING, {
- help: "Smallest denomination",
- })
- .requiredOption("maxAmount", ["--max-amount"], clk.STRING, {
- help: "Largest denomination",
- })
- .action(async (args) => {
- let out = "";
-
- const stamp = Math.floor(new Date().getTime() / 1000);
-
- const min = Amounts.parseOrThrow(args.coincfg.minAmount);
- const max = Amounts.parseOrThrow(args.coincfg.maxAmount);
- if (min.currency != max.currency) {
- console.error("currency mismatch");
- process.exit(1);
- }
- const currency = min.currency;
- let x = min;
- let n = 1;
-
- out += "# Coin configuration for the exchange.\n";
- out += '# Should be placed in "/etc/taler/conf.d/exchange-coins.conf".\n';
- out += "\n";
-
- while (Amounts.cmp(x, max) < 0) {
- out += `[COIN-${currency}-n${n}-t${stamp}]\n`;
- out += `VALUE = ${Amounts.stringify(x)}\n`;
- out += `DURATION_WITHDRAW = 7 days\n`;
- out += `DURATION_SPEND = 2 years\n`;
- out += `DURATION_LEGAL = 6 years\n`;
- out += `FEE_WITHDRAW = ${currency}:0\n`;
- out += `FEE_DEPOSIT = ${Amounts.stringify(min)}\n`;
- out += `FEE_REFRESH = ${currency}:0\n`;
- out += `FEE_REFUND = ${currency}:0\n`;
- out += `RSA_KEYSIZE = 2048\n`;
- out += "\n";
- x = Amounts.add(x, x).amount;
- n++;
- }
-
- console.log(out);
- });
-
-const deploymentConfigCli = deploymentCli.subcommand("configArgs", "config", {
- help: "Subcommands the Taler configuration.",
-});
-
-deploymentConfigCli
- .subcommand("show", "show")
- .flag("diagnostics", ["-d", "--diagnostics"])
- .maybeArgument("cfgfile", clk.STRING, {})
- .action(async (args) => {
- const cfg = Configuration.load(args.show.cfgfile);
- console.log(
- cfg.stringify({
- diagnostics: args.show.diagnostics,
- }),
- );
- });
-
const testCli = walletCli.subcommand("testingArgs", "testing", {
help: "Subcommands for testing.",
});
@@ -1426,102 +1251,12 @@ testCli.subcommand("logtest", "logtest").action(async (args) => {
logger.error("This is an error message.");
});
-testCli
- .subcommand("listIntegrationtests", "list-integrationtests")
- .action(async (args) => {
- for (const t of getTestInfo()) {
- let s = t.name;
- if (t.suites.length > 0) {
- s += ` (suites: ${t.suites.join(",")})`;
- }
- if (t.excludeByDefault) {
- s += ` [excluded by default]`;
- }
- console.log(s);
- }
- });
-
-testCli
- .subcommand("runIntegrationtests", "run-integrationtests")
- .maybeArgument("pattern", clk.STRING, {
- help: "Glob pattern to select which tests to run",
- })
- .maybeOption("suites", ["--suites"], clk.STRING, {
- help: "Only run selected suites (comma-separated list)",
- })
- .flag("dryRun", ["--dry"], {
- help: "Only print tests that will be selected to run.",
- })
- .flag("quiet", ["--quiet"], {
- help: "Produce less output.",
- })
- .action(async (args) => {
- await runTests({
- includePattern: args.runIntegrationtests.pattern,
- suiteSpec: args.runIntegrationtests.suites,
- dryRun: args.runIntegrationtests.dryRun,
- verbosity: args.runIntegrationtests.quiet ? 0 : 1,
- });
- });
-
async function read(stream: NodeJS.ReadStream) {
const chunks = [];
for await (const chunk of stream) chunks.push(chunk);
return Buffer.concat(chunks).toString("utf8");
}
-testCli.subcommand("tvgcheck", "tvgcheck").action(async (args) => {
- const data = await read(process.stdin);
-
- const lines = data.match(/[^\r\n]+/g);
-
- if (!lines) {
- throw Error("can't split lines");
- }
-
- const vals: Record<string, string> = {};
-
- let inBlindSigningSection = false;
-
- for (const line of lines) {
- if (line === "blind signing:") {
- inBlindSigningSection = true;
- continue;
- }
- if (line[0] !== " ") {
- inBlindSigningSection = false;
- continue;
- }
- if (inBlindSigningSection) {
- const m = line.match(/ (\w+) (\w+)/);
- if (!m) {
- console.log("bad format");
- process.exit(2);
- }
- vals[m[1]] = m[2];
- }
- }
-
- console.log(vals);
-
- const req = (k: string) => {
- if (!vals[k]) {
- throw Error(`no value for ${k}`);
- }
- return decodeCrock(vals[k]);
- };
-
- const myBm = rsaBlind(
- req("message_hash"),
- req("blinding_key_secret"),
- req("rsa_public_key"),
- );
-
- deepStrictEqual(req("blinded_message"), myBm);
-
- console.log("check passed!");
-});
-
testCli
.subcommand("cryptoworker", "cryptoworker")
.maybeOption("impl", ["--impl"], clk.STRING)
diff --git a/packages/taler-wallet-cli/src/integrationtests/scenario-prompt-payment.ts b/packages/taler-wallet-cli/src/integrationtests/scenario-prompt-payment.ts
deleted file mode 100644
index ea05de8e9..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/scenario-prompt-payment.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- 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 { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment, withdrawViaBank } from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runPromptPaymentScenario(t: GlobalTestState) {
- // Set up test environment
-
- const {
- wallet,
- bank,
- exchange,
- merchant,
- } = await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- // Set up order.
-
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- },
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- console.log(orderStatus);
-
- // Wait "forever"
- await new Promise(() => {});
-}
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-merchant.ts b/packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-merchant.ts
deleted file mode 100644
index ff589dd79..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-merchant.ts
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022 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 { BankApi, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { defaultCoinConfig } from "../harness/denomStructures.js";
-import {
- getWireMethodForTest,
- GlobalTestState,
- MerchantPrivateApi,
- WalletCli,
-} from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- makeTestPayment,
-} from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal and payment.
- */
-export async function runAgeRestrictionsMerchantTest(t: GlobalTestState) {
- // Set up test environment
-
- const {
- wallet: walletOne,
- bank,
- exchange,
- merchant,
- exchangeBankAccount,
- } = await createSimpleTestkudosEnvironment(
- t,
- defaultCoinConfig.map((x) => x("TESTKUDOS")),
- {
- ageMaskSpec: "8:10:12:14:16:18:21",
- },
- );
-
- const walletTwo = new WalletCli(t, "walletTwo");
- const walletThree = new WalletCli(t, "walletThree");
-
- {
- const walletZero = new WalletCli(t, "walletZero");
-
- await withdrawViaBank(t, {
- wallet: walletZero,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- restrictAge: 13,
- });
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- minimum_age: 9,
- };
-
- await makeTestPayment(t, { wallet: walletZero, merchant, order });
- await walletZero.runUntilDone();
- }
-
- {
- const wallet = walletOne;
-
- await withdrawViaBank(t, {
- wallet,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- restrictAge: 13,
- });
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- minimum_age: 9,
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
- }
-
- {
- const wallet = walletTwo;
-
- await withdrawViaBank(t, {
- wallet,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- restrictAge: 13,
- });
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
- }
-
- {
- const wallet = walletThree;
-
- await withdrawViaBank(t, {
- wallet,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- });
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- minimum_age: 9,
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
- }
-
- // Pay with coin from tipping
- {
- const mbu = await BankApi.createRandomBankUser(bank);
- const tipReserveResp = await MerchantPrivateApi.createTippingReserve(
- merchant,
- "default",
- {
- exchange_url: exchange.baseUrl,
- initial_balance: "TESTKUDOS:10",
- wire_method: getWireMethodForTest(),
- },
- );
-
- t.assertDeepEqual(
- tipReserveResp.payto_uri,
- exchangeBankAccount.accountPaytoUri,
- );
-
- await BankApi.adminAddIncoming(bank, {
- amount: "TESTKUDOS:10",
- debitAccountPayto: mbu.accountPaytoUri,
- exchangeBankAccount,
- reservePub: tipReserveResp.reserve_pub,
- });
-
- await exchange.runWirewatchOnce();
-
- const tip = await MerchantPrivateApi.giveTip(merchant, "default", {
- amount: "TESTKUDOS:5",
- justification: "why not?",
- next_url: "https://example.com/after-tip",
- });
-
- const walletTipping = new WalletCli(t, "age-tipping");
-
- const ptr = await walletTipping.client.call(WalletApiOperation.PrepareTip, {
- talerTipUri: tip.taler_tip_uri,
- });
-
- await walletTipping.client.call(WalletApiOperation.AcceptTip, {
- walletTipId: ptr.walletTipId,
- });
-
- await walletTipping.runUntilDone();
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:4",
- fulfillment_url: "taler://fulfillment-success/thx",
- minimum_age: 9,
- };
-
- await makeTestPayment(t, { wallet: walletTipping, merchant, order });
- await walletTipping.runUntilDone();
- }
-}
-
-runAgeRestrictionsMerchantTest.suites = ["wallet"];
-runAgeRestrictionsMerchantTest.timeoutMs = 120 * 1000;
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-mixed-merchant.ts b/packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-mixed-merchant.ts
deleted file mode 100644
index 8bf71b63d..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-mixed-merchant.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022 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 { defaultCoinConfig } from "../harness/denomStructures.js";
-import { GlobalTestState, WalletCli } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- makeTestPayment,
-} from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal and payment.
- */
-export async function runAgeRestrictionsMixedMerchantTest(t: GlobalTestState) {
- // Set up test environment
-
- const {
- wallet: walletOne,
- bank,
- exchange,
- merchant,
- } = await createSimpleTestkudosEnvironment(
- t,
- defaultCoinConfig.map((x) => x("TESTKUDOS")),
- {
- ageMaskSpec: "8:10:12:14:16:18:21",
- mixedAgeRestriction: true,
- },
- );
-
- const walletTwo = new WalletCli(t, "walletTwo");
- const walletThree = new WalletCli(t, "walletThree");
-
- {
- const wallet = walletOne;
-
- await withdrawViaBank(t, {
- wallet,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- restrictAge: 13,
- });
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- minimum_age: 9,
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
- }
-
- {
- const wallet = walletTwo;
-
- await withdrawViaBank(t, {
- wallet,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- restrictAge: 13,
- });
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
- }
-
- {
- const wallet = walletThree;
-
- await withdrawViaBank(t, {
- wallet,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- });
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- minimum_age: 9,
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
- }
-}
-
-runAgeRestrictionsMixedMerchantTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-peer.ts b/packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-peer.ts
deleted file mode 100644
index af5b4df52..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-age-restrictions-peer.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022 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 { AbsoluteTime, Duration } from "@gnu-taler/taler-util";
-import { getDefaultNodeWallet2, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { defaultCoinConfig } from "../harness/denomStructures.js";
-import { GlobalTestState, WalletCli } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- makeTestPayment,
-} from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal and payment.
- */
-export async function runAgeRestrictionsPeerTest(t: GlobalTestState) {
- // Set up test environment
-
- const {
- wallet: walletOne,
- bank,
- exchange,
- merchant,
- } = await createSimpleTestkudosEnvironment(
- t,
- defaultCoinConfig.map((x) => x("TESTKUDOS")),
- {
- ageMaskSpec: "8:10:12:14:16:18:21",
- },
- );
-
- const walletTwo = new WalletCli(t, "walletTwo");
- const walletThree = new WalletCli(t, "walletThree");
-
- {
- const wallet = walletOne;
-
- await withdrawViaBank(t, {
- wallet,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- restrictAge: 13,
- });
-
- const purse_expiration = AbsoluteTime.toTimestamp(
- AbsoluteTime.addDuration(
- AbsoluteTime.now(),
- Duration.fromSpec({ days: 2 }),
- ),
- );
-
- const initResp = await wallet.client.call(WalletApiOperation.InitiatePeerPushPayment, {
- partialContractTerms: {
- summary: "Hello, World",
- amount: "TESTKUDOS:1",
- purse_expiration,
- },
- });
-
- await wallet.runUntilDone();
-
- const checkResp = await walletTwo.client.call(WalletApiOperation.CheckPeerPushPayment, {
- talerUri: initResp.talerUri,
- });
-
- await walletTwo.client.call(WalletApiOperation.AcceptPeerPushPayment, {
- peerPushPaymentIncomingId: checkResp.peerPushPaymentIncomingId,
- });
-
- await walletTwo.runUntilDone();
- }
-}
-
-runAgeRestrictionsPeerTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts b/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts
deleted file mode 100644
index c7a23d3ce..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-bank-api.ts
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- 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 {
- GlobalTestState,
- WalletCli,
- ExchangeService,
- setupDb,
- BankService,
- MerchantService,
- getPayto,
-} from "../harness/harness.js";
-import { createEddsaKeyPair, encodeCrock } from "@gnu-taler/taler-util";
-import { defaultCoinConfig } from "../harness/denomStructures.js";
-import {
- BankApi,
- BankAccessApi,
- CreditDebitIndicator,
-} from "@gnu-taler/taler-wallet-core";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runBankApiTest(t: GlobalTestState) {
- // Set up test environment
-
- const db = await setupDb(t);
-
- const bank = await BankService.create(t, {
- currency: "TESTKUDOS",
- httpPort: 8082,
- database: db.connStr,
- allowRegistrations: true,
- });
-
- 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",
- );
- exchange.addBankAccount("1", exchangeBankAccount);
-
- bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- exchange.addOfferedCoins(defaultCoinConfig);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
- await merchant.addDefaultInstance();
- await merchant.addInstance({
- id: "minst1",
- name: "minst1",
- paytoUris: [getPayto("minst1")],
- });
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- });
-
- console.log("setup done!");
-
- const bankUser = await BankApi.registerAccount(bank, "user1", "pw1");
-
- // Make sure that registering twice results in a 409 Conflict
- {
- const e = await t.assertThrowsTalerErrorAsync(async () => {
- await BankApi.registerAccount(bank, "user1", "pw2");
- });
- t.assertTrue(e.errorDetail.httpStatusCode === 409);
- }
-
- let balResp = await BankAccessApi.getAccountBalance(bank, bankUser);
-
- console.log(balResp);
-
- // Check that we got the sign-up bonus.
- t.assertAmountEquals(balResp.balance.amount, "TESTKUDOS:100");
- t.assertTrue(
- balResp.balance.credit_debit_indicator === CreditDebitIndicator.Credit,
- );
-
- const res = createEddsaKeyPair();
-
- await BankApi.adminAddIncoming(bank, {
- amount: "TESTKUDOS:115",
- debitAccountPayto: bankUser.accountPaytoUri,
- exchangeBankAccount: exchangeBankAccount,
- reservePub: encodeCrock(res.eddsaPub),
- });
-
- balResp = await BankAccessApi.getAccountBalance(bank, bankUser);
- t.assertAmountEquals(balResp.balance.amount, "TESTKUDOS:15");
- t.assertTrue(
- balResp.balance.credit_debit_indicator === CreditDebitIndicator.Debit,
- );
-}
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-claim-loop.ts b/packages/taler-wallet-cli/src/integrationtests/test-claim-loop.ts
deleted file mode 100644
index a509e3b19..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-claim-loop.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- 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 { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment, withdrawViaBank } from "../harness/helpers.js";
-import { URL } from "url";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-
-/**
- * Run test for the merchant's order lifecycle.
- *
- * FIXME: Is this test still necessary? We initially wrote if to confirm/document
- * assumptions about how the merchant should work.
- */
-export async function runClaimLoopTest(t: GlobalTestState) {
- // Set up test environment
-
- const {
- wallet,
- bank,
- exchange,
- merchant,
- } = await createSimpleTestkudosEnvironment(t);
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- // Set up order.
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- },
- });
-
- // Query private order status before claiming it.
- let orderStatusBefore = await MerchantPrivateApi.queryPrivateOrderStatus(
- merchant,
- {
- orderId: orderResp.order_id,
- },
- );
- t.assertTrue(orderStatusBefore.order_status === "unpaid");
- let statusUrlBefore = new URL(orderStatusBefore.order_status_url);
-
- // Make wallet claim the unpaid order.
- t.assertTrue(orderStatusBefore.order_status === "unpaid");
- const talerPayUri = orderStatusBefore.taler_pay_uri;
- await wallet.client.call(WalletApiOperation.PreparePayForUri, {
- talerPayUri,
- });
-
- // Query private order status after claiming it.
- let orderStatusAfter = await MerchantPrivateApi.queryPrivateOrderStatus(
- merchant,
- {
- orderId: orderResp.order_id,
- },
- );
- t.assertTrue(orderStatusAfter.order_status === "claimed");
-
- await t.shutdown();
-}
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-clause-schnorr.ts b/packages/taler-wallet-cli/src/integrationtests/test-clause-schnorr.ts
deleted file mode 100644
index bf42dc4c6..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-clause-schnorr.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- 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 { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
-import { GlobalTestState } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- makeTestPayment,
-} from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal and payment.
- */
-export async function runClauseSchnorrTest(t: GlobalTestState) {
- // Set up test environment
-
- const coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => {
- return {
- ...x("TESTKUDOS"),
- cipher: "CS",
- };
- });
-
- // We need to have at least one RSA denom configured
- coinConfig.push({
- cipher: "RSA",
- rsaKeySize: 1024,
- durationLegal: "3 years",
- durationSpend: "2 years",
- durationWithdraw: "7 days",
- feeDeposit: "TESTKUDOS:42",
- value: "TESTKUDOS:0.0001",
- feeWithdraw: "TESTKUDOS:42",
- feeRefresh: "TESTKUDOS:42",
- feeRefund: "TESTKUDOS:42",
- name: "rsa_dummy",
- });
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t, coinConfig);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
-
- // Test JSON normalization of contract terms: Does the wallet
- // agree with the merchant?
- const order2 = {
- summary: "Testing “unicode” characters",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- await makeTestPayment(t, { wallet, merchant, order: order2 });
- await wallet.runUntilDone();
-
- // Test JSON normalization of contract terms: Does the wallet
- // agree with the merchant?
- const order3 = {
- summary: "Testing\nNewlines\rAnd\tStuff\nHere\b",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- await makeTestPayment(t, { wallet, merchant, order: order3 });
-
- await wallet.runUntilDone();
-}
-
-runClauseSchnorrTest.suites = ["experimental-wallet"];
-runClauseSchnorrTest.excludeByDefault = true;
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-denom-unoffered.ts b/packages/taler-wallet-cli/src/integrationtests/test-denom-unoffered.ts
deleted file mode 100644
index b5ecbee4a..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-denom-unoffered.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 { PreparePayResultType, TalerErrorCode } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-
-export async function runDenomUnofferedTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- // Make the exchange forget the denomination.
- // Effectively we completely reset the exchange,
- // but keep the exchange master public key.
-
- await exchange.stop();
- await exchange.purgeDatabase();
- await exchange.purgeSecmodKeys();
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- await merchant.stop();
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- {
- const orderResp = await MerchantPrivateApi.createOrder(
- merchant,
- "default",
- {
- order: order,
- },
- );
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(
- merchant,
- {
- orderId: orderResp.order_id,
- },
- );
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- // Make wallet pay for the order
-
- const preparePayResult = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: orderStatus.taler_pay_uri,
- },
- );
-
- t.assertTrue(
- preparePayResult.status === PreparePayResultType.PaymentPossible,
- );
-
- const exc = await t.assertThrowsTalerErrorAsync(async () => {
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
- proposalId: preparePayResult.proposalId,
- });
- });
-
- t.assertTrue(
- exc.hasErrorCode(TalerErrorCode.WALLET_PENDING_OPERATION_FAILED),
- );
-
- // FIXME: We might want a more specific error code here!
- t.assertDeepEqual(
- exc.errorDetail.innerError.code,
- TalerErrorCode.WALLET_UNEXPECTED_REQUEST_ERROR,
- );
- const merchantErrorCode = (exc.errorDetail.innerError.errorResponse as any)
- .code;
- t.assertDeepEqual(
- merchantErrorCode,
- TalerErrorCode.MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND,
- );
- }
-
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: exchange.baseUrl,
- forceUpdate: true,
- });
-
- // Now withdrawal should work again.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- await wallet.runUntilDone();
-
- const txs = await wallet.client.call(WalletApiOperation.GetTransactions, {});
- console.log(JSON.stringify(txs, undefined, 2));
-}
-
-runDenomUnofferedTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-deposit.ts b/packages/taler-wallet-cli/src/integrationtests/test-deposit.ts
deleted file mode 100644
index 07382c43e..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-deposit.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- 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 { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { GlobalTestState, getPayto } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment, withdrawViaBank } from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal and payment.
- */
-export async function runDepositTest(t: GlobalTestState) {
- // Set up test environment
-
- const {
- wallet,
- bank,
- exchange,
- merchant,
- } = await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- await wallet.runUntilDone();
-
- const { depositGroupId } = await wallet.client.call(
- WalletApiOperation.CreateDepositGroup,
- {
- amount: "TESTKUDOS:10",
- depositPaytoUri: getPayto("foo"),
- },
- );
-
- await wallet.runUntilDone();
-
- const transactions = await wallet.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
- console.log("transactions", JSON.stringify(transactions, undefined, 2));
- t.assertDeepEqual(transactions.transactions[0].type, "withdrawal");
- t.assertTrue(!transactions.transactions[0].pending);
- t.assertDeepEqual(transactions.transactions[1].type, "deposit");
- t.assertTrue(!transactions.transactions[1].pending);
- // The raw amount is what ends up on the bank account, which includes
- // deposit and wire fees.
- t.assertDeepEqual(transactions.transactions[1].amountRaw, "TESTKUDOS:9.79");
-
- const trackResult = wallet.client.call(WalletApiOperation.TrackDepositGroup, {
- depositGroupId,
- });
-
- console.log(JSON.stringify(trackResult, undefined, 2));
-}
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-exchange-management.ts b/packages/taler-wallet-cli/src/integrationtests/test-exchange-management.ts
deleted file mode 100644
index 6b63c3741..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-exchange-management.ts
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- 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 {
- GlobalTestState,
- WalletCli,
- setupDb,
- BankService,
- ExchangeService,
- MerchantService,
- getPayto,
-} from "../harness/harness.js";
-import {
- WalletApiOperation,
- BankApi,
- BankAccessApi,
-} from "@gnu-taler/taler-wallet-core";
-import {
- ExchangesListResponse,
- URL,
- TalerErrorCode,
- j2s,
-} from "@gnu-taler/taler-util";
-import {
- FaultInjectedExchangeService,
- FaultInjectionResponseContext,
-} from "../harness/faultInjection.js";
-import { defaultCoinConfig } from "../harness/denomStructures.js";
-
-/**
- * Test if the wallet handles outdated exchange versions correct.y
- */
-export async function runExchangeManagementTest(
- t: GlobalTestState,
-): Promise<void> {
- // Set up test environment
-
- 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,
- });
-
- const exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
- exchange.addBankAccount("1", exchangeBankAccount);
-
- const faultyExchange = new FaultInjectedExchangeService(t, exchange, 8091);
-
- bank.setSuggestedExchange(
- faultyExchange,
- exchangeBankAccount.accountPaytoUri,
- );
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- exchange.addOfferedCoins(defaultCoinConfig);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- });
-
- await merchant.addInstance({
- id: "minst1",
- name: "minst1",
- paytoUris: [getPayto("minst1")],
- });
-
- console.log("setup done!");
-
- /*
- * =========================================================================
- * Check that the exchange can be added to the wallet
- * (without any faults active).
- * =========================================================================
- */
-
- const wallet = new WalletCli(t);
-
- let exchangesList: ExchangesListResponse;
-
- exchangesList = await wallet.client.call(
- WalletApiOperation.ListExchanges,
- {},
- );
- console.log("exchanges list:", j2s(exchangesList));
- t.assertTrue(exchangesList.exchanges.length === 0);
-
- // Try before fault is injected
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: faultyExchange.baseUrl,
- });
-
- exchangesList = await wallet.client.call(
- WalletApiOperation.ListExchanges,
- {},
- );
- t.assertTrue(exchangesList.exchanges.length === 1);
-
- await wallet.client.call(WalletApiOperation.ListExchanges, {});
-
- console.log("listing exchanges");
-
- exchangesList = await wallet.client.call(
- WalletApiOperation.ListExchanges,
- {},
- );
- t.assertTrue(exchangesList.exchanges.length === 1);
-
- console.log("got list", exchangesList);
-
- /*
- * =========================================================================
- * Check what happens if the exchange returns something totally
- * bogus for /keys.
- * =========================================================================
- */
-
- wallet.deleteDatabase();
-
- exchangesList = await wallet.client.call(
- WalletApiOperation.ListExchanges,
- {},
- );
- t.assertTrue(exchangesList.exchanges.length === 0);
-
- faultyExchange.faultProxy.addFault({
- async modifyResponse(ctx: FaultInjectionResponseContext) {
- const url = new URL(ctx.request.requestUrl);
- if (url.pathname === "/keys") {
- const body = {
- version: "whaaat",
- };
- ctx.responseBody = Buffer.from(JSON.stringify(body), "utf-8");
- }
- },
- });
-
- const err1 = await t.assertThrowsTalerErrorAsync(async () => {
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: faultyExchange.baseUrl,
- });
- });
-
- // Response is malformed, since it didn't even contain a version code
- // in a format the wallet can understand.
- t.assertTrue(
- err1.errorDetail.code === TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
- );
- exchangesList = await wallet.client.call(
- WalletApiOperation.ListExchanges,
- {},
- );
- console.log("exchanges list", j2s(exchangesList));
- t.assertTrue(exchangesList.exchanges.length === 1);
- t.assertTrue(
- exchangesList.exchanges[0].lastUpdateErrorInfo?.error.code ===
- TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE,
- );
-
- /*
- * =========================================================================
- * Check what happens if the exchange returns an old, unsupported
- * version for /keys
- * =========================================================================
- */
-
- wallet.deleteDatabase();
- faultyExchange.faultProxy.clearAllFaults();
-
- faultyExchange.faultProxy.addFault({
- async modifyResponse(ctx: FaultInjectionResponseContext) {
- const url = new URL(ctx.request.requestUrl);
- if (url.pathname === "/keys") {
- const keys = ctx.responseBody?.toString("utf-8");
- t.assertTrue(keys != null);
- const keysJson = JSON.parse(keys);
- keysJson["version"] = "2:0:0";
- ctx.responseBody = Buffer.from(JSON.stringify(keysJson), "utf-8");
- }
- },
- });
-
- const err2 = await t.assertThrowsTalerErrorAsync(async () => {
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: faultyExchange.baseUrl,
- });
- });
-
- t.assertTrue(
- err2.hasErrorCode(
- TalerErrorCode.WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE,
- ),
- );
-
- exchangesList = await wallet.client.call(
- WalletApiOperation.ListExchanges,
- {},
- );
- t.assertTrue(exchangesList.exchanges.length === 1);
- t.assertTrue(
- exchangesList.exchanges[0].lastUpdateErrorInfo?.error.code ===
- TalerErrorCode.WALLET_EXCHANGE_PROTOCOL_VERSION_INCOMPATIBLE,
- );
-
- /*
- * =========================================================================
- * Check that the exchange version is also checked when
- * the exchange is implicitly added via the suggested
- * exchange of a bank-integrated withdrawal.
- * =========================================================================
- */
-
- // Fault from above is still active!
-
- // Create withdrawal operation
-
- const user = await BankApi.createRandomBankUser(bank);
- const wop = await BankAccessApi.createWithdrawalOperation(
- bank,
- user,
- "TESTKUDOS:10",
- );
-
- // Hand it to the wallet
-
- const wd = await wallet.client.call(
- WalletApiOperation.GetWithdrawalDetailsForUri,
- {
- talerWithdrawUri: wop.taler_withdraw_uri,
- },
- );
-
- // Make sure the faulty exchange isn't used for the suggestion.
- t.assertTrue(wd.possibleExchanges.length === 0);
-}
-
-runExchangeManagementTest.suites = ["wallet", "exchange"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-exchange-timetravel.ts b/packages/taler-wallet-cli/src/integrationtests/test-exchange-timetravel.ts
deleted file mode 100644
index 074126e9f..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-exchange-timetravel.ts
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- 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 {
- AbsoluteTime,
- codecForExchangeKeysJson,
- DenominationPubKey,
- Duration,
- durationFromSpec,
-} from "@gnu-taler/taler-util";
-import {
- NodeHttpLib,
- readSuccessResponseJsonOrThrow,
-} from "@gnu-taler/taler-wallet-core";
-import { makeNoFeeCoinConfig } from "../harness/denomStructures.js";
-import {
- BankService,
- ExchangeService,
- GlobalTestState,
- MerchantPrivateApi,
- MerchantService,
- setupDb,
- WalletCli,
- getPayto,
-} from "../harness/harness.js";
-import { startWithdrawViaBank, withdrawViaBank } from "../harness/helpers.js";
-
-async function applyTimeTravel(
- timetravelDuration: Duration,
- s: {
- exchange?: ExchangeService;
- merchant?: MerchantService;
- wallet?: WalletCli;
- },
-): Promise<void> {
- if (s.exchange) {
- await s.exchange.stop();
- s.exchange.setTimetravel(timetravelDuration);
- await s.exchange.start();
- await s.exchange.pingUntilAvailable();
- }
-
- if (s.merchant) {
- await s.merchant.stop();
- s.merchant.setTimetravel(timetravelDuration);
- await s.merchant.start();
- await s.merchant.pingUntilAvailable();
- }
-
- if (s.wallet) {
- console.log("setting wallet time travel to", timetravelDuration);
- s.wallet.setTimetravel(timetravelDuration);
- }
-}
-
-const http = new NodeHttpLib();
-
-/**
- * Basic time travel test.
- */
-export async function runExchangeTimetravelTest(t: GlobalTestState) {
- // Set up test environment
-
- 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,
- });
-
- const exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
- exchange.addBankAccount("1", exchangeBankAccount);
-
- bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- exchange.addCoinConfigList(makeNoFeeCoinConfig("TESTKUDOS"));
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- });
-
- await merchant.addInstance({
- id: "minst1",
- name: "minst1",
- paytoUris: [getPayto("minst1")],
- });
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:15" });
-
- const keysResp1 = await http.get(exchange.baseUrl + "keys");
- const keys1 = await readSuccessResponseJsonOrThrow(
- keysResp1,
- codecForExchangeKeysJson(),
- );
- console.log(
- "keys 1 (before time travel):",
- JSON.stringify(keys1, undefined, 2),
- );
-
- // Travel into the future, the deposit expiration is two years
- // into the future.
- console.log("applying first time travel");
- await applyTimeTravel(durationFromSpec({ days: 400 }), {
- wallet,
- exchange,
- merchant,
- });
-
- const keysResp2 = await http.get(exchange.baseUrl + "keys");
- const keys2 = await readSuccessResponseJsonOrThrow(
- keysResp2,
- codecForExchangeKeysJson(),
- );
- console.log(
- "keys 2 (after time travel):",
- JSON.stringify(keys2, undefined, 2),
- );
-
- const denomPubs1 = keys1.denoms.map((x) => {
- return {
- denomPub: x.denom_pub,
- expireDeposit: AbsoluteTime.stringify(
- AbsoluteTime.fromTimestamp(x.stamp_expire_deposit),
- ),
- };
- });
-
- const denomPubs2 = keys2.denoms.map((x) => {
- return {
- denomPub: x.denom_pub,
- expireDeposit: AbsoluteTime.stringify(
- AbsoluteTime.fromTimestamp(x.stamp_expire_deposit),
- ),
- };
- });
- const dps2 = new Set(denomPubs2.map((x) => x.denomPub));
-
- console.log("=== KEYS RESPONSE 1 ===");
-
- console.log(
- "list issue date",
- AbsoluteTime.stringify(AbsoluteTime.fromTimestamp(keys1.list_issue_date)),
- );
- console.log("num denoms", keys1.denoms.length);
- console.log("denoms", JSON.stringify(denomPubs1, undefined, 2));
-
- console.log("=== KEYS RESPONSE 2 ===");
-
- console.log(
- "list issue date",
- AbsoluteTime.stringify(AbsoluteTime.fromTimestamp(keys2.list_issue_date)),
- );
- console.log("num denoms", keys2.denoms.length);
- console.log("denoms", JSON.stringify(denomPubs2, undefined, 2));
-
- for (const da of denomPubs1) {
- let found = false;
- for (const db of denomPubs2) {
- const d1 = da.denomPub;
- const d2 = db.denomPub;
- if (DenominationPubKey.cmp(d1, d2) === 0) {
- found = true;
- break;
- }
- }
- if (!found) {
- console.log("=== ERROR ===");
- console.log(
- `denomination with public key ${da.denomPub} is not present in new /keys response`,
- );
- console.log(
- `the new /keys response was issued ${AbsoluteTime.stringify(
- AbsoluteTime.fromTimestamp(keys2.list_issue_date),
- )}`,
- );
- console.log(
- `however, the missing denomination has stamp_expire_deposit ${da.expireDeposit}`,
- );
- console.log("see above for the verbatim /keys responses");
- t.assertTrue(false);
- }
- }
-}
-
-runExchangeTimetravelTest.suites = ["exchange"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-fee-regression.ts b/packages/taler-wallet-cli/src/integrationtests/test-fee-regression.ts
deleted file mode 100644
index 8c5a5bea4..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-fee-regression.ts
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- 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 { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import {
- GlobalTestState,
- BankService,
- ExchangeService,
- MerchantService,
- setupDb,
- WalletCli,
- getPayto,
-} from "../harness/harness.js";
-import {
- withdrawViaBank,
- makeTestPayment,
- SimpleTestEnvironment,
-} from "../harness/helpers.js";
-
-/**
- * Run a test case with a simple TESTKUDOS Taler environment, consisting
- * of one exchange, one bank and one merchant.
- */
-export async function createMyTestkudosEnvironment(
- t: GlobalTestState,
-): Promise<SimpleTestEnvironment> {
- 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,
- });
-
- const exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
- exchange.addBankAccount("1", exchangeBankAccount);
-
- bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- const coinCommon = {
- cipher: "RSA" as const,
- durationLegal: "3 years",
- durationSpend: "2 years",
- durationWithdraw: "7 days",
- rsaKeySize: 1024,
- feeDeposit: "TESTKUDOS:0.0025",
- feeWithdraw: "TESTKUDOS:0",
- feeRefresh: "TESTKUDOS:0",
- feeRefund: "TESTKUDOS:0",
- };
-
- exchange.addCoinConfigList([
- {
- ...coinCommon,
- name: "c1",
- value: "TESTKUDOS:1.28",
- },
- {
- ...coinCommon,
- name: "c2",
- value: "TESTKUDOS:0.64",
- },
- {
- ...coinCommon,
- name: "c3",
- value: "TESTKUDOS:0.32",
- },
- {
- ...coinCommon,
- name: "c4",
- value: "TESTKUDOS:0.16",
- },
- {
- ...coinCommon,
- name: "c5",
- value: "TESTKUDOS:0.08",
- },
- {
- ...coinCommon,
- name: "c5",
- value: "TESTKUDOS:0.04",
- },
- {
- ...coinCommon,
- name: "c6",
- value: "TESTKUDOS:0.02",
- },
- {
- ...coinCommon,
- name: "c7",
- value: "TESTKUDOS:0.01",
- },
- ]);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addDefaultInstance();
- await merchant.addInstance({
- id: "minst1",
- name: "minst1",
- paytoUris: [getPayto("minst1")],
- });
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- return {
- commonDb: db,
- exchange,
- merchant,
- wallet,
- bank,
- exchangeBankAccount,
- };
-}
-
-/**
- * Run test for basic, bank-integrated withdrawal and payment.
- */
-export async function runFeeRegressionTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createMyTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, {
- wallet,
- bank,
- exchange,
- amount: "TESTKUDOS:1.92",
- });
-
- const coins = await wallet.client.call(WalletApiOperation.DumpCoins, {});
-
- // Make sure we really withdraw one 0.64 and one 1.28 coin.
- t.assertTrue(coins.coins.length === 2);
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:1.30",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
-
- await wallet.runUntilDone();
-
- const txs = await wallet.client.call(WalletApiOperation.GetTransactions, {});
- t.assertAmountEquals(txs.transactions[1].amountEffective, "TESTKUDOS:1.30");
- console.log(txs);
-}
-
-runFeeRegressionTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-forced-selection.ts b/packages/taler-wallet-cli/src/integrationtests/test-forced-selection.ts
deleted file mode 100644
index 91be11a82..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-forced-selection.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- 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 { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
-
-/**
- * Run test for forced denom/coin selection.
- */
-export async function runForcedSelectionTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
-
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: exchange.baseUrl,
- });
-
- await wallet.client.call(WalletApiOperation.WithdrawTestBalance, {
- exchangeBaseUrl: exchange.baseUrl,
- amount: "TESTKUDOS:10",
- bankBaseUrl: bank.baseUrl,
- bankAccessApiBaseUrl: bank.bankAccessApiBaseUrl,
- forcedDenomSel: {
- denoms: [
- {
- value: "TESTKUDOS:2",
- count: 3,
- },
- ],
- },
- });
-
- await wallet.runUntilDone();
-
- const coinDump = await wallet.client.call(WalletApiOperation.DumpCoins, {});
- console.log(coinDump);
- t.assertDeepEqual(coinDump.coins.length, 3);
-
- const payResp = await wallet.client.call(WalletApiOperation.TestPay, {
- amount: "TESTKUDOS:3",
- merchantBaseUrl: merchant.makeInstanceBaseUrl(),
- summary: "bla",
- forcedCoinSel: {
- coins: [
- {
- value: "TESTKUDOS:2",
- contribution: "TESTKUDOS:1",
- },
- {
- value: "TESTKUDOS:2",
- contribution: "TESTKUDOS:1",
- },
- {
- value: "TESTKUDOS:2",
- contribution: "TESTKUDOS:1",
- },
- ],
- },
- });
-
- console.log(j2s(payResp));
-
- // Without forced selection, we would only use 2 coins.
- t.assertDeepEqual(payResp.payCoinSelection.coinContributions.length, 3);
-}
-
-runForcedSelectionTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-bankaccount.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-bankaccount.ts
deleted file mode 100644
index c3cbc0608..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-bankaccount.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- NexusUserBundle,
- LibeufinNexusApi,
- LibeufinNexusService,
- LibeufinSandboxService,
- LibeufinSandboxApi,
- findNexusPayment,
-} from "../harness/libeufin.js";
-
-/**
- * Run basic test with LibEuFin.
- */
-export async function runLibeufinApiBankaccountTest(t: GlobalTestState) {
- const nexus = await LibeufinNexusService.create(t, {
- httpPort: 5011,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-nexus.sqlite3`,
- });
- await nexus.start();
- await nexus.pingUntilAvailable();
-
- await LibeufinNexusApi.createUser(nexus, {
- username: "one",
- password: "testing-the-bankaccount-api",
- });
- const sandbox = await LibeufinSandboxService.create(t, {
- httpPort: 5012,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-sandbox.sqlite3`,
- });
- await sandbox.start();
- await sandbox.pingUntilAvailable();
- await LibeufinSandboxApi.createEbicsHost(sandbox, "mock");
- await LibeufinSandboxApi.createDemobankAccount(
- "mock",
- "password-unused",
- { baseUrl: sandbox.baseUrl + "/demobanks/default/access-api/" },
- "DE71500105179674997361"
- );
- await LibeufinSandboxApi.createDemobankEbicsSubscriber(
- {
- hostID: "mock",
- partnerID: "mock",
- userID: "mock",
- },
- "mock",
- { baseUrl: sandbox.baseUrl + "/demobanks/default/" }
- );
- await LibeufinNexusApi.createEbicsBankConnection(nexus, {
- name: "bankaccount-api-test-connection",
- ebicsURL: "http://localhost:5012/ebicsweb",
- hostID: "mock",
- userID: "mock",
- partnerID: "mock",
- });
- await LibeufinNexusApi.connectBankConnection(
- nexus,
- "bankaccount-api-test-connection",
- );
- await LibeufinNexusApi.fetchAccounts(
- nexus,
- "bankaccount-api-test-connection",
- );
-
- await LibeufinNexusApi.importConnectionAccount(
- nexus,
- "bankaccount-api-test-connection",
- "mock",
- "local-mock",
- );
- await LibeufinSandboxApi.simulateIncomingTransaction(
- sandbox,
- "mock", // creditor bankaccount label
- {
- debtorIban: "DE84500105176881385584",
- debtorBic: "BELADEBEXXX",
- debtorName: "mock2",
- amount: "1",
- subject: "mock subject",
- },
- );
- await LibeufinNexusApi.fetchTransactions(nexus, "local-mock");
- let transactions = await LibeufinNexusApi.getAccountTransactions(
- nexus,
- "local-mock",
- );
- let el = findNexusPayment("mock subject", transactions.data);
- t.assertTrue(el instanceof Object);
-}
-
-runLibeufinApiBankaccountTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-bankconnection.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-bankconnection.ts
deleted file mode 100644
index 912b7b2ac..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-bankconnection.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import { LibeufinNexusApi, LibeufinNexusService } from "../harness/libeufin.js";
-
-/**
- * Run basic test with LibEuFin.
- */
-export async function runLibeufinApiBankconnectionTest(t: GlobalTestState) {
- const nexus = await LibeufinNexusService.create(t, {
- httpPort: 5011,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-nexus.sqlite3`,
- });
- await nexus.start();
- await nexus.pingUntilAvailable();
-
- await LibeufinNexusApi.createUser(nexus, {
- username: "one",
- password: "testing-the-bankconnection-api",
- });
-
- await LibeufinNexusApi.createEbicsBankConnection(nexus, {
- name: "bankconnection-api-test-connection",
- ebicsURL: "http://localhost:5012/ebicsweb",
- hostID: "mock",
- userID: "mock",
- partnerID: "mock",
- });
-
- let connections = await LibeufinNexusApi.getAllConnections(nexus);
- t.assertTrue(connections.data["bankConnections"].length == 1);
-
- await LibeufinNexusApi.deleteBankConnection(nexus, {
- bankConnectionId: "bankconnection-api-test-connection",
- });
- connections = await LibeufinNexusApi.getAllConnections(nexus);
- t.assertTrue(connections.data["bankConnections"].length == 0);
-}
-runLibeufinApiBankconnectionTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-facade-bad-request.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-facade-bad-request.ts
deleted file mode 100644
index a1da9e0da..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-facade-bad-request.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- 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 { URL } from "@gnu-taler/taler-util";
-import axiosImp from "axios";
-import { GlobalTestState } from "../harness/harness.js";
-import {
- launchLibeufinServices,
- NexusUserBundle,
- SandboxUserBundle,
-} from "../harness/libeufin.js";
-
-const axios = axiosImp.default;
-
-export async function runLibeufinApiFacadeBadRequestTest(t: GlobalTestState) {
- /**
- * User saltetd "01"
- */
- const user01nexus = new NexusUserBundle(
- "01",
- "http://localhost:5010/ebicsweb",
- );
- const user01sandbox = new SandboxUserBundle("01");
-
- /**
- * Launch Sandbox and Nexus.
- */
- const libeufinServices = await launchLibeufinServices(
- t,
- [user01nexus],
- [user01sandbox],
- ["twg"],
- );
- console.log("malformed facade");
- const baseUrl = libeufinServices.libeufinNexus.baseUrl;
- let url = new URL("facades", baseUrl);
- let resp = await axios.post(
- url.href,
- {
- name: "malformed-facade",
- type: "taler-wire-gateway",
- config: {}, // malformation here.
- },
- {
- auth: {
- username: "admin",
- password: "test",
- },
- validateStatus: () => true,
- },
- );
- t.assertTrue(resp.status == 400);
-}
-
-runLibeufinApiFacadeBadRequestTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-facade.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-facade.ts
deleted file mode 100644
index 946c565d4..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-facade.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- SandboxUserBundle,
- NexusUserBundle,
- launchLibeufinServices,
- LibeufinNexusApi,
-} from "../harness/libeufin.js";
-
-/**
- * Run basic test with LibEuFin.
- */
-export async function runLibeufinApiFacadeTest(t: GlobalTestState) {
- /**
- * User saltetd "01"
- */
- const user01nexus = new NexusUserBundle(
- "01",
- "http://localhost:5010/ebicsweb",
- );
- const user01sandbox = new SandboxUserBundle("01");
-
- /**
- * Launch Sandbox and Nexus.
- */
- const libeufinServices = await launchLibeufinServices(
- t,
- [user01nexus],
- [user01sandbox],
- ["twg"],
- );
- let resp = await LibeufinNexusApi.getAllFacades(
- libeufinServices.libeufinNexus,
- );
- // check that original facade shows up.
- t.assertTrue(resp.data["facades"][0]["name"] == user01nexus.twgReq["name"]);
-
- const twgBaseUrl: string = resp.data["facades"][0]["baseUrl"];
- t.assertTrue(typeof twgBaseUrl === "string");
- t.assertTrue(twgBaseUrl.startsWith("http://"));
- t.assertTrue(twgBaseUrl.endsWith("/"));
-
- // delete it.
- resp = await LibeufinNexusApi.deleteFacade(
- libeufinServices.libeufinNexus,
- user01nexus.twgReq["name"],
- );
- // check that no facades show up.
- t.assertTrue(!resp.data.hasOwnProperty("facades"));
-}
-
-runLibeufinApiFacadeTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-permissions.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-permissions.ts
deleted file mode 100644
index f8f2d7d80..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-permissions.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- NexusUserBundle,
- LibeufinNexusApi,
- LibeufinNexusService,
-} from "../harness/libeufin.js";
-
-/**
- * Run basic test with LibEuFin.
- */
-export async function runLibeufinApiPermissionsTest(t: GlobalTestState) {
- const nexus = await LibeufinNexusService.create(t, {
- httpPort: 5011,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-nexus.sqlite3`,
- });
- await nexus.start();
- await nexus.pingUntilAvailable();
-
- const user01nexus = new NexusUserBundle(
- "01",
- "http://localhost:5010/ebicsweb",
- );
-
- await LibeufinNexusApi.createUser(nexus, user01nexus.userReq);
- await LibeufinNexusApi.postPermission(
- nexus,
- user01nexus.twgTransferPermission,
- );
- let transferPermission = await LibeufinNexusApi.getAllPermissions(nexus);
- let element = transferPermission.data["permissions"].pop();
- t.assertTrue(
- element["permissionName"] == "facade.talerwiregateway.transfer" &&
- element["subjectId"] == "username-01",
- );
- let denyTransfer = user01nexus.twgTransferPermission;
-
- // Now revoke permission.
- denyTransfer["action"] = "revoke";
- await LibeufinNexusApi.postPermission(nexus, denyTransfer);
-
- transferPermission = await LibeufinNexusApi.getAllPermissions(nexus);
- t.assertTrue(transferPermission.data["permissions"].length == 0);
-}
-
-runLibeufinApiPermissionsTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-sandbox-camt.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-sandbox-camt.ts
deleted file mode 100644
index cb85c1ffc..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-sandbox-camt.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- LibeufinSandboxApi,
- LibeufinSandboxService,
-} from "../harness/libeufin.js";
-
-// This test only checks that LibEuFin doesn't fail when
-// it generates Camt statements - no assertions take place.
-// Furthermore, it prints the Camt.053 being generated.
-export async function runLibeufinApiSandboxCamtTest(t: GlobalTestState) {
- const sandbox = await LibeufinSandboxService.create(t, {
- httpPort: 5012,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-sandbox.sqlite3`,
- });
- await sandbox.start();
- await sandbox.pingUntilAvailable();
-
- await LibeufinSandboxApi.createDemobankAccount(
- "mock-account-0",
- "password-unused",
- { baseUrl: sandbox.baseUrl + "/demobanks/default/access-api/" }
- );
- await LibeufinSandboxApi.createDemobankAccount(
- "mock-account-1",
- "password-unused",
- { baseUrl: sandbox.baseUrl + "/demobanks/default/access-api/" }
- );
- await sandbox.makeTransaction(
- "mock-account-0",
- "mock-account-1",
- "EUR:1",
- "+1",
- );
- await sandbox.makeTransaction(
- "mock-account-0",
- "mock-account-1",
- "EUR:1",
- "+1",
- );
- await sandbox.makeTransaction(
- "mock-account-0",
- "mock-account-1",
- "EUR:1",
- "+1",
- );
- await sandbox.makeTransaction(
- "mock-account-1",
- "mock-account-0",
- "EUR:5",
- "minus 5",
- );
- await sandbox.c53tick();
- let ret = await LibeufinSandboxApi.getCamt053(sandbox, "mock-account-1");
- console.log(ret);
-}
-runLibeufinApiSandboxCamtTest.excludeByDefault = true;
-runLibeufinApiSandboxCamtTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-sandbox-transactions.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-sandbox-transactions.ts
deleted file mode 100644
index 24fd9d3ef..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-sandbox-transactions.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- LibeufinSandboxApi,
- LibeufinSandboxService,
-} from "../harness/libeufin.js";
-
-export async function runLibeufinApiSandboxTransactionsTest(
- t: GlobalTestState,
-) {
- const sandbox = await LibeufinSandboxService.create(t, {
- httpPort: 5012,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-sandbox.sqlite3`,
- });
- await sandbox.start();
- await sandbox.pingUntilAvailable();
- await LibeufinSandboxApi.createDemobankAccount(
- "mock-account",
- "password-unused",
- { baseUrl: sandbox.baseUrl + "/demobanks/default/access-api/" },
- "DE71500105179674997361"
- );
- await LibeufinSandboxApi.simulateIncomingTransaction(
- sandbox,
- "mock-account",
- {
- debtorIban: "DE84500105176881385584",
- debtorBic: "BELADEBEXXX",
- debtorName: "mock2",
- subject: "mock subject",
- amount: "1", // EUR is default.
- },
- );
- await LibeufinSandboxApi.simulateIncomingTransaction(
- sandbox,
- "mock-account",
- {
- debtorIban: "DE84500105176881385584",
- debtorBic: "BELADEBEXXX",
- debtorName: "mock2",
- subject: "mock subject 2",
- amount: "1.1", // EUR is default.
- },
- );
- let ret = await LibeufinSandboxApi.getAccountInfoWithBalance(
- sandbox,
- "mock-account",
- );
- t.assertAmountEquals(ret.data.balance, "EUR:2.1");
-}
-runLibeufinApiSandboxTransactionsTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-scheduling.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-scheduling.ts
deleted file mode 100644
index 95f4bfaa0..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-scheduling.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- launchLibeufinServices,
- LibeufinNexusApi,
- LibeufinNexusService,
- NexusUserBundle,
- SandboxUserBundle,
-} from "../harness/libeufin.js";
-
-/**
- * Test Nexus scheduling API. It creates a task, check whether it shows
- * up, then deletes it, and check if it's gone. Ideally, a check over the
- * _liveliness_ of a scheduled task should happen.
- */
-export async function runLibeufinApiSchedulingTest(t: GlobalTestState) {
- const nexus = await LibeufinNexusService.create(t, {
- httpPort: 5011,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-nexus.sqlite3`,
- });
- await nexus.start();
- await nexus.pingUntilAvailable();
-
- const user01nexus = new NexusUserBundle(
- "01",
- "http://localhost:5010/ebicsweb",
- );
- const user01sandbox = new SandboxUserBundle("01");
- await launchLibeufinServices(t, [user01nexus], [user01sandbox]);
- await LibeufinNexusApi.postTask(nexus, user01nexus.localAccountName, {
- name: "test-task",
- cronspec: "* * *",
- type: "fetch",
- params: {
- level: "all",
- rangeType: "all",
- },
- });
- let resp = await LibeufinNexusApi.getTasks(
- nexus,
- user01nexus.localAccountName,
- "test-task",
- );
- t.assertTrue(resp.data["taskName"] == "test-task");
- await LibeufinNexusApi.deleteTask(
- nexus,
- user01nexus.localAccountName,
- "test-task",
- );
- try {
- await LibeufinNexusApi.getTasks(
- nexus,
- user01nexus.localAccountName,
- "test-task",
- );
- } catch (err: any) {
- t.assertTrue(err.response.status == 404);
- }
-
- // Same with submit task.
- await LibeufinNexusApi.postTask(nexus, user01nexus.localAccountName, {
- name: "test-task",
- cronspec: "* * *",
- type: "submit",
- params: {},
- });
- resp = await LibeufinNexusApi.getTasks(
- nexus,
- user01nexus.localAccountName,
- "test-task",
- );
- t.assertTrue(resp.data["taskName"] == "test-task");
- await LibeufinNexusApi.deleteTask(
- nexus,
- user01nexus.localAccountName,
- "test-task",
- );
- try {
- await LibeufinNexusApi.getTasks(
- nexus,
- user01nexus.localAccountName,
- "test-task",
- );
- } catch (err: any) {
- t.assertTrue(err.response.status == 404);
- }
-}
-runLibeufinApiSchedulingTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-users.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-users.ts
deleted file mode 100644
index bc3103c7e..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-api-users.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import { LibeufinNexusApi, LibeufinNexusService } from "../harness/libeufin.js";
-
-/**
- * Run basic test with LibEuFin.
- */
-export async function runLibeufinApiUsersTest(t: GlobalTestState) {
- const nexus = await LibeufinNexusService.create(t, {
- httpPort: 5011,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-nexus.sqlite3`,
- });
- await nexus.start();
- await nexus.pingUntilAvailable();
-
- await LibeufinNexusApi.createUser(nexus, {
- username: "one",
- password: "will-be-changed",
- });
-
- await LibeufinNexusApi.changePassword(
- nexus,
- "one",
- {
- newPassword: "got-changed",
- },
- {
- auth: {
- username: "admin",
- password: "test",
- },
- },
- );
-
- let resp = await LibeufinNexusApi.getUser(nexus, {
- auth: {
- username: "one",
- password: "got-changed",
- },
- });
- console.log(resp.data);
- t.assertTrue(resp.data["username"] == "one" && !resp.data["superuser"]);
-}
-
-runLibeufinApiUsersTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-bad-gateway.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-bad-gateway.ts
deleted file mode 100644
index 53aacca84..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-bad-gateway.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- 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 { GlobalTestState, delayMs } from "../harness/harness.js";
-import {
- NexusUserBundle,
- LibeufinNexusApi,
- LibeufinNexusService,
- LibeufinSandboxService,
-} from "../harness/libeufin.js";
-
-/**
- * Testing how Nexus reacts when the Sandbox is unreachable.
- * Typically, because the user specified a wrong EBICS endpoint.
- */
-export async function runLibeufinBadGatewayTest(t: GlobalTestState) {
- /**
- * User saltetd "01"
- */
- const user01nexus = new NexusUserBundle(
- "01", "http://localhost:5010/not-found", // the EBICS endpoint at Sandbox
- );
-
- // Start Nexus
- const libeufinNexus = await LibeufinNexusService.create(t, {
- httpPort: 5011,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-nexus.sqlite3`,
- });
- await libeufinNexus.start();
- await libeufinNexus.pingUntilAvailable();
-
- // Start Sandbox
- const libeufinSandbox = await LibeufinSandboxService.create(t, {
- httpPort: 5010,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-sandbox.sqlite3`,
- });
- await libeufinSandbox.start();
- await libeufinSandbox.pingUntilAvailable();
-
- // Connecting to a non-existent Sandbox endpoint.
- await LibeufinNexusApi.createEbicsBankConnection(
- libeufinNexus,
- user01nexus.connReq
- );
-
- // 502 Bad Gateway expected.
- try {
- await LibeufinNexusApi.connectBankConnection(
- libeufinNexus,
- user01nexus.connReq.name,
- );
- } catch(e: any) {
- t.assertTrue(e.response.status == 502);
- return;
- }
- t.assertTrue(false);
-}
-runLibeufinBadGatewayTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-basic.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-basic.ts
deleted file mode 100644
index 94fd76683..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-basic.ts
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- 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 { AbsoluteTime, MerchantContractTerms, Duration } from "@gnu-taler/taler-util";
-import {
- WalletApiOperation,
- HarnessExchangeBankAccount,
-} from "@gnu-taler/taler-wallet-core";
-import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
-import {
- DbInfo,
- ExchangeService,
- GlobalTestState,
- MerchantService,
- setupDb,
- WalletCli,
-} from "../harness/harness.js";
-import { makeTestPayment } from "../harness/helpers.js";
-import {
- LibeufinNexusApi,
- LibeufinNexusService,
- LibeufinSandboxApi,
- LibeufinSandboxService,
-} from "../harness/libeufin.js";
-
-const exchangeIban = "DE71500105179674997361";
-const customerIban = "DE84500105176881385584";
-const customerBic = "BELADEBEXXX";
-const merchantIban = "DE42500105171245624648";
-
-export interface LibeufinTestEnvironment {
- commonDb: DbInfo;
- exchange: ExchangeService;
- exchangeBankAccount: HarnessExchangeBankAccount;
- merchant: MerchantService;
- wallet: WalletCli;
- libeufinSandbox: LibeufinSandboxService;
- libeufinNexus: LibeufinNexusService;
-}
-
-/**
- * Create a Taler environment with LibEuFin and an EBICS account.
- */
-export async function createLibeufinTestEnvironment(
- t: GlobalTestState,
- coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("EUR")),
-): Promise<LibeufinTestEnvironment> {
- const db = await setupDb(t);
-
- const libeufinSandbox = await LibeufinSandboxService.create(t, {
- httpPort: 5010,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-sandbox.sqlite3`,
- });
-
- await libeufinSandbox.start();
- await libeufinSandbox.pingUntilAvailable();
-
- const libeufinNexus = await LibeufinNexusService.create(t, {
- httpPort: 5011,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-nexus.sqlite3`,
- });
-
- await libeufinNexus.start();
- await libeufinNexus.pingUntilAvailable();
-
- await LibeufinSandboxApi.createEbicsHost(libeufinSandbox, "host01");
- // Subscriber and bank Account for the exchange
- await LibeufinSandboxApi.createDemobankAccount(
- "exchangeacct",
- "password-unused",
- { baseUrl: libeufinSandbox.baseUrl + "/demobanks/default/access-api/" },
- exchangeIban
- );
- await LibeufinSandboxApi.createDemobankEbicsSubscriber(
- {
- hostID: "host01",
- partnerID: "partner01",
- userID: "user01",
- },
- "exchangeacct",
- { baseUrl: libeufinSandbox.baseUrl + "/demobanks/default/" }
- );
-
- await LibeufinSandboxApi.createDemobankAccount(
- "merchantacct",
- "password-unused",
- { baseUrl: libeufinSandbox.baseUrl + "/demobanks/default/access-api/" },
- merchantIban
- );
- await LibeufinSandboxApi.createDemobankEbicsSubscriber(
- {
- hostID: "host01",
- partnerID: "partner02",
- userID: "user02",
- },
- "merchantacct",
- { baseUrl: libeufinSandbox.baseUrl + "/demobanks/default/" },
- );
-
- await LibeufinNexusApi.createEbicsBankConnection(libeufinNexus, {
- name: "myconn",
- ebicsURL: "http://localhost:5010/ebicsweb",
- hostID: "host01",
- partnerID: "partner01",
- userID: "user01",
- });
- await LibeufinNexusApi.connectBankConnection(libeufinNexus, "myconn");
- await LibeufinNexusApi.fetchAccounts(libeufinNexus, "myconn");
- await LibeufinNexusApi.importConnectionAccount(
- libeufinNexus,
- "myconn",
- "exchangeacct",
- "myacct",
- );
-
- await LibeufinNexusApi.createTwgFacade(libeufinNexus, {
- name: "twg1",
- accountName: "myacct",
- connectionName: "myconn",
- currency: "EUR",
- reserveTransferLevel: "report",
- });
-
- await LibeufinNexusApi.createUser(libeufinNexus, {
- username: "twguser",
- password: "twgpw",
- });
-
- await LibeufinNexusApi.postPermission(libeufinNexus, {
- action: "grant",
- permission: {
- subjectType: "user",
- subjectId: "twguser",
- resourceType: "facade",
- resourceId: "twg1",
- permissionName: "facade.talerWireGateway.history",
- },
- });
-
- await LibeufinNexusApi.postPermission(libeufinNexus, {
- action: "grant",
- permission: {
- subjectType: "user",
- subjectId: "twguser",
- resourceType: "facade",
- resourceId: "twg1",
- permissionName: "facade.talerWireGateway.transfer",
- },
- });
-
- const exchange = ExchangeService.create(t, {
- name: "testexchange-1",
- currency: "EUR",
- httpPort: 8081,
- database: db.connStr,
- });
-
- const merchant = await MerchantService.create(t, {
- name: "testmerchant-1",
- currency: "EUR",
- httpPort: 8083,
- database: db.connStr,
- });
-
- const exchangeBankAccount: HarnessExchangeBankAccount = {
- accountName: "twguser",
- accountPassword: "twgpw",
- accountPaytoUri: `payto://iban/${exchangeIban}?receiver-name=Exchange`,
- wireGatewayApiBaseUrl:
- "http://localhost:5011/facades/twg1/taler-wire-gateway/",
- };
-
- exchange.addBankAccount("1", exchangeBankAccount);
-
- exchange.addCoinConfigList(coinConfig);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [`payto://iban/${merchantIban}?receiver-name=Merchant`],
- defaultWireTransferDelay: Duration.toTalerProtocolDuration(
- Duration.getZero(),
- ),
- });
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- return {
- commonDb: db,
- exchange,
- merchant,
- wallet,
- exchangeBankAccount,
- libeufinNexus,
- libeufinSandbox,
- };
-}
-
-/**
- * Run basic test with LibEuFin.
- */
-export async function runLibeufinBasicTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, exchange, merchant, libeufinSandbox, libeufinNexus } =
- await createLibeufinTestEnvironment(t);
-
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: exchange.baseUrl,
- });
-
- const wr = await wallet.client.call(
- WalletApiOperation.AcceptManualWithdrawal,
- {
- exchangeBaseUrl: exchange.baseUrl,
- amount: "EUR:15",
- },
- );
-
- const reservePub: string = wr.reservePub;
-
- await LibeufinSandboxApi.simulateIncomingTransaction(
- libeufinSandbox,
- "exchangeacct",
- {
- amount: "15.00",
- debtorBic: customerBic,
- debtorIban: customerIban,
- debtorName: "Jane Customer",
- subject: `Taler Top-up ${reservePub}`,
- },
- );
-
- await LibeufinNexusApi.fetchTransactions(libeufinNexus, "myacct");
-
- await exchange.runWirewatchOnce();
-
- await wallet.runUntilDone();
-
- const bal = await wallet.client.call(WalletApiOperation.GetBalances, {});
- console.log("balances", JSON.stringify(bal, undefined, 2));
- t.assertAmountEquals(bal.balances[0].available, "EUR:14.7");
-
- const order: Partial<MerchantContractTerms> = {
- summary: "Buy me!",
- amount: "EUR:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- wire_transfer_deadline: AbsoluteTime.toTimestamp(AbsoluteTime.now()),
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
-
- await exchange.runAggregatorOnce();
- await exchange.runTransferOnce();
-
- await LibeufinNexusApi.submitAllPaymentInitiations(libeufinNexus, "myacct");
-
- const exchangeTransactions = await LibeufinSandboxApi.getAccountTransactions(
- libeufinSandbox,
- "exchangeacct",
- );
-
- console.log(
- "exchange transactions:",
- JSON.stringify(exchangeTransactions, undefined, 2),
- );
-
- t.assertDeepEqual(
- exchangeTransactions.payments[0].creditDebitIndicator,
- "credit",
- );
- t.assertDeepEqual(
- exchangeTransactions.payments[1].creditDebitIndicator,
- "debit",
- );
- t.assertDeepEqual(exchangeTransactions.payments[1].debtorIban, exchangeIban);
- t.assertDeepEqual(
- exchangeTransactions.payments[1].creditorIban,
- merchantIban,
- );
-}
-runLibeufinBasicTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-c5x.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-c5x.ts
deleted file mode 100644
index 2ba29656a..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-c5x.ts
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- launchLibeufinServices,
- LibeufinNexusApi,
- NexusUserBundle,
- SandboxUserBundle,
-} from "../harness/libeufin.js";
-
-/**
- * This test checks how the C52 and C53 coordinate. It'll test
- * whether fresh transactions stop showing as C52 after they get
- * included in a bank statement.
- */
-export async function runLibeufinC5xTest(t: GlobalTestState) {
- /**
- * User saltetd "01"
- */
- const user01nexus = new NexusUserBundle(
- "01",
- "http://localhost:5010/ebicsweb",
- );
- const user01sandbox = new SandboxUserBundle("01");
-
- /**
- * User saltetd "02".
- */
- const user02nexus = new NexusUserBundle(
- "02",
- "http://localhost:5010/ebicsweb",
- );
- const user02sandbox = new SandboxUserBundle("02");
-
- /**
- * Launch Sandbox and Nexus.
- */
- const libeufinServices = await launchLibeufinServices(
- t,
- [user01nexus, user02nexus],
- [user01sandbox, user02sandbox],
- ["twg"],
- );
-
- // Check that C52 and C53 have zero entries.
-
- // C52
- await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- "all", // range
- "report", // level
- );
- // C53
- await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- "all", // range
- "statement", // level
- );
- const nexusTxs = await LibeufinNexusApi.getAccountTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- );
- t.assertTrue(nexusTxs.data["transactions"].length == 0);
-
- // Addressing one payment to user 01
- await libeufinServices.libeufinSandbox.makeTransaction(
- user02sandbox.ebicsBankAccount.label, // debit
- user01sandbox.ebicsBankAccount.label, // credit
- "EUR:10",
- "first payment",
- );
-
- let expectOne = await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- "all", // range
- "report", // C52
- );
- t.assertTrue(expectOne.data.newTransactions == 1);
- t.assertTrue(expectOne.data.downloadedTransactions == 1);
-
- /* Expect zero payments being downloaded because the
- * previous request consumed already the one pending
- * payment.
- */
- let expectZero = await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- "all", // range
- "report", // C52
- );
- t.assertTrue(expectZero.data.newTransactions == 0);
- t.assertTrue(expectZero.data.downloadedTransactions == 0);
-
- /**
- * A statement should still account zero payments because
- * so far the payment made before is still pending.
- */
- expectZero = await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- "all", // range
- "statement", // C53
- );
- t.assertTrue(expectZero.data.newTransactions == 0);
- t.assertTrue(expectZero.data.downloadedTransactions == 0);
-
- /**
- * Ticking now. That books any pending transaction.
- */
- await libeufinServices.libeufinSandbox.c53tick();
-
- /**
- * A statement is now expected to download the transaction,
- * although that got already ingested along the report
- * earlier. Thus the transaction counts as downloaded but
- * not as new.
- */
- expectOne = await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- "all", // range
- "statement", // C53
- );
- t.assertTrue(expectOne.data.downloadedTransactions == 1);
- t.assertTrue(expectOne.data.newTransactions == 0);
-}
-runLibeufinC5xTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-facade-anastasis.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-facade-anastasis.ts
deleted file mode 100644
index 1ed258c3a..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-facade-anastasis.ts
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- SandboxUserBundle,
- NexusUserBundle,
- launchLibeufinServices,
- LibeufinNexusApi,
- LibeufinSandboxApi,
-} from "../harness/libeufin.js";
-
-/**
- * Testing the Anastasis API, offered by the Anastasis facade.
- */
-export async function runLibeufinAnastasisFacadeTest(t: GlobalTestState) {
- /**
- * User saltetd "01"
- */
- const user01nexus = new NexusUserBundle(
- "01",
- "http://localhost:5010/ebicsweb",
- );
- const user01sandbox = new SandboxUserBundle("01");
-
- /**
- * Launch Sandbox and Nexus.
- */
- const libeufinServices = await launchLibeufinServices(
- t,
- [user01nexus],
- [user01sandbox],
- ["anastasis"], // create only one Anastasis facade.
- );
- let resp = await LibeufinNexusApi.getAllFacades(
- libeufinServices.libeufinNexus,
- );
- // check that original facade shows up.
- t.assertTrue(resp.data["facades"][0]["name"] == user01nexus.anastasisReq["name"]);
- const anastasisBaseUrl: string = resp.data["facades"][0]["baseUrl"];
- t.assertTrue(typeof anastasisBaseUrl === "string");
- t.assertTrue(anastasisBaseUrl.startsWith("http://"));
- t.assertTrue(anastasisBaseUrl.endsWith("/"));
-
- await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- );
-
- await LibeufinNexusApi.postPermission(
- libeufinServices.libeufinNexus, {
- action: "grant",
- permission: {
- subjectId: user01nexus.userReq.username,
- subjectType: "user",
- resourceType: "facade",
- resourceId: user01nexus.anastasisReq.name,
- permissionName: "facade.anastasis.history",
- },
- }
- );
-
- // check if empty.
- let txsEmpty = await LibeufinNexusApi.getAnastasisTransactions(
- libeufinServices.libeufinNexus,
- anastasisBaseUrl, {delta: 5})
-
- t.assertTrue(txsEmpty.data.incoming_transactions.length == 0);
-
- LibeufinSandboxApi.simulateIncomingTransaction(
- libeufinServices.libeufinSandbox,
- user01sandbox.ebicsBankAccount.label,
- {
- debtorIban: "ES3314655813489414469157",
- debtorBic: "BCMAESM1XXX",
- debtorName: "Mock Donor",
- subject: "Anastasis donation",
- amount: "3", // Sandbox takes currency from its 'config'
- },
- )
-
- LibeufinSandboxApi.simulateIncomingTransaction(
- libeufinServices.libeufinSandbox,
- user01sandbox.ebicsBankAccount.label,
- {
- debtorIban: "ES3314655813489414469157",
- debtorBic: "BCMAESM1XXX",
- debtorName: "Mock Donor",
- subject: "another Anastasis donation",
- amount: "1", // Sandbox takes currency from its "config"
- },
- )
-
- await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- );
-
- let txs = await LibeufinNexusApi.getAnastasisTransactions(
- libeufinServices.libeufinNexus,
- anastasisBaseUrl,
- {delta: 5},
- user01nexus.userReq.username,
- user01nexus.userReq.password,
- );
-
- // check the two payments show up
- let txsList = txs.data.incoming_transactions
- t.assertTrue(txsList.length == 2);
- t.assertTrue([txsList[0].subject, txsList[1].subject].includes("Anastasis donation"));
- t.assertTrue([txsList[0].subject, txsList[1].subject].includes("another Anastasis donation"));
- t.assertTrue(txsList[0].row_id == 1)
- t.assertTrue(txsList[1].row_id == 2)
-
- LibeufinSandboxApi.simulateIncomingTransaction(
- libeufinServices.libeufinSandbox,
- user01sandbox.ebicsBankAccount.label,
- {
- debtorIban: "ES3314655813489414469157",
- debtorBic: "BCMAESM1XXX",
- debtorName: "Mock Donor",
- subject: "last Anastasis donation",
- amount: "10.10", // Sandbox takes currency from its "config"
- },
- )
-
- await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- );
-
- let txsLast = await LibeufinNexusApi.getAnastasisTransactions(
- libeufinServices.libeufinNexus,
- anastasisBaseUrl,
- {delta: 5, start: 2},
- user01nexus.userReq.username,
- user01nexus.userReq.password,
- );
- console.log(txsLast.data.incoming_transactions[0].subject == "last Anastasis donation");
-
- let txsReverse = await LibeufinNexusApi.getAnastasisTransactions(
- libeufinServices.libeufinNexus,
- anastasisBaseUrl,
- {delta: -5, start: 4},
- user01nexus.userReq.username,
- user01nexus.userReq.password,
- );
- t.assertTrue(txsReverse.data.incoming_transactions[0].row_id == 3);
- t.assertTrue(txsReverse.data.incoming_transactions[1].row_id == 2);
- t.assertTrue(txsReverse.data.incoming_transactions[2].row_id == 1);
-}
-
-runLibeufinAnastasisFacadeTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-keyrotation.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-keyrotation.ts
deleted file mode 100644
index 21bf07de2..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-keyrotation.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- SandboxUserBundle,
- NexusUserBundle,
- launchLibeufinServices,
- LibeufinSandboxApi,
- LibeufinNexusApi,
-} from "../harness/libeufin.js";
-
-/**
- * Run basic test with LibEuFin.
- */
-export async function runLibeufinKeyrotationTest(t: GlobalTestState) {
- /**
- * User saltetd "01"
- */
- const user01nexus = new NexusUserBundle(
- "01",
- "http://localhost:5010/ebicsweb",
- );
- const user01sandbox = new SandboxUserBundle("01");
-
- /**
- * Launch Sandbox and Nexus.
- */
- const libeufinServices = await launchLibeufinServices(
- t, [user01nexus], [user01sandbox],
- );
-
- await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- );
-
- /* Rotate the Sandbox keys, and fetch the transactions again */
- await LibeufinSandboxApi.rotateKeys(
- libeufinServices.libeufinSandbox,
- user01sandbox.ebicsBankAccount.subscriber.hostID,
- );
-
- try {
- await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- );
- } catch (e: any) {
- /**
- * Asserting that Nexus responded with a 500 Internal server
- * error, because the bank signed the last response with a new
- * key pair that was never downloaded by Nexus.
- *
- * NOTE: the bank accepted the request addressed to the old
- * public key. Should it in this case reject the request even
- * before trying to verify it?
- */
- t.assertTrue(e.response.status == 500);
- t.assertTrue(e.response.data.code == 9000);
- }
-}
-runLibeufinKeyrotationTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-nexus-balance.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-nexus-balance.ts
deleted file mode 100644
index 850b0f1d9..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-nexus-balance.ts
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- SandboxUserBundle,
- NexusUserBundle,
- launchLibeufinServices,
- LibeufinNexusApi,
- LibeufinCli
-} from "../harness/libeufin.js";
-
-/**
- * This test checks how the C52 and C53 coordinate. It'll test
- * whether fresh transactions stop showing as C52 after they get
- * included in a bank statement.
- */
-export async function runLibeufinNexusBalanceTest(t: GlobalTestState) {
- /**
- * User saltetd "01"
- */
- const user01nexus = new NexusUserBundle(
- "01",
- "http://localhost:5010/ebicsweb",
- );
- const user01sandbox = new SandboxUserBundle("01");
-
- /**
- * User saltetd "02".
- */
- const user02nexus = new NexusUserBundle(
- "02",
- "http://localhost:5010/ebicsweb",
- );
- const user02sandbox = new SandboxUserBundle("02");
-
- /**
- * Launch Sandbox and Nexus.
- */
- const libeufinServices = await launchLibeufinServices(
- t,
- [user01nexus, user02nexus],
- [user01sandbox, user02sandbox],
- ["twg"],
- );
-
- // user 01 gets 10
- await libeufinServices.libeufinSandbox.makeTransaction(
- user02sandbox.ebicsBankAccount.label, // debit
- user01sandbox.ebicsBankAccount.label, // credit
- "EUR:10",
- "first payment",
- );
- // user 01 gets another 10
- await libeufinServices.libeufinSandbox.makeTransaction(
- user02sandbox.ebicsBankAccount.label, // debit
- user01sandbox.ebicsBankAccount.label, // credit
- "EUR:10",
- "second payment",
- );
-
- await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- "all", // range
- "report", // level
- );
-
- // Check that user 01 has 20, via Nexus.
- let accountInfo = await LibeufinNexusApi.getBankAccount(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- );
- t.assertAmountEquals(accountInfo.data.lastSeenBalance, "EUR:20");
-
- // Booking the first two transactions.
- await libeufinServices.libeufinSandbox.c53tick();
-
- // user 01 gives 30
- await libeufinServices.libeufinSandbox.makeTransaction(
- user01sandbox.ebicsBankAccount.label,
- user02sandbox.ebicsBankAccount.label,
- "EUR:30",
- "third payment",
- );
-
- await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- "all", // range
- "report", // level
- );
-
- let accountInfoDebit = await LibeufinNexusApi.getBankAccount(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- );
- t.assertDeepEqual(accountInfoDebit.data.lastSeenBalance, "-EUR:10");
-}
-
-runLibeufinNexusBalanceTest.suites = ["libeufin"];
-runLibeufinNexusBalanceTest.excludeByDefault = true;
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-refund-multiple-users.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-refund-multiple-users.ts
deleted file mode 100644
index 245f34331..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-refund-multiple-users.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- 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 { GlobalTestState, delayMs } from "../harness/harness.js";
-import {
- SandboxUserBundle,
- NexusUserBundle,
- launchLibeufinServices,
- LibeufinSandboxApi,
- LibeufinNexusApi,
-} from "../harness/libeufin.js";
-
-/**
- * User 01 expects a refund from user 02, and expectedly user 03
- * should not be involved in the process.
- */
-export async function runLibeufinRefundMultipleUsersTest(t: GlobalTestState) {
- /**
- * User saltetd "01"
- */
- const user01nexus = new NexusUserBundle(
- "01",
- "http://localhost:5010/ebicsweb",
- );
- const user01sandbox = new SandboxUserBundle("01");
-
- /**
- * User saltetd "02"
- */
- const user02nexus = new NexusUserBundle(
- "02",
- "http://localhost:5010/ebicsweb",
- );
- const user02sandbox = new SandboxUserBundle("02");
-
- /**
- * User saltetd "03"
- */
- const user03nexus = new NexusUserBundle(
- "03",
- "http://localhost:5010/ebicsweb",
- );
- const user03sandbox = new SandboxUserBundle("03");
-
- /**
- * Launch Sandbox and Nexus.
- */
- const libeufinServices = await launchLibeufinServices(
- t,
- [user01nexus, user02nexus],
- [user01sandbox, user02sandbox],
- ["twg"],
- );
-
- // user 01 gets the payment
- await libeufinServices.libeufinSandbox.makeTransaction(
- user02sandbox.ebicsBankAccount.label, // debit
- user01sandbox.ebicsBankAccount.label, // credit
- "EUR:1",
- "not a public key",
- );
-
- // user 01 fetches the payments
- await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- );
-
- // user 01 tries to submit the reimbursement, as
- // the payment didn't have a valid public key in
- // the subject.
- await LibeufinNexusApi.submitInitiatedPayment(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- "1", // so far the only one that can exist.
- );
-
- // user 02 checks whether a reimbursement arrived.
- let history = await LibeufinSandboxApi.getAccountTransactions(
- libeufinServices.libeufinSandbox,
- user02sandbox.ebicsBankAccount["label"],
- );
- // reimbursement arrived IFF the total payments are 2:
- // 1 the original (faulty) transaction + 1 the reimbursement.
- t.assertTrue(history["payments"].length == 2);
-}
-
-runLibeufinRefundMultipleUsersTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-refund.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-refund.ts
deleted file mode 100644
index 9d90121a0..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-refund.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- 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 { GlobalTestState, delayMs } from "../harness/harness.js";
-import {
- SandboxUserBundle,
- NexusUserBundle,
- launchLibeufinServices,
- LibeufinSandboxApi,
- LibeufinNexusApi,
-} from "../harness/libeufin.js";
-
-/**
- * Run basic test with LibEuFin.
- */
-export async function runLibeufinRefundTest(t: GlobalTestState) {
- /**
- * User saltetd "01"
- */
- const user01nexus = new NexusUserBundle(
- "01",
- "http://localhost:5010/ebicsweb",
- );
- const user01sandbox = new SandboxUserBundle("01");
-
- /**
- * User saltetd "02"
- */
- const user02nexus = new NexusUserBundle(
- "02",
- "http://localhost:5010/ebicsweb",
- );
- const user02sandbox = new SandboxUserBundle("02");
-
- /**
- * Launch Sandbox and Nexus.
- */
- const libeufinServices = await launchLibeufinServices(
- t,
- [user01nexus, user02nexus],
- [user01sandbox, user02sandbox],
- ["twg"],
- );
-
- // user 02 pays user 01 with a faulty (non Taler) subject.
- await libeufinServices.libeufinSandbox.makeTransaction(
- user02sandbox.ebicsBankAccount.label, // debit
- user01sandbox.ebicsBankAccount.label, // credit
- "EUR:1",
- "not a public key",
- );
-
- // The bad payment should be now ingested and prepared as
- // a reimbursement.
- await LibeufinNexusApi.fetchTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- );
- // Check that the payment arrived at the Nexus.
- const nexusTxs = await LibeufinNexusApi.getAccountTransactions(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- );
- t.assertTrue(nexusTxs.data["transactions"].length == 1);
-
- // Submit the reimbursement
- await LibeufinNexusApi.submitInitiatedPayment(
- libeufinServices.libeufinNexus,
- user01nexus.localAccountName,
- // The initiated payment (= the reimbursement) ID below
- // got set by the Taler facade; at this point only one must
- // exist. If "1" is not found, a 404 will make this test fail.
- "1",
- );
-
- // user 02 checks whether the reimbursement arrived.
- let history = await LibeufinSandboxApi.getAccountTransactions(
- libeufinServices.libeufinSandbox,
- user02sandbox.ebicsBankAccount["label"],
- );
- // 2 payments must exist: 1 the original (faulty) payment +
- // 1 the reimbursement.
- t.assertTrue(history["payments"].length == 2);
-}
-runLibeufinRefundTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-sandbox-wire-transfer-cli.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-sandbox-wire-transfer-cli.ts
deleted file mode 100644
index e56cb3d68..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-sandbox-wire-transfer-cli.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- LibeufinSandboxApi,
- LibeufinSandboxService,
-} from "../harness/libeufin.js";
-
-export async function runLibeufinSandboxWireTransferCliTest(
- t: GlobalTestState,
-) {
- const sandbox = await LibeufinSandboxService.create(t, {
- httpPort: 5012,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-sandbox.sqlite3`,
- });
- await sandbox.start();
- await sandbox.pingUntilAvailable();
- await LibeufinSandboxApi.createDemobankAccount(
- "mock-account",
- "password-unused",
- { baseUrl: sandbox.baseUrl + "/demobanks/default/access-api/" },
- "DE71500105179674997361"
- );
- await LibeufinSandboxApi.createDemobankAccount(
- "mock-account-2",
- "password-unused",
- { baseUrl: sandbox.baseUrl + "/demobanks/default/access-api/" },
- "DE71500105179674997364"
- );
-
- await sandbox.makeTransaction(
- "mock-account",
- "mock-account-2",
- "EUR:1",
- "one!",
- );
- await sandbox.makeTransaction(
- "mock-account",
- "mock-account-2",
- "EUR:1",
- "two!",
- );
- await sandbox.makeTransaction(
- "mock-account",
- "mock-account-2",
- "EUR:1",
- "three!",
- );
- await sandbox.makeTransaction(
- "mock-account-2",
- "mock-account",
- "EUR:1",
- "Give one back.",
- );
- await sandbox.makeTransaction(
- "mock-account-2",
- "mock-account",
- "EUR:0.11",
- "Give fraction back.",
- );
- let ret = await LibeufinSandboxApi.getAccountInfoWithBalance(
- sandbox,
- "mock-account-2",
- );
- console.log(ret.data.balance);
- t.assertTrue(ret.data.balance == "EUR:1.89");
-}
-runLibeufinSandboxWireTransferCliTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-tutorial.ts b/packages/taler-wallet-cli/src/integrationtests/test-libeufin-tutorial.ts
deleted file mode 100644
index 7bc067cfe..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-libeufin-tutorial.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- LibeufinNexusService,
- LibeufinSandboxService,
- LibeufinCli,
-} from "../harness/libeufin.js";
-
-/**
- * Run basic test with LibEuFin.
- */
-export async function runLibeufinTutorialTest(t: GlobalTestState) {
- // Set up test environment
-
- const libeufinSandbox = await LibeufinSandboxService.create(t, {
- httpPort: 5010,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-sandbox.sqlite3`,
- });
-
- await libeufinSandbox.start();
- await libeufinSandbox.pingUntilAvailable();
-
- const libeufinNexus = await LibeufinNexusService.create(t, {
- httpPort: 5011,
- databaseJdbcUri: `jdbc:sqlite:${t.testDir}/libeufin-nexus.sqlite3`,
- });
-
- const nexusUser = { username: "foo", password: "secret" };
- const libeufinCli = new LibeufinCli(t, {
- sandboxUrl: libeufinSandbox.baseUrl,
- nexusUrl: libeufinNexus.baseUrl,
- sandboxDatabaseUri: `jdbc:sqlite:${t.testDir}/libeufin-sandbox.sqlite3`,
- nexusDatabaseUri: `jdbc:sqlite:${t.testDir}/libeufin-nexus.sqlite3`,
- nexusUser: nexusUser,
- });
-
- const ebicsDetails = {
- hostId: "testhost",
- partnerId: "partner01",
- userId: "user01",
- };
- const bankAccountDetails = {
- currency: "EUR",
- iban: "DE18500105172929531888",
- bic: "INGDDEFFXXX",
- personName: "Jane Normal",
- accountName: "testacct01",
- };
-
- await libeufinCli.checkSandbox();
- await libeufinCli.createEbicsHost("testhost");
- await libeufinCli.createEbicsSubscriber(ebicsDetails);
- await libeufinCli.createEbicsBankAccount(ebicsDetails, bankAccountDetails);
- await libeufinCli.generateTransactions(bankAccountDetails.accountName);
-
- await libeufinNexus.start();
- await libeufinNexus.pingUntilAvailable();
-
- await libeufinNexus.createNexusSuperuser(nexusUser);
- const connectionDetails = {
- subscriberDetails: ebicsDetails,
- ebicsUrl: `${libeufinSandbox.baseUrl}ebicsweb`, // FIXME: need appropriate URL concatenation
- connectionName: "my-ebics-conn",
- };
- await libeufinCli.createEbicsConnection(connectionDetails);
- await libeufinCli.createBackupFile({
- passphrase: "secret",
- outputFile: `${t.testDir}/connection-backup.json`,
- connectionName: connectionDetails.connectionName,
- });
- await libeufinCli.createKeyLetter({
- outputFile: `${t.testDir}/letter.pdf`,
- connectionName: connectionDetails.connectionName,
- });
- await libeufinCli.connect(connectionDetails.connectionName);
- await libeufinCli.downloadBankAccounts(connectionDetails.connectionName);
- await libeufinCli.listOfferedBankAccounts(connectionDetails.connectionName);
-
- const bankAccountImportDetails = {
- offeredBankAccountName: bankAccountDetails.accountName,
- nexusBankAccountName: "at-nexus-testacct01",
- connectionName: connectionDetails.connectionName,
- };
-
- await libeufinCli.importBankAccount(bankAccountImportDetails);
- await libeufinSandbox.c53tick()
- await libeufinCli.fetchTransactions(bankAccountImportDetails.nexusBankAccountName);
- await libeufinCli.transactions(bankAccountImportDetails.nexusBankAccountName);
-
- const paymentDetails = {
- creditorIban: "DE42500105171245624648",
- creditorBic: "BELADEBEXXX",
- creditorName: "Mina Musterfrau",
- subject: "Purchase 01234",
- amount: "1.0",
- currency: "EUR",
- nexusBankAccountName: bankAccountImportDetails.nexusBankAccountName,
- };
- await libeufinCli.preparePayment(paymentDetails);
- await libeufinCli.submitPayment(paymentDetails, "1");
-
- await libeufinCli.newTalerWireGatewayFacade({
- accountName: bankAccountImportDetails.nexusBankAccountName,
- connectionName: "my-ebics-conn",
- currency: "EUR",
- facadeName: "my-twg",
- });
- await libeufinCli.listFacades();
-}
-runLibeufinTutorialTest.suites = ["libeufin"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-merchant-exchange-confusion.ts b/packages/taler-wallet-cli/src/integrationtests/test-merchant-exchange-confusion.ts
deleted file mode 100644
index 30ab1cd4b..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-merchant-exchange-confusion.ts
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- 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 {
- codecForMerchantOrderStatusUnpaid,
- ConfirmPayResultType,
- PreparePayResultType,
-} from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import axiosImp from "axios";
-const axios = axiosImp.default;
-import { URL } from "url";
-import { defaultCoinConfig } from "../harness/denomStructures.js";
-import {
- FaultInjectedExchangeService,
- FaultInjectedMerchantService,
-} from "../harness/faultInjection.js";
-import {
- BankService,
- ExchangeService,
- getPayto,
- GlobalTestState,
- MerchantPrivateApi,
- MerchantService,
- setupDb,
- WalletCli,
-} from "../harness/harness.js";
-import {
- FaultyMerchantTestEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-
-/**
- * Run a test case with a simple TESTKUDOS Taler environment, consisting
- * of one exchange, one bank and one merchant.
- */
-export async function createConfusedMerchantTestkudosEnvironment(
- t: GlobalTestState,
-): Promise<FaultyMerchantTestEnvironment> {
- 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,
- });
-
- const faultyMerchant = new FaultInjectedMerchantService(t, merchant, 9083);
- const faultyExchange = new FaultInjectedExchangeService(t, exchange, 9081);
-
- const exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
- exchange.addBankAccount("1", exchangeBankAccount);
-
- bank.setSuggestedExchange(
- faultyExchange,
- exchangeBankAccount.accountPaytoUri,
- );
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- exchange.addOfferedCoins(defaultCoinConfig);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- // Confuse the merchant by adding the non-proxied exchange.
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- });
-
- await merchant.addInstance({
- id: "minst1",
- name: "minst1",
- paytoUris: [getPayto("minst1")],
- });
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- return {
- commonDb: db,
- exchange,
- merchant,
- wallet,
- bank,
- exchangeBankAccount,
- faultyMerchant,
- faultyExchange,
- };
-}
-
-/**
- * Confuse the merchant by having one URL for the same exchange in the config,
- * but sending coins from the same exchange with a different URL.
- */
-export async function runMerchantExchangeConfusionTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, faultyExchange, faultyMerchant } =
- await createConfusedMerchantTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, {
- wallet,
- bank,
- exchange: faultyExchange,
- amount: "TESTKUDOS:20",
- });
-
- /**
- * =========================================================================
- * Create an order and let the wallet pay under a session ID
- *
- * We check along the way that the JSON response to /orders/{order_id}
- * returns the right thing.
- * =========================================================================
- */
-
- const merchant = faultyMerchant;
-
- let orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "https://example.com/article42",
- },
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- sessionId: "mysession-one",
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- t.assertTrue(orderStatus.already_paid_order_id === undefined);
- let publicOrderStatusUrl = orderStatus.order_status_url;
-
- let publicOrderStatusResp = await axios.get(publicOrderStatusUrl, {
- validateStatus: () => true,
- });
-
- if (publicOrderStatusResp.status != 402) {
- throw Error(
- `expected status 402 (before claiming), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- let pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
- );
-
- console.log(pubUnpaidStatus);
-
- let preparePayResp = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: pubUnpaidStatus.taler_pay_uri,
- },
- );
-
- t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible);
-
- const proposalId = preparePayResp.proposalId;
-
- const orderUrlWithHash = new URL(publicOrderStatusUrl);
- orderUrlWithHash.searchParams.set(
- "h_contract",
- preparePayResp.contractTermsHash,
- );
-
- console.log("requesting", orderUrlWithHash.href);
-
- publicOrderStatusResp = await axios.get(orderUrlWithHash.href, {
- validateStatus: () => true,
- });
-
- if (publicOrderStatusResp.status != 402) {
- throw Error(
- `expected status 402 (after claiming), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
- );
-
- const confirmPayRes = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId: proposalId,
- },
- );
-
- t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done);
-}
-
-runMerchantExchangeConfusionTest.suites = ["merchant"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-delete.ts b/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-delete.ts
deleted file mode 100644
index 09231cdd8..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-delete.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 { URL } from "@gnu-taler/taler-util";
-import axiosImp from "axios";
-const axios = axiosImp.default;
-import {
- ExchangeService,
- GlobalTestState,
- MerchantApiClient,
- MerchantService,
- setupDb,
- getPayto,
-} from "../harness/harness.js";
-
-/**
- * Test instance deletion and authentication for it
- */
-export async function runMerchantInstancesDeleteTest(t: GlobalTestState) {
- // Set up test environment
-
- const db = await setupDb(t);
-
- 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,
- });
-
- // We add the exchange to the config, but note that the exchange won't be started.
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- // Base URL for the default instance.
- const baseUrl = merchant.makeInstanceBaseUrl();
-
- {
- const r = await axios.get(new URL("config", baseUrl).href);
- console.log(r.data);
- t.assertDeepEqual(r.data.currency, "TESTKUDOS");
- }
-
- // Instances should initially be empty
- {
- const r = await axios.get(new URL("management/instances", baseUrl).href);
- t.assertDeepEqual(r.data.instances, []);
- }
-
- // Add an instance, no auth!
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- auth: {
- method: "external",
- },
- });
-
- // Add an instance, no auth!
- await merchant.addInstance({
- id: "myinst",
- name: "Second Instance",
- paytoUris: [getPayto("merchant-default")],
- auth: {
- method: "external",
- },
- });
-
- let merchantClient = new MerchantApiClient(merchant.makeInstanceBaseUrl(), {
- method: "external",
- });
-
- await merchantClient.changeAuth({
- method: "token",
- token: "secret-token:foobar",
- });
-
- merchantClient = new MerchantApiClient(merchant.makeInstanceBaseUrl(), {
- method: "token",
- token: "secret-token:foobar",
- });
-
- // Check that deleting an instance checks the auth
- // of the default instance.
- {
- const unauthMerchantClient = new MerchantApiClient(
- merchant.makeInstanceBaseUrl(),
- {
- method: "token",
- token: "secret-token:invalid",
- },
- );
-
- const exc = await t.assertThrowsAsync(async () => {
- await unauthMerchantClient.deleteInstance("myinst");
- });
- console.log("Got expected exception", exc);
- t.assertAxiosError(exc);
- t.assertDeepEqual(exc.response?.status, 401);
- }
-}
-
-runMerchantInstancesDeleteTest.suites = ["merchant"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-urls.ts b/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-urls.ts
deleted file mode 100644
index a4e44c7f3..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances-urls.ts
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 { Duration } from "@gnu-taler/taler-util";
-import axiosImp from "axios";
-const axios = axiosImp.default;
-import {
- ExchangeService,
- GlobalTestState,
- MerchantApiClient,
- MerchantService,
- setupDb,
- getPayto,
-} from "../harness/harness.js";
-
-/**
- * Do basic checks on instance management and authentication.
- */
-export async function runMerchantInstancesUrlsTest(t: GlobalTestState) {
- // Set up test environment
-
- const db = await setupDb(t);
-
- 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,
- });
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- const clientForDefault = new MerchantApiClient(
- merchant.makeInstanceBaseUrl(),
- {
- method: "token",
- token: "secret-token:i-am-default",
- },
- );
-
- await clientForDefault.createInstance({
- id: "default",
- address: {},
- default_max_deposit_fee: "TESTKUDOS:1",
- default_max_wire_fee: "TESTKUDOS:1",
- default_pay_delay: Duration.toTalerProtocolDuration(
- Duration.fromSpec({ seconds: 60 }),
- ),
- default_wire_fee_amortization: 1,
- default_wire_transfer_delay: Duration.toTalerProtocolDuration(
- Duration.fromSpec({ seconds: 60 }),
- ),
- jurisdiction: {},
- name: "My Default Instance",
- payto_uris: [getPayto("bar")],
- auth: {
- method: "token",
- token: "secret-token:i-am-default",
- },
- });
-
- await clientForDefault.createInstance({
- id: "myinst",
- address: {},
- default_max_deposit_fee: "TESTKUDOS:1",
- default_max_wire_fee: "TESTKUDOS:1",
- default_pay_delay: Duration.toTalerProtocolDuration(
- Duration.fromSpec({ seconds: 60 }),
- ),
- default_wire_fee_amortization: 1,
- default_wire_transfer_delay: Duration.toTalerProtocolDuration(
- Duration.fromSpec({ seconds: 60 }),
- ),
- jurisdiction: {},
- name: "My Second Instance",
- payto_uris: [getPayto("bar")],
- auth: {
- method: "token",
- token: "secret-token:i-am-myinst",
- },
- });
-
- async function check(url: string, token: string, expectedStatus: number) {
- const resp = await axios.get(url, {
- headers: {
- Authorization: `Bearer ${token}`,
- },
- validateStatus: () => true,
- });
- console.log(
- `checking ${url}, expected ${expectedStatus}, got ${resp.status}`,
- );
- t.assertDeepEqual(resp.status, expectedStatus);
- }
-
- const tokDefault = "secret-token:i-am-default";
-
- const defaultBaseUrl = merchant.makeInstanceBaseUrl();
-
- await check(
- `${defaultBaseUrl}private/instances/default/instances/default/config`,
- tokDefault,
- 404,
- );
-
- // Instance management is only available when accessing the default instance
- // directly.
- await check(
- `${defaultBaseUrl}instances/default/private/instances`,
- "foo",
- 404,
- );
-
- // Non-default instances don't allow instance management.
- await check(`${defaultBaseUrl}instances/foo/private/instances`, "foo", 404);
- await check(
- `${defaultBaseUrl}instances/myinst/private/instances`,
- "foo",
- 404,
- );
-
- await check(`${defaultBaseUrl}config`, "foo", 200);
- await check(`${defaultBaseUrl}instances/default/config`, "foo", 200);
- await check(`${defaultBaseUrl}instances/myinst/config`, "foo", 200);
- await check(`${defaultBaseUrl}instances/foo/config`, "foo", 404);
- await check(
- `${defaultBaseUrl}instances/default/instances/config`,
- "foo",
- 404,
- );
-
- await check(
- `${defaultBaseUrl}private/instances/myinst/config`,
- tokDefault,
- 404,
- );
-
- await check(
- `${defaultBaseUrl}instances/myinst/private/orders`,
- tokDefault,
- 401,
- );
-
- await check(
- `${defaultBaseUrl}instances/myinst/private/orders`,
- tokDefault,
- 401,
- );
-
- await check(
- `${defaultBaseUrl}instances/myinst/private/orders`,
- "secret-token:i-am-myinst",
- 200,
- );
-
- await check(
- `${defaultBaseUrl}private/instances/myinst/orders`,
- tokDefault,
- 404,
- );
-}
-
-runMerchantInstancesUrlsTest.suites = ["merchant"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances.ts b/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances.ts
deleted file mode 100644
index 3efe83241..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-merchant-instances.ts
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 { URL } from "@gnu-taler/taler-util";
-import axiosImp from "axios";
-const axios = axiosImp.default;
-import {
- ExchangeService,
- GlobalTestState,
- MerchantApiClient,
- MerchantService,
- setupDb,
- getPayto
-} from "../harness/harness.js";
-
-/**
- * Do basic checks on instance management and authentication.
- */
-export async function runMerchantInstancesTest(t: GlobalTestState) {
- // Set up test environment
-
- const db = await setupDb(t);
-
- 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,
- });
-
- // We add the exchange to the config, but note that the exchange won't be started.
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- // Base URL for the default instance.
- const baseUrl = merchant.makeInstanceBaseUrl();
-
- {
- const r = await axios.get(new URL("config", baseUrl).href);
- console.log(r.data);
- t.assertDeepEqual(r.data.currency, "TESTKUDOS");
- }
-
- // Instances should initially be empty
- {
- const r = await axios.get(new URL("management/instances", baseUrl).href);
- t.assertDeepEqual(r.data.instances, []);
- }
-
- // Add an instance, no auth!
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- auth: {
- method: "external",
- },
- });
-
- // Add an instance, no auth!
- await merchant.addInstance({
- id: "myinst",
- name: "Second Instance",
- paytoUris: [getPayto("merchant-default")],
- auth: {
- method: "external",
- },
- });
-
- let merchantClient = new MerchantApiClient(merchant.makeInstanceBaseUrl(), {
- method: "external",
- });
-
- {
- const r = await merchantClient.getInstances();
- t.assertDeepEqual(r.instances.length, 2);
- }
-
- // Check that a "malformed" bearer Authorization header gets ignored
- {
- const url = merchant.makeInstanceBaseUrl();
- const resp = await axios.get(new URL("management/instances", url).href, {
- headers: {
- Authorization: "foo bar-baz",
- },
- });
- t.assertDeepEqual(resp.status, 200);
- }
-
- {
- const fullDetails = await merchantClient.getInstanceFullDetails("default");
- t.assertDeepEqual(fullDetails.auth.method, "external");
- }
-
- await merchantClient.changeAuth({
- method: "token",
- token: "secret-token:foobar",
- });
-
- // Now this should fail, as we didn't change the auth of the client yet.
- const exc = await t.assertThrowsAsync(async () => {
- console.log("requesting instances with auth", merchantClient.auth);
- const resp = await merchantClient.getInstances();
- console.log("instances result:", resp);
- });
-
- console.log(exc);
-
- t.assertAxiosError(exc);
- t.assertTrue(exc.response?.status === 401);
-
- merchantClient = new MerchantApiClient(merchant.makeInstanceBaseUrl(), {
- method: "token",
- token: "secret-token:foobar",
- });
-
- // With the new client auth settings, request should work again.
- await merchantClient.getInstances();
-
- // Now, try some variations.
- {
- const url = merchant.makeInstanceBaseUrl();
- const resp = await axios.get(new URL("management/instances", url).href, {
- headers: {
- // Note the spaces
- Authorization: "Bearer secret-token:foobar",
- },
- });
- t.assertDeepEqual(resp.status, 200);
- }
-
- // Check that auth is reported properly
- {
- const fullDetails = await merchantClient.getInstanceFullDetails("default");
- t.assertDeepEqual(fullDetails.auth.method, "token");
- // Token should *not* be reported back.
- t.assertDeepEqual(fullDetails.auth.token, undefined);
- }
-
- // Check that deleting an instance checks the auth
- // of the default instance.
- {
- const unauthMerchantClient = new MerchantApiClient(
- merchant.makeInstanceBaseUrl(),
- {
- method: "external",
- },
- );
-
- const exc = await t.assertThrowsAsync(async () => {
- await unauthMerchantClient.deleteInstance("myinst");
- });
- console.log(exc);
- t.assertAxiosError(exc);
- t.assertDeepEqual(exc.response?.status, 401);
- }
-}
-
-runMerchantInstancesTest.suites = ["merchant"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-merchant-longpolling.ts b/packages/taler-wallet-cli/src/integrationtests/test-merchant-longpolling.ts
deleted file mode 100644
index 4b9f53f05..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-merchant-longpolling.ts
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- 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 { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment, withdrawViaBank } from "../harness/helpers.js";
-import {
- PreparePayResultType,
- codecForMerchantOrderStatusUnpaid,
- ConfirmPayResultType,
- URL,
-} from "@gnu-taler/taler-util";
-import axiosImp from "axios";
-const axios = axiosImp.default;
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runMerchantLongpollingTest(t: GlobalTestState) {
- // Set up test environment
-
- const {
- wallet,
- bank,
- exchange,
- merchant,
- } = await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- /**
- * =========================================================================
- * Create an order and let the wallet pay under a session ID
- *
- * We check along the way that the JSON response to /orders/{order_id}
- * returns the right thing.
- * =========================================================================
- */
-
- let orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "https://example.com/article42",
- },
- create_token: false,
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- sessionId: "mysession-one",
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- t.assertTrue(orderStatus.already_paid_order_id === undefined);
- let publicOrderStatusUrl = new URL(orderStatus.order_status_url);
-
- // First, request order status without longpolling
- {
- console.log("requesting", publicOrderStatusUrl.href);
- let publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
-
- if (publicOrderStatusResp.status != 402) {
- throw Error(
- `expected status 402 (before claiming, no long polling), but got ${publicOrderStatusResp.status}`,
- );
- }
- }
-
- // Now do long-polling for half a second!
- publicOrderStatusUrl.searchParams.set("timeout_ms", "500");
-
- console.log("requesting", publicOrderStatusUrl.href);
- let publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
-
- if (publicOrderStatusResp.status != 402) {
- throw Error(
- `expected status 402 (before claiming, with long-polling), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- let pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
- );
-
- console.log(pubUnpaidStatus);
-
- /**
- * =========================================================================
- * Now actually pay, but WHILE a long poll is active!
- * =========================================================================
- */
-
- let preparePayResp = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: pubUnpaidStatus.taler_pay_uri,
- },
- );
-
- t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible);
-
- publicOrderStatusUrl.searchParams.set("timeout_ms", "5000");
- publicOrderStatusUrl.searchParams.set(
- "h_contract",
- preparePayResp.contractTermsHash,
- );
-
- let publicOrderStatusPromise = axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
-
- t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible);
-
- const proposalId = preparePayResp.proposalId;
-
- publicOrderStatusResp = await publicOrderStatusPromise;
-
- if (publicOrderStatusResp.status != 402) {
- throw Error(
- `expected status 402 (after claiming), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
- );
-
- const confirmPayRes = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId: proposalId,
- },
- );
-
- t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done);
-}
-
-runMerchantLongpollingTest.suites = ["merchant"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-merchant-refund-api.ts b/packages/taler-wallet-cli/src/integrationtests/test-merchant-refund-api.ts
deleted file mode 100644
index 5d9b23fa7..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-merchant-refund-api.ts
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- 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 {
- GlobalTestState,
- MerchantPrivateApi,
- MerchantServiceInterface,
- WalletCli,
- ExchangeServiceInterface,
-} from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-import {
- URL,
- durationFromSpec,
- PreparePayResultType,
- Duration,
-} from "@gnu-taler/taler-util";
-import axiosImp from "axios";
-const axios = axiosImp.default;
-import {
- WalletApiOperation,
- BankServiceHandle,
-} from "@gnu-taler/taler-wallet-core";
-
-async function testRefundApiWithFulfillmentUrl(
- t: GlobalTestState,
- env: {
- merchant: MerchantServiceInterface;
- bank: BankServiceHandle;
- wallet: WalletCli;
- exchange: ExchangeServiceInterface;
- },
-): Promise<void> {
- const { wallet, bank, exchange, merchant } = env;
-
- // Set up order.
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "https://example.com/fulfillment",
- },
- refund_delay: Duration.toTalerProtocolDuration(
- durationFromSpec({ minutes: 5 }),
- ),
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- const talerPayUri = orderStatus.taler_pay_uri;
- const orderId = orderResp.order_id;
-
- // Make wallet pay for the order
-
- let preparePayResult = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri,
- },
- );
-
- t.assertTrue(
- preparePayResult.status === PreparePayResultType.PaymentPossible,
- );
-
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
- proposalId: preparePayResult.proposalId,
- });
-
- // Check if payment was successful.
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- preparePayResult = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri,
- },
- );
-
- t.assertTrue(
- preparePayResult.status === PreparePayResultType.AlreadyConfirmed,
- );
-
- await MerchantPrivateApi.giveRefund(merchant, {
- amount: "TESTKUDOS:5",
- instance: "default",
- justification: "foo",
- orderId: orderResp.order_id,
- });
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- t.assertAmountEquals(orderStatus.refund_amount, "TESTKUDOS:5");
-
- // Now test what the merchant gives as a response for various requests to the
- // public order status URL!
-
- let publicOrderStatusUrl = new URL(
- `orders/${orderId}`,
- merchant.makeInstanceBaseUrl(),
- );
- publicOrderStatusUrl.searchParams.set(
- "h_contract",
- preparePayResult.contractTermsHash,
- );
-
- let publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
- console.log(publicOrderStatusResp.data);
- t.assertTrue(publicOrderStatusResp.status === 200);
- t.assertAmountEquals(publicOrderStatusResp.data.refund_amount, "TESTKUDOS:5");
-
- publicOrderStatusUrl = new URL(
- `orders/${orderId}`,
- merchant.makeInstanceBaseUrl(),
- );
- console.log(`requesting order status via '${publicOrderStatusUrl.href}'`);
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
- console.log(publicOrderStatusResp.status);
- console.log(publicOrderStatusResp.data);
- // We didn't give any authentication, so we should get a fulfillment URL back
- t.assertTrue(publicOrderStatusResp.status === 403);
-}
-
-async function testRefundApiWithFulfillmentMessage(
- t: GlobalTestState,
- env: {
- merchant: MerchantServiceInterface;
- bank: BankServiceHandle;
- wallet: WalletCli;
- exchange: ExchangeServiceInterface;
- },
-): Promise<void> {
- const { wallet, bank, exchange, merchant } = env;
-
- // Set up order.
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_message: "Thank you for buying foobar",
- },
- refund_delay: Duration.toTalerProtocolDuration(
- durationFromSpec({ minutes: 5 }),
- ),
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- const talerPayUri = orderStatus.taler_pay_uri;
- const orderId = orderResp.order_id;
-
- // Make wallet pay for the order
-
- let preparePayResult = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri,
- },
- );
-
- t.assertTrue(
- preparePayResult.status === PreparePayResultType.PaymentPossible,
- );
-
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
- proposalId: preparePayResult.proposalId,
- });
-
- // Check if payment was successful.
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- preparePayResult = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri,
- },
- );
-
- t.assertTrue(
- preparePayResult.status === PreparePayResultType.AlreadyConfirmed,
- );
-
- await MerchantPrivateApi.giveRefund(merchant, {
- amount: "TESTKUDOS:5",
- instance: "default",
- justification: "foo",
- orderId: orderResp.order_id,
- });
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- t.assertAmountEquals(orderStatus.refund_amount, "TESTKUDOS:5");
-
- // Now test what the merchant gives as a response for various requests to the
- // public order status URL!
-
- let publicOrderStatusUrl = new URL(
- `orders/${orderId}`,
- merchant.makeInstanceBaseUrl(),
- );
- publicOrderStatusUrl.searchParams.set(
- "h_contract",
- preparePayResult.contractTermsHash,
- );
-
- let publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
- console.log(publicOrderStatusResp.data);
- t.assertTrue(publicOrderStatusResp.status === 200);
- t.assertAmountEquals(publicOrderStatusResp.data.refund_amount, "TESTKUDOS:5");
-
- publicOrderStatusUrl = new URL(
- `orders/${orderId}`,
- merchant.makeInstanceBaseUrl(),
- );
-
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
- console.log(publicOrderStatusResp.data);
- // We didn't give any authentication, so we should get a fulfillment URL back
- t.assertTrue(publicOrderStatusResp.status === 403);
-}
-
-/**
- * Test case for the refund API of the merchant backend.
- */
-export async function runMerchantRefundApiTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- await testRefundApiWithFulfillmentUrl(t, {
- wallet,
- bank,
- exchange,
- merchant,
- });
-
- await testRefundApiWithFulfillmentMessage(t, {
- wallet,
- bank,
- exchange,
- merchant,
- });
-}
-
-runMerchantRefundApiTest.suites = ["merchant"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts b/packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts
deleted file mode 100644
index 70edaaf0c..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-merchant-spec-public-orders.ts
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 {
- ConfirmPayResultType,
- PreparePayResultType,
- URL,
- encodeCrock,
- getRandomBytes,
-} from "@gnu-taler/taler-util";
-import { NodeHttpLib, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import {
- BankService,
- ExchangeService,
- GlobalTestState,
- MerchantPrivateApi,
- MerchantService,
- WalletCli,
-} from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-
-const httpLib = new NodeHttpLib();
-
-interface Context {
- merchant: MerchantService;
- merchantBaseUrl: string;
- bank: BankService;
- exchange: ExchangeService;
-}
-
-async function testWithClaimToken(
- t: GlobalTestState,
- c: Context,
-): Promise<void> {
- const wallet = new WalletCli(t, "withclaimtoken");
- const { bank, exchange } = c;
- const { merchant, merchantBaseUrl } = c;
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
- const sessionId = "mysession";
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "https://example.com/article42",
- public_reorder_url: "https://example.com/article42-share",
- },
- });
-
- const claimToken = orderResp.token;
- const orderId = orderResp.order_id;
- t.assertTrue(!!claimToken);
- let talerPayUri: string;
-
- {
- const httpResp = await httpLib.get(
- new URL(`orders/${orderId}`, merchantBaseUrl).href,
- );
- const r = await httpResp.json();
- t.assertDeepEqual(httpResp.status, 202);
- console.log(r);
- }
-
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- url.searchParams.set("token", claimToken);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- t.assertDeepEqual(httpResp.status, 402);
- console.log(r);
- talerPayUri = r.taler_pay_uri;
- t.assertTrue(!!talerPayUri);
- }
-
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- url.searchParams.set("token", claimToken);
- const httpResp = await httpLib.get(url.href, {
- headers: {
- Accept: "text/html",
- },
- });
- const r = await httpResp.text();
- t.assertDeepEqual(httpResp.status, 402);
- console.log(r);
- }
-
- const preparePayResp = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri,
- },
- );
-
- t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible);
- const contractTermsHash = preparePayResp.contractTermsHash;
- const proposalId = preparePayResp.proposalId;
-
- // claimed, unpaid, access with wrong h_contract
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const hcWrong = encodeCrock(getRandomBytes(64));
- url.searchParams.set("h_contract", hcWrong);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 403);
- }
-
- // claimed, unpaid, access with wrong claim token
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const ctWrong = encodeCrock(getRandomBytes(16));
- url.searchParams.set("token", ctWrong);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 403);
- }
-
- // claimed, unpaid, access with correct claim token
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- url.searchParams.set("token", claimToken);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 402);
- }
-
- // claimed, unpaid, access with correct contract terms hash
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- url.searchParams.set("h_contract", contractTermsHash);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 402);
- }
-
- // claimed, unpaid, access without credentials
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 202);
- }
-
- const confirmPayRes = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId: proposalId,
- },
- );
-
- t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done);
-
- // paid, access without credentials
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 202);
- }
-
- // paid, access with wrong h_contract
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const hcWrong = encodeCrock(getRandomBytes(64));
- url.searchParams.set("h_contract", hcWrong);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 403);
- }
-
- // paid, access with wrong claim token
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const ctWrong = encodeCrock(getRandomBytes(16));
- url.searchParams.set("token", ctWrong);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 403);
- }
-
- // paid, access with correct h_contract
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- url.searchParams.set("h_contract", contractTermsHash);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 200);
- }
-
- // paid, access with correct claim token, JSON
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- url.searchParams.set("token", claimToken);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 200);
- const respFulfillmentUrl = r.fulfillment_url;
- t.assertDeepEqual(respFulfillmentUrl, "https://example.com/article42");
- }
-
- // paid, access with correct claim token, HTML
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- url.searchParams.set("token", claimToken);
- const httpResp = await httpLib.get(url.href, {
- headers: { Accept: "text/html" },
- });
- t.assertDeepEqual(httpResp.status, 200);
- }
-
- const confirmPayRes2 = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId: proposalId,
- sessionId: sessionId,
- },
- );
-
- t.assertTrue(confirmPayRes2.type === ConfirmPayResultType.Done);
-
- // Create another order with identical fulfillment URL to test the "already paid" flow
- const alreadyPaidOrderResp = await MerchantPrivateApi.createOrder(
- merchant,
- "default",
- {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "https://example.com/article42",
- public_reorder_url: "https://example.com/article42-share",
- },
- },
- );
-
- const apOrderId = alreadyPaidOrderResp.order_id;
- const apToken = alreadyPaidOrderResp.token;
- t.assertTrue(!!apToken);
-
- {
- const url = new URL(`orders/${apOrderId}`, merchantBaseUrl);
- url.searchParams.set("token", apToken);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 402);
- }
-
- // Check for already paid session ID, JSON
- {
- const url = new URL(`orders/${apOrderId}`, merchantBaseUrl);
- url.searchParams.set("token", apToken);
- url.searchParams.set("session_id", sessionId);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 402);
- const alreadyPaidOrderId = r.already_paid_order_id;
- t.assertDeepEqual(alreadyPaidOrderId, orderId);
- }
-
- // Check for already paid session ID, HTML
- {
- const url = new URL(`orders/${apOrderId}`, merchantBaseUrl);
- url.searchParams.set("token", apToken);
- url.searchParams.set("session_id", sessionId);
- const httpResp = await httpLib.get(url.href, {
- headers: { Accept: "text/html" },
- });
- t.assertDeepEqual(httpResp.status, 302);
- const location = httpResp.headers.get("Location");
- console.log("location header:", location);
- t.assertDeepEqual(location, "https://example.com/article42");
- }
-}
-
-async function testWithoutClaimToken(
- t: GlobalTestState,
- c: Context,
-): Promise<void> {
- const wallet = new WalletCli(t, "withoutct");
- const sessionId = "mysession2";
- const { bank, exchange } = c;
- const { merchant, merchantBaseUrl } = c;
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "https://example.com/article42",
- public_reorder_url: "https://example.com/article42-share",
- },
- create_token: false,
- });
-
- const orderId = orderResp.order_id;
- let talerPayUri: string;
-
- {
- const httpResp = await httpLib.get(
- new URL(`orders/${orderId}`, merchantBaseUrl).href,
- );
- const r = await httpResp.json();
- t.assertDeepEqual(httpResp.status, 402);
- console.log(r);
- }
-
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- t.assertDeepEqual(httpResp.status, 402);
- console.log(r);
- talerPayUri = r.taler_pay_uri;
- t.assertTrue(!!talerPayUri);
- }
-
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const httpResp = await httpLib.get(url.href, {
- headers: {
- Accept: "text/html",
- },
- });
- const r = await httpResp.text();
- t.assertDeepEqual(httpResp.status, 402);
- console.log(r);
- }
-
- const preparePayResp = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri,
- },
- );
-
- console.log(preparePayResp);
-
- t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible);
- const contractTermsHash = preparePayResp.contractTermsHash;
- const proposalId = preparePayResp.proposalId;
-
- // claimed, unpaid, access with wrong h_contract
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const hcWrong = encodeCrock(getRandomBytes(64));
- url.searchParams.set("h_contract", hcWrong);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 403);
- }
-
- // claimed, unpaid, access with wrong claim token
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const ctWrong = encodeCrock(getRandomBytes(16));
- url.searchParams.set("token", ctWrong);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 403);
- }
-
- // claimed, unpaid, no claim token
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 402);
- }
-
- // claimed, unpaid, access with correct contract terms hash
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- url.searchParams.set("h_contract", contractTermsHash);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 402);
- }
-
- // claimed, unpaid, access without credentials
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- // No credentials, but the order doesn't require a claim token.
- // This effectively means that the order ID is already considered
- // enough authentication, at least to check for the basic order status
- t.assertDeepEqual(httpResp.status, 402);
- }
-
- const confirmPayRes = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId: proposalId,
- },
- );
-
- t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done);
-
- // paid, access without credentials
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 200);
- }
-
- // paid, access with wrong h_contract
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const hcWrong = encodeCrock(getRandomBytes(64));
- url.searchParams.set("h_contract", hcWrong);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 403);
- }
-
- // paid, access with wrong claim token
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const ctWrong = encodeCrock(getRandomBytes(16));
- url.searchParams.set("token", ctWrong);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 403);
- }
-
- // paid, access with correct h_contract
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- url.searchParams.set("h_contract", contractTermsHash);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 200);
- }
-
- // paid, JSON
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 200);
- const respFulfillmentUrl = r.fulfillment_url;
- t.assertDeepEqual(respFulfillmentUrl, "https://example.com/article42");
- }
-
- // paid, HTML
- {
- const url = new URL(`orders/${orderId}`, merchantBaseUrl);
- const httpResp = await httpLib.get(url.href, {
- headers: { Accept: "text/html" },
- });
- t.assertDeepEqual(httpResp.status, 200);
- }
-
- const confirmPayRes2 = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId: proposalId,
- sessionId: sessionId,
- },
- );
-
- t.assertTrue(confirmPayRes2.type === ConfirmPayResultType.Done);
-
- // Create another order with identical fulfillment URL to test the "already paid" flow
- const alreadyPaidOrderResp = await MerchantPrivateApi.createOrder(
- merchant,
- "default",
- {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "https://example.com/article42",
- public_reorder_url: "https://example.com/article42-share",
- },
- },
- );
-
- const apOrderId = alreadyPaidOrderResp.order_id;
- const apToken = alreadyPaidOrderResp.token;
- t.assertTrue(!!apToken);
-
- {
- const url = new URL(`orders/${apOrderId}`, merchantBaseUrl);
- url.searchParams.set("token", apToken);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 402);
- }
-
- // Check for already paid session ID, JSON
- {
- const url = new URL(`orders/${apOrderId}`, merchantBaseUrl);
- url.searchParams.set("token", apToken);
- url.searchParams.set("session_id", sessionId);
- const httpResp = await httpLib.get(url.href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 402);
- const alreadyPaidOrderId = r.already_paid_order_id;
- t.assertDeepEqual(alreadyPaidOrderId, orderId);
- }
-
- // Check for already paid session ID, HTML
- {
- const url = new URL(`orders/${apOrderId}`, merchantBaseUrl);
- url.searchParams.set("token", apToken);
- url.searchParams.set("session_id", sessionId);
- const httpResp = await httpLib.get(url.href, {
- headers: { Accept: "text/html" },
- });
- t.assertDeepEqual(httpResp.status, 302);
- const location = httpResp.headers.get("Location");
- console.log("location header:", location);
- t.assertDeepEqual(location, "https://example.com/article42");
- }
-}
-
-/**
- * Checks for the /orders/{id} endpoint of the merchant.
- *
- * The tests here should exercise all code paths in the executable
- * specification of the endpoint.
- */
-export async function runMerchantSpecPublicOrdersTest(t: GlobalTestState) {
- const { bank, exchange, merchant } = await createSimpleTestkudosEnvironment(
- t,
- );
-
- // Base URL for the default instance.
- const merchantBaseUrl = merchant.makeInstanceBaseUrl();
-
- {
- const httpResp = await httpLib.get(new URL("config", merchantBaseUrl).href);
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(r.currency, "TESTKUDOS");
- }
-
- {
- const httpResp = await httpLib.get(
- new URL("orders/foo", merchantBaseUrl).href,
- );
- const r = await httpResp.json();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 404);
- // FIXME: also check Taler error code
- }
-
- {
- const httpResp = await httpLib.get(
- new URL("orders/foo", merchantBaseUrl).href,
- {
- headers: {
- Accept: "text/html",
- },
- },
- );
- const r = await httpResp.text();
- console.log(r);
- t.assertDeepEqual(httpResp.status, 404);
- // FIXME: also check Taler error code
- }
-
- await testWithClaimToken(t, {
- merchant,
- merchantBaseUrl,
- exchange,
- bank,
- });
-
- await testWithoutClaimToken(t, {
- merchant,
- merchantBaseUrl,
- exchange,
- bank,
- });
-}
-
-runMerchantSpecPublicOrdersTest.suites = ["merchant"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-pay-paid.ts b/packages/taler-wallet-cli/src/integrationtests/test-pay-paid.ts
deleted file mode 100644
index 2ef91e4a8..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-pay-paid.ts
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- 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 { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import {
- withdrawViaBank,
- createFaultInjectedMerchantTestkudosEnvironment,
-} from "../harness/helpers.js";
-import {
- PreparePayResultType,
- codecForMerchantOrderStatusUnpaid,
- ConfirmPayResultType,
- URL,
-} from "@gnu-taler/taler-util";
-import axiosImp from "axios";
-const axios = axiosImp.default;
-import { FaultInjectionRequestContext } from "../harness/faultInjection.js";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-
-/**
- * Run test for the wallets repurchase detection mechanism
- * based on the fulfillment URL.
- *
- * FIXME: This test is now almost the same as test-paywall-flow,
- * since we can't initiate payment via a "claimed" private order status
- * response.
- */
-export async function runPayPaidTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, faultyExchange, faultyMerchant } =
- await createFaultInjectedMerchantTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, {
- wallet,
- bank,
- exchange: faultyExchange,
- amount: "TESTKUDOS:20",
- });
-
- /**
- * =========================================================================
- * Create an order and let the wallet pay under a session ID
- *
- * We check along the way that the JSON response to /orders/{order_id}
- * returns the right thing.
- * =========================================================================
- */
-
- const merchant = faultyMerchant;
-
- let orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "https://example.com/article42",
- public_reorder_url: "https://example.com/article42-share",
- },
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- sessionId: "mysession-one",
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- t.assertTrue(orderStatus.already_paid_order_id === undefined);
- let publicOrderStatusUrl = orderStatus.order_status_url;
-
- let publicOrderStatusResp = await axios.get(publicOrderStatusUrl, {
- validateStatus: () => true,
- });
-
- if (publicOrderStatusResp.status != 402) {
- throw Error(
- `expected status 402 (before claiming), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- let pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
- );
-
- console.log(pubUnpaidStatus);
-
- let preparePayResp = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: pubUnpaidStatus.taler_pay_uri,
- },
- );
-
- t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible);
-
- const proposalId = preparePayResp.proposalId;
-
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl, {
- validateStatus: () => true,
- });
-
- if (publicOrderStatusResp.status != 402) {
- throw Error(
- `expected status 402 (after claiming), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
- );
-
- const confirmPayRes = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId: proposalId,
- },
- );
-
- t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done);
-
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl, {
- validateStatus: () => true,
- });
-
- console.log(publicOrderStatusResp.data);
-
- if (publicOrderStatusResp.status != 200) {
- console.log(publicOrderStatusResp.data);
- throw Error(
- `expected status 200 (after paying), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- /**
- * =========================================================================
- * Now change up the session ID and do payment re-play!
- * =========================================================================
- */
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- sessionId: "mysession-two",
- });
-
- console.log(
- "order status under mysession-two:",
- JSON.stringify(orderStatus, undefined, 2),
- );
-
- // Should be claimed (not paid!) because of a new session ID
- t.assertTrue(orderStatus.order_status === "claimed");
-
- let numPayRequested = 0;
- let numPaidRequested = 0;
-
- faultyMerchant.faultProxy.addFault({
- async modifyRequest(ctx: FaultInjectionRequestContext) {
- const url = new URL(ctx.requestUrl);
- if (url.pathname.endsWith("/pay")) {
- numPayRequested++;
- } else if (url.pathname.endsWith("/paid")) {
- numPaidRequested++;
- }
- },
- });
-
- let orderRespTwo = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "https://example.com/article42",
- public_reorder_url: "https://example.com/article42-share",
- },
- });
-
- let orderStatusTwo = await MerchantPrivateApi.queryPrivateOrderStatus(
- merchant,
- {
- orderId: orderRespTwo.order_id,
- sessionId: "mysession-two",
- },
- );
-
- t.assertTrue(orderStatusTwo.order_status === "unpaid");
-
- // Pay with new taler://pay URI, which should
- // have the new session ID!
- // Wallet should now automatically re-play payment.
- preparePayResp = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: orderStatusTwo.taler_pay_uri,
- },
- );
-
- t.assertTrue(preparePayResp.status === PreparePayResultType.AlreadyConfirmed);
- t.assertTrue(preparePayResp.paid);
-
- // Make sure the wallet is actually doing the replay properly.
- t.assertTrue(numPaidRequested == 1);
- t.assertTrue(numPayRequested == 0);
-}
-
-runPayPaidTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-payment-claim.ts b/packages/taler-wallet-cli/src/integrationtests/test-payment-claim.ts
deleted file mode 100644
index e93d2c44c..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-payment-claim.ts
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- 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 {
- GlobalTestState,
- MerchantPrivateApi,
- WalletCli,
-} from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-import { PreparePayResultType } from "@gnu-taler/taler-util";
-import { TalerErrorCode } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runPaymentClaimTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
-
- const walletTwo = new WalletCli(t, "two");
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- // Set up order.
-
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- },
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- const talerPayUri = orderStatus.taler_pay_uri;
-
- // Make wallet pay for the order
-
- const preparePayResult = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri,
- },
- );
-
- t.assertTrue(
- preparePayResult.status === PreparePayResultType.PaymentPossible,
- );
-
- t.assertThrowsTalerErrorAsync(async () => {
- await walletTwo.client.call(WalletApiOperation.PreparePayForUri, {
- talerPayUri,
- });
- });
-
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
- proposalId: preparePayResult.proposalId,
- });
-
- // Check if payment was successful.
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- walletTwo.deleteDatabase();
-
- const err = await t.assertThrowsTalerErrorAsync(async () => {
- await walletTwo.client.call(WalletApiOperation.PreparePayForUri, {
- talerPayUri,
- });
- });
-
- t.assertTrue(err.hasErrorCode(TalerErrorCode.WALLET_ORDER_ALREADY_CLAIMED));
-
- await t.shutdown();
-}
-
-runPaymentClaimTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-payment-fault.ts b/packages/taler-wallet-cli/src/integrationtests/test-payment-fault.ts
deleted file mode 100644
index dea538e35..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-payment-fault.ts
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- 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/>
- */
-
-/**
- * Sample fault injection test.
- */
-
-/**
- * Imports.
- */
-import {
- GlobalTestState,
- MerchantService,
- ExchangeService,
- setupDb,
- BankService,
- WalletCli,
- MerchantPrivateApi,
- getPayto,
-} from "../harness/harness.js";
-import {
- FaultInjectedExchangeService,
- FaultInjectionRequestContext,
- FaultInjectionResponseContext,
-} from "../harness/faultInjection.js";
-import { CoreApiResponse } from "@gnu-taler/taler-util";
-import { defaultCoinConfig } from "../harness/denomStructures.js";
-import {
- WalletApiOperation,
- BankApi,
- BankAccessApi,
-} from "@gnu-taler/taler-wallet-core";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runPaymentFaultTest(t: GlobalTestState) {
- // Set up test environment
-
- 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 exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
-
- bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- await exchange.addBankAccount("1", exchangeBankAccount);
- exchange.addOfferedCoins(defaultCoinConfig);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- const faultyExchange = new FaultInjectedExchangeService(t, exchange, 8091);
-
- // Print all requests to the exchange
- faultyExchange.faultProxy.addFault({
- async modifyRequest(ctx: FaultInjectionRequestContext) {
- console.log("got request", ctx);
- },
- async modifyResponse(ctx: FaultInjectionResponseContext) {
- console.log("got response", ctx);
- },
- });
-
- const merchant = await MerchantService.create(t, {
- name: "testmerchant-1",
- currency: "TESTKUDOS",
- httpPort: 8083,
- database: db.connStr,
- });
-
- merchant.addExchange(faultyExchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- });
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- // Create withdrawal operation
-
- const user = await BankApi.createRandomBankUser(bank);
- const wop = await BankAccessApi.createWithdrawalOperation(
- bank,
- user,
- "TESTKUDOS:20",
- );
-
- // Hand it to the wallet
-
- await wallet.client.call(WalletApiOperation.GetWithdrawalDetailsForUri, {
- talerWithdrawUri: wop.taler_withdraw_uri,
- });
-
- await wallet.runPending();
-
- // Withdraw
-
- await wallet.client.call(WalletApiOperation.AcceptBankIntegratedWithdrawal, {
- exchangeBaseUrl: faultyExchange.baseUrl,
- talerWithdrawUri: wop.taler_withdraw_uri,
- });
- await wallet.runPending();
-
- // Confirm it
-
- await BankApi.confirmWithdrawalOperation(bank, user, wop);
-
- await wallet.runUntilDone();
-
- // Check balance
-
- await wallet.client.call(WalletApiOperation.GetBalances, {});
-
- // Set up order.
-
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- },
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- // Make wallet pay for the order
-
- let apiResp: CoreApiResponse;
-
- const prepResp = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: orderStatus.taler_pay_uri,
- },
- );
-
- const proposalId = prepResp.proposalId;
-
- await wallet.runPending();
-
- // Drop 3 responses from the exchange.
- let faultCount = 0;
- faultyExchange.faultProxy.addFault({
- async modifyResponse(ctx: FaultInjectionResponseContext) {
- if (!ctx.request.requestUrl.endsWith("/deposit")) {
- return;
- }
- if (faultCount < 3) {
- console.log(`blocking /deposit request #${faultCount}`);
- faultCount++;
- ctx.dropResponse = true;
- } else {
- console.log(`letting through /deposit request #${faultCount}`);
- }
- },
- });
-
- // confirmPay won't work, as the exchange is unreachable
-
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
- // FIXME: should be validated, don't cast!
- proposalId: proposalId,
- });
-
- await wallet.runUntilDone();
-
- // Check if payment was successful.
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-}
-
-runPaymentFaultTest.suites = ["wallet"];
-runPaymentFaultTest.timeoutMs = 120000;
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-payment-forgettable.ts b/packages/taler-wallet-cli/src/integrationtests/test-payment-forgettable.ts
deleted file mode 100644
index 3bdd6bef3..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-payment-forgettable.ts
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- makeTestPayment,
-} from "../harness/helpers.js";
-
-/**
- * Run test for payment with a contract that has forgettable fields.
- */
-export async function runPaymentForgettableTest(t: GlobalTestState) {
- // Set up test environment
-
- const {
- wallet,
- bank,
- exchange,
- merchant,
- } = await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- {
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- extra: {
- foo: { bar: "baz" },
- $forgettable: {
- foo: "gnu",
- },
- },
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
- }
-
- console.log("testing with forgettable field without hash");
-
- {
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- extra: {
- foo: { bar: "baz" },
- $forgettable: {
- foo: true,
- },
- },
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
- }
-
- await wallet.runUntilDone();
-}
-
-runPaymentForgettableTest.suites = ["wallet", "merchant"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-payment-idempotency.ts b/packages/taler-wallet-cli/src/integrationtests/test-payment-idempotency.ts
deleted file mode 100644
index 1099a8188..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-payment-idempotency.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- 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 { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-import { PreparePayResultType } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-
-/**
- * Test the wallet-core payment API, especially that repeated operations
- * return the expected result.
- */
-export async function runPaymentIdempotencyTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- // Set up order.
-
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- },
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- const talerPayUri = orderStatus.taler_pay_uri;
-
- // Make wallet pay for the order
-
- const preparePayResult = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: orderStatus.taler_pay_uri,
- },
- );
-
- const preparePayResultRep = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: orderStatus.taler_pay_uri,
- },
- );
-
- t.assertTrue(
- preparePayResult.status === PreparePayResultType.PaymentPossible,
- );
- t.assertTrue(
- preparePayResultRep.status === PreparePayResultType.PaymentPossible,
- );
-
- const proposalId = preparePayResult.proposalId;
-
- const confirmPayResult = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId: proposalId,
- },
- );
-
- console.log("confirm pay result", confirmPayResult);
-
- await wallet.runUntilDone();
-
- // Check if payment was successful.
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- const preparePayResultAfter = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri,
- },
- );
-
- console.log("result after:", preparePayResultAfter);
-
- t.assertTrue(
- preparePayResultAfter.status === PreparePayResultType.AlreadyConfirmed,
- );
- t.assertTrue(preparePayResultAfter.paid === true);
-
- await t.shutdown();
-}
-
-runPaymentIdempotencyTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-payment-multiple.ts b/packages/taler-wallet-cli/src/integrationtests/test-payment-multiple.ts
deleted file mode 100644
index 46325c05f..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-payment-multiple.ts
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- 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 {
- GlobalTestState,
- setupDb,
- BankService,
- ExchangeService,
- MerchantService,
- WalletCli,
- MerchantPrivateApi,
- getPayto
-} from "../harness/harness.js";
-import { withdrawViaBank } from "../harness/helpers.js";
-import { coin_ct10, coin_u1 } from "../harness/denomStructures.js";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-
-async function setupTest(
- t: GlobalTestState,
-): Promise<{
- merchant: MerchantService;
- exchange: ExchangeService;
- bank: BankService;
-}> {
- 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 exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
-
- exchange.addOfferedCoins([coin_ct10, coin_u1]);
-
- bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- await exchange.addBankAccount("1", exchangeBankAccount);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- const merchant = await MerchantService.create(t, {
- name: "testmerchant-1",
- currency: "TESTKUDOS",
- httpPort: 8083,
- database: db.connStr,
- });
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- });
-
- await merchant.addInstance({
- id: "minst1",
- name: "minst1",
- paytoUris: [getPayto("minst1")],
- });
-
- console.log("setup done!");
-
- return {
- merchant,
- bank,
- exchange,
- };
-}
-
-/**
- * Run test.
- *
- * This test uses a very sub-optimal denomination structure.
- */
-export async function runPaymentMultipleTest(t: GlobalTestState) {
- // Set up test environment
-
- const { merchant, bank, exchange } = await setupTest(t);
-
- const wallet = new WalletCli(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:100" });
-
- // Set up order.
-
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:80",
- fulfillment_url: "taler://fulfillment-success/thx",
- },
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- // Make wallet pay for the order
-
- const r1 = await wallet.client.call(WalletApiOperation.PreparePayForUri, {
- talerPayUri: orderStatus.taler_pay_uri,
- });
-
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
- // FIXME: should be validated, don't cast!
- proposalId: r1.proposalId,
- });
-
- // Check if payment was successful.
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- await t.shutdown();
-}
-
-runPaymentMultipleTest.suites = ["wallet"];
-runPaymentMultipleTest.timeoutMs = 120000;
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-payment-on-demo.ts b/packages/taler-wallet-cli/src/integrationtests/test-payment-on-demo.ts
deleted file mode 100644
index 737620ce7..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-payment-on-demo.ts
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- 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 { GlobalTestState, WalletCli } from "../harness/harness.js";
-import { makeTestPayment } from "../harness/helpers.js";
-import {
- WalletApiOperation,
- BankApi,
- BankAccessApi,
- BankServiceHandle,
- NodeHttpLib,
-} from "@gnu-taler/taler-wallet-core";
-
-/**
- * Run test for basic, bank-integrated withdrawal and payment.
- */
-export async function runPaymentDemoTest(t: GlobalTestState) {
- // Withdraw digital cash into the wallet.
- let bankInterface: BankServiceHandle = {
- baseUrl: "https://bank.demo.taler.net/",
- bankAccessApiBaseUrl: "https://bank.demo.taler.net/",
- http: new NodeHttpLib(),
- };
- let user = await BankApi.createRandomBankUser(bankInterface);
- let wop = await BankAccessApi.createWithdrawalOperation(
- bankInterface,
- user,
- "KUDOS:20",
- );
-
- let wallet = new WalletCli(t);
- await wallet.client.call(WalletApiOperation.GetWithdrawalDetailsForUri, {
- talerWithdrawUri: wop.taler_withdraw_uri,
- });
-
- await wallet.runPending();
-
- // Confirm it
-
- await BankApi.confirmWithdrawalOperation(bankInterface, user, wop);
-
- // Withdraw
-
- await wallet.client.call(WalletApiOperation.AcceptBankIntegratedWithdrawal, {
- exchangeBaseUrl: "https://exchange.demo.taler.net/",
- talerWithdrawUri: wop.taler_withdraw_uri,
- });
- await wallet.runUntilDone();
-
- let balanceBefore = await wallet.client.call(
- WalletApiOperation.GetBalances,
- {},
- );
- t.assertTrue(balanceBefore["balances"].length == 1);
-
- const order = {
- summary: "Buy me!",
- amount: "KUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- let merchant = {
- makeInstanceBaseUrl: function (instanceName?: string) {
- return "https://backend.demo.taler.net/instances/donations/";
- },
- port: 0,
- name: "donations",
- };
-
- t.assertTrue("TALER_ENV_FRONTENDS_APITOKEN" in process.env);
-
- await makeTestPayment(
- t,
- {
- merchant,
- wallet,
- order,
- },
- {
- Authorization: `Bearer ${process.env["TALER_ENV_FRONTENDS_APITOKEN"]}`,
- },
- );
-
- await wallet.runUntilDone();
-
- let balanceAfter = await wallet.client.call(
- WalletApiOperation.GetBalances,
- {},
- );
- t.assertTrue(balanceAfter["balances"].length == 1);
- t.assertTrue(
- balanceBefore["balances"][0]["available"] >
- balanceAfter["balances"][0]["available"],
- );
-}
-
-runPaymentDemoTest.excludeByDefault = true;
-runPaymentDemoTest.suites = ["buildbot"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-payment-transient.ts b/packages/taler-wallet-cli/src/integrationtests/test-payment-transient.ts
deleted file mode 100644
index b57b355c6..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-payment-transient.ts
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- 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 { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import {
- withdrawViaBank,
- createFaultInjectedMerchantTestkudosEnvironment,
-} from "../harness/helpers.js";
-import {
- FaultInjectionResponseContext,
-} from "../harness/faultInjection.js";
-import {
- codecForMerchantOrderStatusUnpaid,
- ConfirmPayResultType,
- PreparePayResultType,
- TalerErrorCode,
- TalerErrorDetail,
- URL,
-} from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import axiosImp from "axios";
-const axios = axiosImp.default;
-
-/**
- * Run test for a payment where the merchant has a transient
- * failure in /pay
- */
-export async function runPaymentTransientTest(t: GlobalTestState) {
- // Set up test environment
-
- const {
- wallet,
- bank,
- exchange,
- faultyMerchant,
- } = await createFaultInjectedMerchantTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- const merchant = faultyMerchant;
-
- let orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "https://example.com/article42",
- public_reorder_url: "https://example.com/article42-share",
- },
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- sessionId: "mysession-one",
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- t.assertTrue(orderStatus.already_paid_order_id === undefined);
- let publicOrderStatusUrl = orderStatus.order_status_url;
-
- let publicOrderStatusResp = await axios.get(publicOrderStatusUrl, {
- validateStatus: () => true,
- });
-
- if (publicOrderStatusResp.status != 402) {
-
-
- throw Error(
- `expected status 402 (before claiming), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- let pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
- );
-
- console.log(pubUnpaidStatus);
-
- let preparePayResp = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: pubUnpaidStatus.taler_pay_uri,
- },
- );
-
- t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible);
-
- const proposalId = preparePayResp.proposalId;
-
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl, {
- validateStatus: () => true,
- });
-
- if (publicOrderStatusResp.status != 402) {
- throw Error(
- `expected status 402 (after claiming), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
- );
-
- let faultInjected = false;
-
- faultyMerchant.faultProxy.addFault({
- async modifyResponse(ctx: FaultInjectionResponseContext) {
- console.log("in modifyResponse");
- const url = new URL(ctx.request.requestUrl);
- console.log("pathname is", url.pathname);
- if (!url.pathname.endsWith("/pay")) {
- return;
- }
- if (faultInjected) {
- console.log("not injecting pay fault");
- return;
- }
- faultInjected = true;
- console.log("injecting pay fault");
- const err: TalerErrorDetail = {
- code: TalerErrorCode.GENERIC_DB_COMMIT_FAILED,
- hint: "something went wrong",
- };
- ctx.responseBody = Buffer.from(JSON.stringify(err));
- ctx.statusCode = 500;
- },
- });
-
- const confirmPayResp = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId,
- },
- );
-
- console.log(confirmPayResp);
-
- t.assertTrue(confirmPayResp.type === ConfirmPayResultType.Pending);
- t.assertTrue(faultInjected);
-
- const confirmPayRespTwo = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId,
- },
- );
-
- t.assertTrue(confirmPayRespTwo.type === ConfirmPayResultType.Done);
-
- // Now ask the merchant if paid
-
- console.log("requesting", publicOrderStatusUrl);
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl, {
- validateStatus: () => true,
- });
-
- console.log(publicOrderStatusResp.data);
-
- if (publicOrderStatusResp.status != 200) {
- console.log(publicOrderStatusResp.data);
- throw Error(
- `expected status 200 (after paying), but got ${publicOrderStatusResp.status}`,
- );
- }
-}
-
-runPaymentTransientTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-payment-zero.ts b/packages/taler-wallet-cli/src/integrationtests/test-payment-zero.ts
deleted file mode 100644
index c38b8b382..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-payment-zero.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- 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 { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { GlobalTestState } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- makeTestPayment,
-} from "../harness/helpers.js";
-
-/**
- * Run test for a payment for a "free" order with
- * an amount of zero.
- */
-export async function runPaymentZeroTest(t: GlobalTestState) {
- // Set up test environment
-
- const {
- wallet,
- bank,
- exchange,
- merchant,
- } = await createSimpleTestkudosEnvironment(t);
-
- // First, make a "free" payment when we don't even have
- // any money in the
-
- // Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- await wallet.runUntilDone();
-
- await makeTestPayment(t, {
- wallet,
- merchant,
- order: {
- summary: "I am free!",
- amount: "TESTKUDOS:0",
- fulfillment_url: "taler://fulfillment-success/thx",
- },
- });
-
- await wallet.runUntilDone();
-
- const transactions = await wallet.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
-
- for (const tr of transactions.transactions) {
- t.assertDeepEqual(tr.pending, false);
- }
-}
-
-runPaymentZeroTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-payment.ts b/packages/taler-wallet-cli/src/integrationtests/test-payment.ts
deleted file mode 100644
index 66d10f996..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-payment.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- makeTestPayment,
-} from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal and payment.
- */
-export async function runPaymentTest(t: GlobalTestState) {
- // Set up test environment
-
- const {
- wallet,
- bank,
- exchange,
- merchant,
- } = await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
-
- // Test JSON normalization of contract terms: Does the wallet
- // agree with the merchant?
- const order2 = {
- summary: "Testing “unicode” characters",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- await makeTestPayment(t, { wallet, merchant, order: order2 });
- await wallet.runUntilDone();
-
- // Test JSON normalization of contract terms: Does the wallet
- // agree with the merchant?
- const order3 = {
- summary: "Testing\nNewlines\rAnd\tStuff\nHere\b",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- await makeTestPayment(t, { wallet, merchant, order: order3 });
-
- await wallet.runUntilDone();
-}
-
-runPaymentTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-paywall-flow.ts b/packages/taler-wallet-cli/src/integrationtests/test-paywall-flow.ts
deleted file mode 100644
index a9601c625..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-paywall-flow.ts
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- 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 { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-import {
- PreparePayResultType,
- codecForMerchantOrderStatusUnpaid,
- ConfirmPayResultType,
- URL,
-} from "@gnu-taler/taler-util";
-import axiosImp from "axios";
-const axios = axiosImp.default;
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runPaywallFlowTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- /**
- * =========================================================================
- * Create an order and let the wallet pay under a session ID
- *
- * We check along the way that the JSON response to /orders/{order_id}
- * returns the right thing.
- * =========================================================================
- */
-
- let orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "https://example.com/article42",
- public_reorder_url: "https://example.com/article42-share",
- },
- });
-
- const firstOrderId = orderResp.order_id;
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- sessionId: "mysession-one",
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- const talerPayUriOne = orderStatus.taler_pay_uri;
-
- t.assertTrue(orderStatus.already_paid_order_id === undefined);
- let publicOrderStatusUrl = new URL(orderStatus.order_status_url);
-
- let publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
-
- if (publicOrderStatusResp.status != 402) {
- throw Error(
- `expected status 402 (before claiming), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- let pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
- );
-
- console.log(pubUnpaidStatus);
-
- let preparePayResp = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: pubUnpaidStatus.taler_pay_uri,
- },
- );
-
- t.assertTrue(preparePayResp.status === PreparePayResultType.PaymentPossible);
-
- const proposalId = preparePayResp.proposalId;
-
- console.log("requesting", publicOrderStatusUrl.href);
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
- console.log("response body", publicOrderStatusResp.data);
- if (publicOrderStatusResp.status != 402) {
- throw Error(
- `expected status 402 (after claiming), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
- );
-
- const confirmPayRes = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId: proposalId,
- },
- );
-
- t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done);
-
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
-
- console.log(publicOrderStatusResp.data);
-
- if (publicOrderStatusResp.status != 200) {
- console.log(publicOrderStatusResp.data);
- throw Error(
- `expected status 200 (after paying), but got ${publicOrderStatusResp.status}`,
- );
- }
-
- /**
- * =========================================================================
- * Now change up the session ID!
- * =========================================================================
- */
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- sessionId: "mysession-two",
- });
-
- // Should be claimed (not paid!) because of a new session ID
- t.assertTrue(orderStatus.order_status === "claimed");
-
- // Pay with new taler://pay URI, which should
- // have the new session ID!
- // Wallet should now automatically re-play payment.
- preparePayResp = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: talerPayUriOne,
- },
- );
-
- t.assertTrue(preparePayResp.status === PreparePayResultType.AlreadyConfirmed);
- t.assertTrue(preparePayResp.paid);
-
- /**
- * =========================================================================
- * Now we test re-purchase detection.
- * =========================================================================
- */
-
- orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- // Same fulfillment URL as previously!
- fulfillment_url: "https://example.com/article42",
- public_reorder_url: "https://example.com/article42-share",
- },
- });
-
- const secondOrderId = orderResp.order_id;
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: secondOrderId,
- sessionId: "mysession-three",
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- t.assertTrue(orderStatus.already_paid_order_id === undefined);
- publicOrderStatusUrl = new URL(orderStatus.order_status_url);
-
- // Here the re-purchase detection should kick in,
- // and the wallet should re-pay for the old order
- // under the new session ID (mysession-three).
- preparePayResp = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: orderStatus.taler_pay_uri,
- },
- );
-
- t.assertTrue(preparePayResp.status === PreparePayResultType.AlreadyConfirmed);
- t.assertTrue(preparePayResp.paid);
-
- // The first order should now be paid under "mysession-three",
- // as the wallet did re-purchase detection
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: firstOrderId,
- sessionId: "mysession-three",
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- // Check that with a completely new session ID, the status would NOT
- // be paid.
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: firstOrderId,
- sessionId: "mysession-four",
- });
-
- t.assertTrue(orderStatus.order_status === "claimed");
-
- // Now check if the public status of the new order is correct.
-
- console.log("requesting public status", publicOrderStatusUrl);
-
- // Ask the order status of the claimed-but-unpaid order
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
-
- if (publicOrderStatusResp.status != 402) {
- throw Error(`expected status 402, but got ${publicOrderStatusResp.status}`);
- }
-
- pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
- );
-
- console.log(publicOrderStatusResp.data);
-
- t.assertTrue(pubUnpaidStatus.already_paid_order_id === firstOrderId);
-}
-
-runPaywallFlowTest.suites = ["merchant", "wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-peer-to-peer-pull.ts b/packages/taler-wallet-cli/src/integrationtests/test-peer-to-peer-pull.ts
deleted file mode 100644
index 211f20494..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-peer-to-peer-pull.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- 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 { AbsoluteTime, Duration, j2s } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { GlobalTestState, WalletCli } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal and payment.
- */
-export async function runPeerToPeerPullTest(t: GlobalTestState) {
- // Set up test environment
-
- const { bank, exchange, merchant } = await createSimpleTestkudosEnvironment(
- t,
- );
-
- // Withdraw digital cash into the wallet.
- const wallet1 = new WalletCli(t, "w1");
- const wallet2 = new WalletCli(t, "w2");
- await withdrawViaBank(t, {
- wallet: wallet2,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- });
-
- await wallet1.runUntilDone();
-
- const purse_expiration = AbsoluteTime.toTimestamp(
- AbsoluteTime.addDuration(
- AbsoluteTime.now(),
- Duration.fromSpec({ days: 2 }),
- ),
- );
-
- const resp = await wallet1.client.call(
- WalletApiOperation.InitiatePeerPullPayment,
- {
- exchangeBaseUrl: exchange.baseUrl,
- partialContractTerms: {
- summary: "Hello World",
- amount: "TESTKUDOS:5",
- purse_expiration
- },
- },
- );
-
- const checkResp = await wallet2.client.call(
- WalletApiOperation.CheckPeerPullPayment,
- {
- talerUri: resp.talerUri,
- },
- );
-
- console.log(`checkResp: ${j2s(checkResp)}`);
-
- const acceptResp = await wallet2.client.call(
- WalletApiOperation.AcceptPeerPullPayment,
- {
- peerPullPaymentIncomingId: checkResp.peerPullPaymentIncomingId,
- },
- );
-
- await wallet1.runUntilDone();
- await wallet2.runUntilDone();
-
- const txn1 = await wallet1.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
- const txn2 = await wallet2.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
-
- console.log(`txn1: ${j2s(txn1)}`);
- console.log(`txn2: ${j2s(txn2)}`);
-}
-
-runPeerToPeerPullTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-peer-to-peer-push.ts b/packages/taler-wallet-cli/src/integrationtests/test-peer-to-peer-push.ts
deleted file mode 100644
index 4aaeca624..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-peer-to-peer-push.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- 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 { AbsoluteTime, Duration, j2s } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { GlobalTestState, WalletCli } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal and payment.
- */
-export async function runPeerToPeerPushTest(t: GlobalTestState) {
- // Set up test environment
-
- const { bank, exchange } = await createSimpleTestkudosEnvironment(t);
-
- const wallet1 = new WalletCli(t, "w1");
- const wallet2 = new WalletCli(t, "w2");
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, {
- wallet: wallet1,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- });
-
- await wallet1.runUntilDone();
-
- const purse_expiration = AbsoluteTime.toTimestamp(
- AbsoluteTime.addDuration(
- AbsoluteTime.now(),
- Duration.fromSpec({ days: 2 }),
- ),
- );
-
- {
- const resp = await wallet1.client.call(
- WalletApiOperation.InitiatePeerPushPayment,
- {
- partialContractTerms: {
- summary: "Hello World",
- amount: "TESTKUDOS:5",
- purse_expiration
- },
- },
- );
-
- console.log(resp);
-
- }
- const resp = await wallet1.client.call(
- WalletApiOperation.InitiatePeerPushPayment,
- {
- partialContractTerms: {
- summary: "Hello World",
- amount: "TESTKUDOS:5",
- purse_expiration
- },
- },
- );
-
- console.log(resp);
-
- const checkResp = await wallet2.client.call(
- WalletApiOperation.CheckPeerPushPayment,
- {
- talerUri: resp.talerUri,
- },
- );
-
- console.log(checkResp);
-
- const acceptResp = await wallet2.client.call(
- WalletApiOperation.AcceptPeerPushPayment,
- {
- peerPushPaymentIncomingId: checkResp.peerPushPaymentIncomingId,
- },
- );
-
- console.log(acceptResp);
-
- await wallet1.runUntilDone();
- await wallet2.runUntilDone();
-
- const txn1 = await wallet1.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
- const txn2 = await wallet2.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
-
- console.log(`txn1: ${j2s(txn1)}`);
- console.log(`txn2: ${j2s(txn2)}`);
-}
-
-runPeerToPeerPushTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-refund-auto.ts b/packages/taler-wallet-cli/src/integrationtests/test-refund-auto.ts
deleted file mode 100644
index 4c2a2f94a..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-refund-auto.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- 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 { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-import { Duration, durationFromSpec } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runRefundAutoTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- // Set up order.
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- auto_refund: {
- d_us: 3000 * 1000,
- },
- },
- refund_delay: Duration.toTalerProtocolDuration(
- durationFromSpec({ minutes: 5 }),
- ),
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- // Make wallet pay for the order
-
- const r1 = await wallet.client.call(WalletApiOperation.PreparePayForUri, {
- talerPayUri: orderStatus.taler_pay_uri,
- });
-
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
- // FIXME: should be validated, don't cast!
- proposalId: r1.proposalId,
- });
-
- // Check if payment was successful.
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- const ref = await MerchantPrivateApi.giveRefund(merchant, {
- amount: "TESTKUDOS:5",
- instance: "default",
- justification: "foo",
- orderId: orderResp.order_id,
- });
-
- console.log(ref);
-
- // The wallet should now automatically pick up the refund.
- await wallet.runUntilDone();
-
- const transactions = await wallet.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
- console.log(JSON.stringify(transactions, undefined, 2));
-
- const transactionTypes = transactions.transactions.map((x) => x.type);
- t.assertDeepEqual(transactionTypes, ["withdrawal", "payment", "refund"]);
-
- await t.shutdown();
-}
-
-runRefundAutoTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-refund-gone.ts b/packages/taler-wallet-cli/src/integrationtests/test-refund-gone.ts
deleted file mode 100644
index b6cefda86..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-refund-gone.ts
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- 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 { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- applyTimeTravel,
-} from "../harness/helpers.js";
-import {
- AbsoluteTime,
- Duration,
- durationFromSpec,
-} from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runRefundGoneTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- // Set up order.
-
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- pay_deadline: AbsoluteTime.toTimestamp(
- AbsoluteTime.addDuration(
- AbsoluteTime.now(),
- durationFromSpec({
- minutes: 10,
- }),
- ),
- ),
- },
- refund_delay: Duration.toTalerProtocolDuration(
- durationFromSpec({ minutes: 1 }),
- ),
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- // Make wallet pay for the order
-
- const r1 = await wallet.client.call(WalletApiOperation.PreparePayForUri, {
- talerPayUri: orderStatus.taler_pay_uri,
- });
-
- const r2 = await wallet.client.call(WalletApiOperation.ConfirmPay, {
- proposalId: r1.proposalId,
- });
-
- // Check if payment was successful.
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- console.log(orderStatus);
-
- await applyTimeTravel(durationFromSpec({ hours: 1 }), { exchange, wallet });
-
- await exchange.runAggregatorOnce();
-
- const ref = await MerchantPrivateApi.giveRefund(merchant, {
- amount: "TESTKUDOS:5",
- instance: "default",
- justification: "foo",
- orderId: orderResp.order_id,
- });
-
- console.log(ref);
-
- let rr = await wallet.client.call(WalletApiOperation.ApplyRefund, {
- talerRefundUri: ref.talerRefundUri,
- });
-
- console.log("refund response:", rr);
- t.assertAmountEquals(rr.amountRefundGone, "TESTKUDOS:5");
-
- await wallet.runUntilDone();
-
- let r = await wallet.client.call(WalletApiOperation.GetBalances, {});
- console.log(JSON.stringify(r, undefined, 2));
-
- const r3 = await wallet.client.call(WalletApiOperation.GetTransactions, {});
- console.log(JSON.stringify(r3, undefined, 2));
-
- await t.shutdown();
-}
-
-runRefundGoneTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-refund-incremental.ts b/packages/taler-wallet-cli/src/integrationtests/test-refund-incremental.ts
deleted file mode 100644
index 8d1f6e873..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-refund-incremental.ts
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- 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 {
- GlobalTestState,
- delayMs,
- MerchantPrivateApi,
-} from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-import {
- TransactionType,
- Amounts,
- durationFromSpec,
- Duration,
-} from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runRefundIncrementalTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- // Set up order.
-
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:10",
- fulfillment_url: "taler://fulfillment-success/thx",
- },
- refund_delay: Duration.toTalerProtocolDuration(
- durationFromSpec({ minutes: 5 }),
- ),
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- // Make wallet pay for the order
-
- const r1 = await wallet.client.call(WalletApiOperation.PreparePayForUri, {
- talerPayUri: orderStatus.taler_pay_uri,
- });
-
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
- proposalId: r1.proposalId,
- });
-
- // Check if payment was successful.
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- let ref = await MerchantPrivateApi.giveRefund(merchant, {
- amount: "TESTKUDOS:2.5",
- instance: "default",
- justification: "foo",
- orderId: orderResp.order_id,
- });
-
- console.log("first refund increase response", ref);
-
- {
- let wr = await wallet.client.call(WalletApiOperation.ApplyRefund, {
- talerRefundUri: ref.talerRefundUri,
- });
- console.log(wr);
- const txs = await wallet.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
- console.log(
- "transactions after applying first refund:",
- JSON.stringify(txs, undefined, 2),
- );
- }
-
- // Wait at least a second, because otherwise the increased
- // refund will be grouped with the previous one.
- await delayMs(1200);
-
- ref = await MerchantPrivateApi.giveRefund(merchant, {
- amount: "TESTKUDOS:5",
- instance: "default",
- justification: "bar",
- orderId: orderResp.order_id,
- });
-
- console.log("second refund increase response", ref);
-
- // Wait at least a second, because otherwise the increased
- // refund will be grouped with the previous one.
- await delayMs(1200);
-
- ref = await MerchantPrivateApi.giveRefund(merchant, {
- amount: "TESTKUDOS:10",
- instance: "default",
- justification: "bar",
- orderId: orderResp.order_id,
- });
-
- console.log("third refund increase response", ref);
-
- {
- let wr = await wallet.client.call(WalletApiOperation.ApplyRefund, {
- talerRefundUri: ref.talerRefundUri,
- });
- console.log(wr);
- }
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- t.assertAmountEquals(orderStatus.refund_amount, "TESTKUDOS:10");
-
- console.log(JSON.stringify(orderStatus, undefined, 2));
-
- await wallet.runUntilDone();
-
- const bal = await wallet.client.call(WalletApiOperation.GetBalances, {});
- console.log(JSON.stringify(bal, undefined, 2));
-
- {
- const txs = await wallet.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
- console.log(JSON.stringify(txs, undefined, 2));
-
- const txTypes = txs.transactions.map((x) => x.type);
- t.assertDeepEqual(txTypes, [
- "withdrawal",
- "payment",
- "refund",
- "refund",
- "refund",
- ]);
-
- for (const tx of txs.transactions) {
- if (tx.type !== TransactionType.Refund) {
- continue;
- }
- t.assertAmountLeq(tx.amountEffective, tx.amountRaw);
- }
-
- const raw = Amounts.sum(
- txs.transactions
- .filter((x) => x.type === TransactionType.Refund)
- .map((x) => x.amountRaw),
- ).amount;
-
- t.assertAmountEquals("TESTKUDOS:10", raw);
-
- const effective = Amounts.sum(
- txs.transactions
- .filter((x) => x.type === TransactionType.Refund)
- .map((x) => x.amountEffective),
- ).amount;
-
- t.assertAmountEquals("TESTKUDOS:8.59", effective);
- }
-
- await t.shutdown();
-}
-
-runRefundIncrementalTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-refund.ts b/packages/taler-wallet-cli/src/integrationtests/test-refund.ts
deleted file mode 100644
index b63dad590..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-refund.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- 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 { Duration, durationFromSpec } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runRefundTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- // Set up order.
-
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- },
- refund_delay: Duration.toTalerProtocolDuration(
- durationFromSpec({ minutes: 5 }),
- ),
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- // Make wallet pay for the order
-
- const r1 = await wallet.client.call(WalletApiOperation.PreparePayForUri, {
- talerPayUri: orderStatus.taler_pay_uri,
- });
-
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
- proposalId: r1.proposalId,
- });
-
- // Check if payment was successful.
-
- orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "paid");
-
- const ref = await MerchantPrivateApi.giveRefund(merchant, {
- amount: "TESTKUDOS:5",
- instance: "default",
- justification: "foo",
- orderId: orderResp.order_id,
- });
-
- console.log(ref);
-
- let r = await wallet.client.call(WalletApiOperation.ApplyRefund, {
- talerRefundUri: ref.talerRefundUri,
- });
- console.log(r);
-
- await wallet.runUntilDone();
-
- {
- const r2 = await wallet.client.call(WalletApiOperation.GetBalances, {});
- console.log(JSON.stringify(r2, undefined, 2));
- }
- {
- const r2 = await wallet.client.call(WalletApiOperation.GetTransactions, {});
- console.log(JSON.stringify(r2, undefined, 2));
- }
-
- await t.shutdown();
-}
-
-runRefundTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-revocation.ts b/packages/taler-wallet-cli/src/integrationtests/test-revocation.ts
deleted file mode 100644
index 0fbb4960e..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-revocation.ts
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- 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 { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { CoinConfig } from "../harness/denomStructures.js";
-import {
- GlobalTestState,
- ExchangeService,
- MerchantService,
- WalletCli,
- setupDb,
- BankService,
- delayMs,
- getPayto,
-} from "../harness/harness.js";
-import {
- withdrawViaBank,
- makeTestPayment,
- SimpleTestEnvironment,
-} from "../harness/helpers.js";
-
-async function revokeAllWalletCoins(req: {
- wallet: WalletCli;
- exchange: ExchangeService;
- merchant: MerchantService;
-}): Promise<void> {
- const { wallet, exchange, merchant } = req;
- const coinDump = await wallet.client.call(WalletApiOperation.DumpCoins, {});
- console.log(coinDump);
- const usedDenomHashes = new Set<string>();
- for (const coin of coinDump.coins) {
- usedDenomHashes.add(coin.denom_pub_hash);
- }
- for (const x of usedDenomHashes.values()) {
- await exchange.revokeDenomination(x);
- }
- await delayMs(1000);
- await exchange.keyup();
- await delayMs(1000);
- await merchant.stop();
- await merchant.start();
- await merchant.pingUntilAvailable();
-}
-
-async function createTestEnvironment(
- t: GlobalTestState,
-): Promise<SimpleTestEnvironment> {
- 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,
- });
-
- const exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
- exchange.addBankAccount("1", exchangeBankAccount);
-
- bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- const coin_u1: CoinConfig = {
- cipher: "RSA" as const,
- durationLegal: "3 years",
- durationSpend: "2 years",
- durationWithdraw: "7 days",
- rsaKeySize: 1024,
- name: `TESTKUDOS_u1`,
- value: `TESTKUDOS:1`,
- feeDeposit: `TESTKUDOS:0`,
- feeRefresh: `TESTKUDOS:0`,
- feeRefund: `TESTKUDOS:0`,
- feeWithdraw: `TESTKUDOS:0`,
- };
-
- exchange.addCoinConfigList([coin_u1]);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- });
-
- await merchant.addInstance({
- id: "minst1",
- name: "minst1",
- paytoUris: [getPayto("minst1")],
- });
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- return {
- commonDb: db,
- exchange,
- merchant,
- wallet,
- bank,
- exchangeBankAccount,
- };
-}
-
-/**
- * Basic time travel test.
- */
-export async function runRevocationTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } = await createTestEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:15" });
-
- console.log("revoking first time");
- await revokeAllWalletCoins({ wallet, exchange, merchant });
-
- // FIXME: this shouldn't be necessary once https://bugs.taler.net/n/6565
- // is implemented.
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: exchange.baseUrl,
- forceUpdate: true,
- });
- await wallet.runUntilDone();
- await wallet.runUntilDone();
- const bal = await wallet.client.call(WalletApiOperation.GetBalances, {});
- console.log("wallet balance", bal);
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:10",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- await makeTestPayment(t, { wallet, merchant, order });
-
- wallet.deleteDatabase();
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:15" });
-
- const coinDump = await wallet.client.call(WalletApiOperation.DumpCoins, {});
- console.log(coinDump);
- const coinPubList = coinDump.coins.map((x) => x.coin_pub);
- await wallet.client.call(WalletApiOperation.ForceRefresh, {
- coinPubList,
- });
- await wallet.runUntilDone();
-
- console.log("revoking second time");
- await revokeAllWalletCoins({ wallet, exchange, merchant });
-
- // FIXME: this shouldn't be necessary once https://bugs.taler.net/n/6565
- // is implemented.
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: exchange.baseUrl,
- forceUpdate: true,
- });
- await wallet.runUntilDone();
- await wallet.runUntilDone();
- {
- const bal = await wallet.client.call(WalletApiOperation.GetBalances, {});
- console.log("wallet balance", bal);
- }
-
- await makeTestPayment(t, { wallet, merchant, order });
-}
-
-runRevocationTest.timeoutMs = 120000;
-runRevocationTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-timetravel-autorefresh.ts b/packages/taler-wallet-cli/src/integrationtests/test-timetravel-autorefresh.ts
deleted file mode 100644
index 54b66e0b2..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-timetravel-autorefresh.ts
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- 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 {
- ConfirmPayResultType,
- Duration,
- durationFromSpec,
- PreparePayResultType,
-} from "@gnu-taler/taler-util";
-import {
- PendingOperationsResponse,
- WalletApiOperation,
-} from "@gnu-taler/taler-wallet-core";
-import { makeNoFeeCoinConfig } from "../harness/denomStructures.js";
-import {
- BankService,
- ExchangeService,
- GlobalTestState,
- MerchantPrivateApi,
- MerchantService,
- setupDb,
- WalletCli,
- getPayto
-} from "../harness/harness.js";
-import { startWithdrawViaBank, withdrawViaBank } from "../harness/helpers.js";
-
-async function applyTimeTravel(
- timetravelDuration: Duration,
- s: {
- exchange?: ExchangeService;
- merchant?: MerchantService;
- wallet?: WalletCli;
- },
-): Promise<void> {
- if (s.exchange) {
- await s.exchange.stop();
- s.exchange.setTimetravel(timetravelDuration);
- await s.exchange.start();
- await s.exchange.pingUntilAvailable();
- }
-
- if (s.merchant) {
- await s.merchant.stop();
- s.merchant.setTimetravel(timetravelDuration);
- await s.merchant.start();
- await s.merchant.pingUntilAvailable();
- }
-
- if (s.wallet) {
- console.log("setting wallet time travel to", timetravelDuration);
- s.wallet.setTimetravel(timetravelDuration);
- }
-}
-
-/**
- * Basic time travel test.
- */
-export async function runTimetravelAutorefreshTest(t: GlobalTestState) {
- // Set up test environment
-
- 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,
- });
-
- const exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
- exchange.addBankAccount("1", exchangeBankAccount);
-
- bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- exchange.addCoinConfigList(makeNoFeeCoinConfig("TESTKUDOS"));
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- });
-
- await merchant.addInstance({
- id: "minst1",
- name: "minst1",
- paytoUris: [getPayto("minst1")],
- });
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:15" });
-
- // Travel into the future, the deposit expiration is two years
- // into the future.
- console.log("applying first time travel");
- await applyTimeTravel(durationFromSpec({ days: 400 }), {
- wallet,
- exchange,
- merchant,
- });
-
- await wallet.runUntilDone();
-
- let p: PendingOperationsResponse;
- p = await wallet.client.call(WalletApiOperation.GetPendingOperations, {});
-
- console.log("pending operations after first time travel");
- console.log(JSON.stringify(p, undefined, 2));
-
- await startWithdrawViaBank(t, {
- wallet,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- });
-
- await wallet.runUntilDone();
-
- // Travel into the future, the deposit expiration is two years
- // into the future.
- console.log("applying second time travel");
- await applyTimeTravel(durationFromSpec({ years: 2, months: 6 }), {
- wallet,
- exchange,
- merchant,
- });
-
- // At this point, the original coins should've been refreshed.
- // It would be too late to refresh them now, as we're past
- // the two year deposit expiration.
-
- await wallet.runUntilDone();
-
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order: {
- fulfillment_url: "http://example.com",
- summary: "foo",
- amount: "TESTKUDOS:30",
- },
- });
-
- const orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(
- merchant,
- {
- orderId: orderResp.order_id,
- instance: "default",
- },
- );
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- const r = await wallet.client.call(WalletApiOperation.PreparePayForUri, {
- talerPayUri: orderStatus.taler_pay_uri,
- });
-
- console.log(r);
-
- t.assertTrue(r.status === PreparePayResultType.PaymentPossible);
-
- const cpr = await wallet.client.call(WalletApiOperation.ConfirmPay, {
- proposalId: r.proposalId,
- });
-
- t.assertTrue(cpr.type === ConfirmPayResultType.Done);
-}
-
-runTimetravelAutorefreshTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-timetravel-withdraw.ts b/packages/taler-wallet-cli/src/integrationtests/test-timetravel-withdraw.ts
deleted file mode 100644
index 9335af9f5..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-timetravel-withdraw.ts
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- 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 { Duration, TransactionType } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { GlobalTestState } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- startWithdrawViaBank,
- withdrawViaBank,
-} from "../harness/helpers.js";
-
-/**
- * Basic time travel test.
- */
-export async function runTimetravelWithdrawTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:15" });
-
- // Travel 400 days into the future,
- // as the deposit expiration is two years
- // into the future.
- const timetravelDuration: Duration = {
- d_ms: 1000 * 60 * 60 * 24 * 400,
- };
-
- await exchange.stop();
- exchange.setTimetravel(timetravelDuration);
- await exchange.start();
- await exchange.pingUntilAvailable();
- await exchange.keyup();
-
- await merchant.stop();
- merchant.setTimetravel(timetravelDuration);
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- console.log("starting withdrawal via bank");
-
- // This should fail, as the wallet didn't time travel yet.
- await startWithdrawViaBank(t, {
- wallet,
- bank,
- exchange,
- amount: "TESTKUDOS:20",
- });
-
- console.log("starting withdrawal done");
-
- // Check that transactions are correct for the failed withdrawal
- {
- console.log("running until done (should run into maxRetries limit)");
- await wallet.runUntilDone({ maxRetries: 5 });
- console.log("wallet done running");
- const transactions = await wallet.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
- console.log(transactions);
- const types = transactions.transactions.map((x) => x.type);
- t.assertDeepEqual(types, ["withdrawal", "withdrawal"]);
- const wtrans = transactions.transactions[1];
- t.assertTrue(wtrans.type === TransactionType.Withdrawal);
- t.assertTrue(wtrans.pending);
- }
-
- // Now we also let the wallet time travel
-
- wallet.setTimetravel(timetravelDuration);
-
- // This doesn't work yet, see https://bugs.taler.net/n/6585
-
- // await wallet.runUntilDone({ maxRetries: 5 });
-}
-
-runTimetravelWithdrawTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-tipping.ts b/packages/taler-wallet-cli/src/integrationtests/test-tipping.ts
deleted file mode 100644
index d31e0c06b..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-tipping.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- 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 { WalletApiOperation, BankApi } from "@gnu-taler/taler-wallet-core";
-import {
- GlobalTestState,
- MerchantPrivateApi,
- getWireMethodForTest,
-} from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runTippingTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, merchant, exchangeBankAccount } =
- await createSimpleTestkudosEnvironment(t);
-
- const mbu = await BankApi.createRandomBankUser(bank);
-
- const tipReserveResp = await MerchantPrivateApi.createTippingReserve(
- merchant,
- "default",
- {
- exchange_url: exchange.baseUrl,
- initial_balance: "TESTKUDOS:10",
- wire_method: getWireMethodForTest(),
- },
- );
-
- console.log("tipReserveResp:", tipReserveResp);
-
- t.assertDeepEqual(
- tipReserveResp.payto_uri,
- exchangeBankAccount.accountPaytoUri,
- );
-
- await BankApi.adminAddIncoming(bank, {
- amount: "TESTKUDOS:10",
- debitAccountPayto: mbu.accountPaytoUri,
- exchangeBankAccount,
- reservePub: tipReserveResp.reserve_pub,
- });
-
- await exchange.runWirewatchOnce();
-
- await merchant.stop();
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- const r = await MerchantPrivateApi.queryTippingReserves(merchant, "default");
- console.log("tipping reserves:", JSON.stringify(r, undefined, 2));
-
- t.assertTrue(r.reserves.length === 1);
- t.assertDeepEqual(
- r.reserves[0].exchange_initial_amount,
- r.reserves[0].merchant_initial_amount,
- );
-
- const tip = await MerchantPrivateApi.giveTip(merchant, "default", {
- amount: "TESTKUDOS:5",
- justification: "why not?",
- next_url: "https://example.com/after-tip",
- });
-
- console.log("created tip", tip);
-
- const doTip = async (): Promise<void> => {
- const ptr = await wallet.client.call(WalletApiOperation.PrepareTip, {
- talerTipUri: tip.taler_tip_uri,
- });
-
- console.log(ptr);
-
- t.assertAmountEquals(ptr.tipAmountRaw, "TESTKUDOS:5");
- t.assertAmountEquals(ptr.tipAmountEffective, "TESTKUDOS:4.85");
-
- await wallet.client.call(WalletApiOperation.AcceptTip, {
- walletTipId: ptr.walletTipId,
- });
-
- await wallet.runUntilDone();
-
- const bal = await wallet.client.call(WalletApiOperation.GetBalances, {});
-
- console.log(bal);
-
- t.assertAmountEquals(bal.balances[0].available, "TESTKUDOS:4.85");
-
- const txns = await wallet.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
-
- console.log("Transactions:", JSON.stringify(txns, undefined, 2));
-
- t.assertDeepEqual(txns.transactions[0].type, "tip");
- t.assertDeepEqual(txns.transactions[0].pending, false);
- t.assertAmountEquals(
- txns.transactions[0].amountEffective,
- "TESTKUDOS:4.85",
- );
- t.assertAmountEquals(txns.transactions[0].amountRaw, "TESTKUDOS:5.0");
- };
-
- // Check twice so make sure tip handling is idempotent
- await doTip();
- await doTip();
-}
-
-runTippingTest.suites = ["wallet", "wallet-tipping"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-wallet-backup-basic.ts b/packages/taler-wallet-cli/src/integrationtests/test-wallet-backup-basic.ts
deleted file mode 100644
index fc2f3335d..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-wallet-backup-basic.ts
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- 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, WalletCli } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-import { SyncService } from "../harness/sync.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runWalletBackupBasicTest(t: GlobalTestState) {
- // Set up test environment
-
- const { commonDb, merchant, wallet, bank, exchange } =
- await createSimpleTestkudosEnvironment(t);
-
- const sync = await SyncService.create(t, {
- currency: "TESTKUDOS",
- annualFee: "TESTKUDOS:0.5",
- database: commonDb.connStr,
- fulfillmentUrl: "taler://fulfillment-success",
- httpPort: 8089,
- name: "sync1",
- paymentBackendUrl: merchant.makeInstanceBaseUrl(),
- uploadLimitMb: 10,
- });
-
- await sync.start();
- await sync.pingUntilAvailable();
-
- await wallet.client.call(WalletApiOperation.AddBackupProvider, {
- backupProviderBaseUrl: sync.baseUrl,
- activate: false,
- name: sync.baseUrl,
- });
-
- {
- const bi = await wallet.client.call(WalletApiOperation.GetBackupInfo, {});
- t.assertDeepEqual(bi.providers[0].active, false);
- }
-
- await wallet.client.call(WalletApiOperation.AddBackupProvider, {
- backupProviderBaseUrl: sync.baseUrl,
- activate: true,
- name: sync.baseUrl,
- });
-
- {
- const bi = await wallet.client.call(WalletApiOperation.GetBackupInfo, {});
- t.assertDeepEqual(bi.providers[0].active, true);
- }
-
- await wallet.client.call(WalletApiOperation.RunBackupCycle, {});
-
- {
- const bi = await wallet.client.call(WalletApiOperation.GetBackupInfo, {});
- console.log(bi);
- t.assertDeepEqual(
- bi.providers[0].paymentStatus.type,
- "insufficient-balance",
- );
- }
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:10" });
-
- await wallet.runUntilDone();
-
- await wallet.client.call(WalletApiOperation.RunBackupCycle, {});
-
- {
- const bi = await wallet.client.call(WalletApiOperation.GetBackupInfo, {});
- console.log(bi);
- }
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:5" });
-
- await wallet.client.call(WalletApiOperation.RunBackupCycle, {});
-
- {
- const bi = await wallet.client.call(WalletApiOperation.GetBackupInfo, {});
- console.log(bi);
- }
-
- const backupRecovery = await wallet.client.call(
- WalletApiOperation.ExportBackupRecovery,
- {},
- );
-
- const txs = await wallet.client.call(WalletApiOperation.GetTransactions, {});
- console.log(`backed up transactions ${j2s(txs)}`);
-
- const wallet2 = new WalletCli(t, "wallet2");
-
- // Check that the second wallet is a fresh wallet.
- {
- const bal = await wallet2.client.call(WalletApiOperation.GetBalances, {});
- t.assertTrue(bal.balances.length === 0);
- }
-
- await wallet2.client.call(WalletApiOperation.ImportBackupRecovery, {
- recovery: backupRecovery,
- });
-
- await wallet2.client.call(WalletApiOperation.RunBackupCycle, {});
-
- // Check that now the old balance is available!
- {
- const bal = await wallet2.client.call(WalletApiOperation.GetBalances, {});
- t.assertTrue(bal.balances.length === 1);
- console.log(bal);
- }
-
- // Now do some basic checks that the restored wallet is still functional
- {
- const txs = await wallet2.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
- console.log(`restored transactions ${j2s(txs)}`);
- const bal1 = await wallet2.client.call(WalletApiOperation.GetBalances, {});
-
- t.assertAmountEquals(bal1.balances[0].available, "TESTKUDOS:14.1");
-
- await withdrawViaBank(t, {
- wallet: wallet2,
- bank,
- exchange,
- amount: "TESTKUDOS:10",
- });
-
- await exchange.runWirewatchOnce();
-
- await wallet2.runUntilDone();
-
- const txs2 = await wallet2.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
- console.log(`tx after withdraw after restore ${j2s(txs2)}`);
-
- const bal2 = await wallet2.client.call(WalletApiOperation.GetBalances, {});
-
- t.assertAmountEquals(bal2.balances[0].available, "TESTKUDOS:23.82");
- }
-}
-
-runWalletBackupBasicTest.suites = ["wallet", "wallet-backup"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-wallet-backup-doublespend.ts b/packages/taler-wallet-cli/src/integrationtests/test-wallet-backup-doublespend.ts
deleted file mode 100644
index 8b52260e9..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-wallet-backup-doublespend.ts
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- 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 { PreparePayResultType } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import {
- GlobalTestState,
- WalletCli,
- MerchantPrivateApi,
-} from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- makeTestPayment,
- withdrawViaBank,
-} from "../harness/helpers.js";
-import { SyncService } from "../harness/sync.js";
-
-export async function runWalletBackupDoublespendTest(t: GlobalTestState) {
- // Set up test environment
-
- const { commonDb, merchant, wallet, bank, exchange } =
- await createSimpleTestkudosEnvironment(t);
-
- const sync = await SyncService.create(t, {
- currency: "TESTKUDOS",
- annualFee: "TESTKUDOS:0.5",
- database: commonDb.connStr,
- fulfillmentUrl: "taler://fulfillment-success",
- httpPort: 8089,
- name: "sync1",
- paymentBackendUrl: merchant.makeInstanceBaseUrl(),
- uploadLimitMb: 10,
- });
-
- await sync.start();
- await sync.pingUntilAvailable();
-
- await wallet.client.call(WalletApiOperation.AddBackupProvider, {
- backupProviderBaseUrl: sync.baseUrl,
- activate: true,
- name: sync.baseUrl,
- });
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:10" });
-
- await wallet.runUntilDone();
-
- await wallet.client.call(WalletApiOperation.RunBackupCycle, {});
- await wallet.runUntilDone();
- await wallet.client.call(WalletApiOperation.RunBackupCycle, {});
-
- const backupRecovery = await wallet.client.call(
- WalletApiOperation.ExportBackupRecovery,
- {},
- );
-
- const wallet2 = new WalletCli(t, "wallet2");
-
- await wallet2.client.call(WalletApiOperation.ImportBackupRecovery, {
- recovery: backupRecovery,
- });
-
- await wallet2.client.call(WalletApiOperation.RunBackupCycle, {});
-
- console.log(
- "wallet1 balance before spend:",
- await wallet.client.call(WalletApiOperation.GetBalances, {}),
- );
-
- await makeTestPayment(t, {
- merchant,
- wallet,
- order: {
- summary: "foo",
- amount: "TESTKUDOS:7",
- },
- });
-
- await wallet.runUntilDone();
-
- console.log(
- "wallet1 balance after spend:",
- await wallet.client.call(WalletApiOperation.GetBalances, {}),
- );
-
- {
- console.log(
- "wallet2 balance:",
- await wallet2.client.call(WalletApiOperation.GetBalances, {}),
- );
- }
-
- // Now we double-spend with the second wallet
-
- {
- const instance = "default";
-
- const orderResp = await MerchantPrivateApi.createOrder(merchant, instance, {
- order: {
- amount: "TESTKUDOS:8",
- summary: "bla",
- fulfillment_url: "taler://fulfillment-success",
- },
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(
- merchant,
- {
- orderId: orderResp.order_id,
- },
- );
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- // Make wallet pay for the order
-
- {
- console.log(
- "wallet2 balance before preparePay:",
- await wallet2.client.call(WalletApiOperation.GetBalances, {}),
- );
- }
-
- const preparePayResult = await wallet2.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: orderStatus.taler_pay_uri,
- },
- );
-
- t.assertDeepEqual(
- preparePayResult.status,
- PreparePayResultType.PaymentPossible,
- );
-
- const res = await wallet2.client.call(WalletApiOperation.ConfirmPay, {
- proposalId: preparePayResult.proposalId,
- });
-
- console.log(res);
-
- // FIXME: wait for a notification that indicates insufficient funds!
-
- await withdrawViaBank(t, {
- wallet: wallet2,
- bank,
- exchange,
- amount: "TESTKUDOS:50",
- });
-
- const bal = await wallet2.client.call(WalletApiOperation.GetBalances, {});
- console.log("bal", bal);
-
- await wallet2.runUntilDone();
- }
-}
-
-runWalletBackupDoublespendTest.suites = ["wallet", "wallet-backup"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-wallet-balance.ts b/packages/taler-wallet-cli/src/integrationtests/test-wallet-balance.ts
deleted file mode 100644
index f5226c6c0..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-wallet-balance.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- 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 { Duration, PreparePayResultType } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
-import {
- ExchangeService,
- FakebankService,
- getRandomIban,
- GlobalTestState,
- MerchantPrivateApi,
- MerchantService,
- setupDb,
- WalletCli,
-} from "../harness/harness.js";
-import { withdrawViaBank } from "../harness/helpers.js";
-
-/**
- * Test for wallet balance error messages / different types of insufficient balance.
- *
- * Related bugs:
- * https://bugs.taler.net/n/7299
- */
-export async function runWalletBalanceTest(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",
- );
- 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();
-
- // Fakebank uses x-taler-bank, but merchant is configured to only accept sepa!
- const label = "mymerchant";
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [
- `payto://iban/SANDBOXX/${getRandomIban(label)}?receiver-name=${label}`,
- ],
- defaultWireTransferDelay: Duration.toTalerProtocolDuration(
- Duration.fromSpec({ minutes: 1 }),
- ),
- });
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- // Withdraw digital cash into the wallet.
-
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
-
- const order = {
- summary: "Buy me!",
- amount: "TESTKUDOS:5",
- fulfillment_url: "taler://fulfillment-success/thx",
- };
-
- const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
- order,
- });
-
- let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
- orderId: orderResp.order_id,
- });
-
- t.assertTrue(orderStatus.order_status === "unpaid");
-
- // Make wallet pay for the order
-
- const preparePayResult = await wallet.client.call(
- WalletApiOperation.PreparePayForUri,
- {
- talerPayUri: orderStatus.taler_pay_uri,
- },
- );
-
- t.assertDeepEqual(
- preparePayResult.status,
- PreparePayResultType.InsufficientBalance,
- );
-
- await wallet.runUntilDone();
-}
-
-runWalletBalanceTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-wallet-cryptoworker.ts b/packages/taler-wallet-cli/src/integrationtests/test-wallet-cryptoworker.ts
deleted file mode 100644
index a9f1c4d80..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-wallet-cryptoworker.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- 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 {
- checkReserve,
- CryptoDispatcher,
- depositCoin,
- downloadExchangeInfo,
- findDenomOrThrow,
- NodeHttpLib,
- refreshCoin,
- SynchronousCryptoWorkerFactoryNode,
- TalerError,
- topupReserveWithDemobank,
- WalletApiOperation,
- withdrawCoin,
-} from "@gnu-taler/taler-wallet-core";
-import { GlobalTestState, WalletCli } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
-
-/**
- * Run test for the different crypto workers.
- */
-export async function runWalletCryptoWorkerTest(t: GlobalTestState) {
- const wallet1 = new WalletCli(t, "w1", {
- cryptoWorkerType: "sync",
- });
-
- await wallet1.client.call(WalletApiOperation.TestCrypto, {});
-
- const wallet2 = new WalletCli(t, "w2", {
- cryptoWorkerType: "node-worker-thread",
- });
-
- await wallet2.client.call(WalletApiOperation.TestCrypto, {});
-}
-
-runWalletCryptoWorkerTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-wallet-dbless.ts b/packages/taler-wallet-cli/src/integrationtests/test-wallet-dbless.ts
deleted file mode 100644
index 269a8b240..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-wallet-dbless.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- 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 {
- checkReserve,
- CryptoDispatcher,
- depositCoin,
- downloadExchangeInfo,
- findDenomOrThrow,
- NodeHttpLib,
- refreshCoin,
- SynchronousCryptoWorkerFactoryNode,
- TalerError,
- topupReserveWithDemobank,
- withdrawCoin,
-} from "@gnu-taler/taler-wallet-core";
-import { GlobalTestState } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal and payment.
- */
-export async function runWalletDblessTest(t: GlobalTestState) {
- // Set up test environment
-
- const { bank, exchange } = await createSimpleTestkudosEnvironment(t);
-
- const http = new NodeHttpLib();
- const cryptiDisp = new CryptoDispatcher(new SynchronousCryptoWorkerFactoryNode());
- const cryptoApi = cryptiDisp.cryptoApi;
-
- try {
- // Withdraw digital cash into the wallet.
-
- const exchangeInfo = await downloadExchangeInfo(exchange.baseUrl, http);
-
- const reserveKeyPair = await cryptoApi.createEddsaKeypair({});
-
- await topupReserveWithDemobank(
- http,
- reserveKeyPair.pub,
- bank.baseUrl,
- bank.bankAccessApiBaseUrl,
- exchangeInfo,
- "TESTKUDOS:10",
- );
-
- await exchange.runWirewatchOnce();
-
- await checkReserve(http, exchange.baseUrl, reserveKeyPair.pub);
-
- const d1 = findDenomOrThrow(exchangeInfo, "TESTKUDOS:8");
-
- const coin = await withdrawCoin({
- http,
- cryptoApi,
- reserveKeyPair: {
- reservePriv: reserveKeyPair.priv,
- reservePub: reserveKeyPair.pub,
- },
- denom: d1,
- exchangeBaseUrl: exchange.baseUrl,
- });
-
- await depositCoin({
- amount: "TESTKUDOS:4",
- coin: coin,
- cryptoApi,
- exchangeBaseUrl: exchange.baseUrl,
- http,
- });
-
- const refreshDenoms = [
- findDenomOrThrow(exchangeInfo, "TESTKUDOS:1"),
- findDenomOrThrow(exchangeInfo, "TESTKUDOS:1"),
- ];
-
- await refreshCoin({
- oldCoin: coin,
- cryptoApi,
- http,
- newDenoms: refreshDenoms,
- });
- } catch (e) {
- if (e instanceof TalerError) {
- console.log(e);
- console.log(j2s(e.errorDetail));
- } else {
- console.log(e);
- }
- throw e;
- }
-}
-
-runWalletDblessTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-wallettesting.ts b/packages/taler-wallet-cli/src/integrationtests/test-wallettesting.ts
deleted file mode 100644
index 03c446db3..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-wallettesting.ts
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- 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/>
- */
-
-/**
- * Integration test for the wallet testing functionality used by the exchange
- * test cases.
- */
-
-/**
- * Imports.
- */
-import { Amounts, CoinStatus } from "@gnu-taler/taler-util";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
-import {
- BankService,
- ExchangeService,
- GlobalTestState,
- MerchantService,
- setupDb,
- WalletCli,
- getPayto,
-} from "../harness/harness.js";
-import { SimpleTestEnvironment } from "../harness/helpers.js";
-
-const merchantAuthToken = "secret-token:sandbox";
-
-/**
- * Run a test case with a simple TESTKUDOS Taler environment, consisting
- * of one exchange, one bank and one merchant.
- */
-export async function createMyEnvironment(
- t: GlobalTestState,
- coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS")),
-): Promise<SimpleTestEnvironment> {
- 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,
- });
-
- const exchangeBankAccount = await bank.createExchangeAccount(
- "myexchange",
- "x",
- );
- exchange.addBankAccount("1", exchangeBankAccount);
-
- bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- exchange.addCoinConfigList(coinConfig);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- merchant.addExchange(exchange);
-
- await merchant.start();
- await merchant.pingUntilAvailable();
-
- await merchant.addInstance({
- id: "default",
- name: "Default Instance",
- paytoUris: [getPayto("merchant-default")],
- });
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- return {
- commonDb: db,
- exchange,
- merchant,
- wallet,
- bank,
- exchangeBankAccount,
- };
-}
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runWallettestingTest(t: GlobalTestState) {
- const { wallet, bank, exchange, merchant } = await createMyEnvironment(t);
-
- await wallet.client.call(WalletApiOperation.RunIntegrationTest, {
- amountToSpend: "TESTKUDOS:5",
- amountToWithdraw: "TESTKUDOS:10",
- bankBaseUrl: bank.baseUrl,
- bankAccessApiBaseUrl: bank.bankAccessApiBaseUrl,
- exchangeBaseUrl: exchange.baseUrl,
- merchantAuthToken: merchantAuthToken,
- merchantBaseUrl: merchant.makeInstanceBaseUrl(),
- });
-
- let txns = await wallet.client.call(WalletApiOperation.GetTransactions, {});
- console.log(JSON.stringify(txns, undefined, 2));
- let txTypes = txns.transactions.map((x) => x.type);
-
- t.assertDeepEqual(txTypes, [
- "withdrawal",
- "payment",
- "withdrawal",
- "payment",
- "refund",
- "payment",
- ]);
-
- wallet.deleteDatabase();
-
- await wallet.client.call(WalletApiOperation.WithdrawTestBalance, {
- amount: "TESTKUDOS:10",
- bankBaseUrl: bank.baseUrl,
- bankAccessApiBaseUrl: bank.bankAccessApiBaseUrl,
- exchangeBaseUrl: exchange.baseUrl,
- });
-
- await wallet.runUntilDone();
-
- await wallet.client.call(WalletApiOperation.TestPay, {
- amount: "TESTKUDOS:5",
- merchantAuthToken: merchantAuthToken,
- merchantBaseUrl: merchant.makeInstanceBaseUrl(),
- summary: "foo",
- });
-
- await wallet.runUntilDone();
-
- txns = await wallet.client.call(WalletApiOperation.GetTransactions, {});
- console.log(JSON.stringify(txns, undefined, 2));
- txTypes = txns.transactions.map((x) => x.type);
-
- t.assertDeepEqual(txTypes, ["withdrawal", "payment"]);
-
- wallet.deleteDatabase();
-
- await wallet.client.call(WalletApiOperation.WithdrawTestBalance, {
- amount: "TESTKUDOS:10",
- bankBaseUrl: bank.baseUrl,
- bankAccessApiBaseUrl: bank.bankAccessApiBaseUrl,
- exchangeBaseUrl: exchange.baseUrl,
- });
-
- await wallet.runUntilDone();
-
- const coinDump = await wallet.client.call(WalletApiOperation.DumpCoins, {});
-
- console.log("coin dump:", JSON.stringify(coinDump, undefined, 2));
-
- let susp: string | undefined;
- {
- for (const c of coinDump.coins) {
- if (
- c.coin_status === CoinStatus.Fresh &&
- 0 === Amounts.cmp(c.denom_value, "TESTKUDOS:8")
- ) {
- susp = c.coin_pub;
- }
- }
- }
-
- t.assertTrue(susp !== undefined);
-
- console.log("suspending coin");
-
- await wallet.client.call(WalletApiOperation.SetCoinSuspended, {
- coinPub: susp,
- suspended: true,
- });
-
- // This should fail, as we've suspended a coin that we need
- // to pay.
- await t.assertThrowsAsync(async () => {
- await wallet.client.call(WalletApiOperation.TestPay, {
- amount: "TESTKUDOS:5",
- merchantAuthToken: merchantAuthToken,
- merchantBaseUrl: merchant.makeInstanceBaseUrl(),
- summary: "foo",
- });
- });
-
- console.log("unsuspending coin");
-
- await wallet.client.call(WalletApiOperation.SetCoinSuspended, {
- coinPub: susp,
- suspended: false,
- });
-
- await wallet.client.call(WalletApiOperation.TestPay, {
- amount: "TESTKUDOS:5",
- merchantAuthToken: merchantAuthToken,
- merchantBaseUrl: merchant.makeInstanceBaseUrl(),
- summary: "foo",
- });
-
- await t.shutdown();
-}
-
-runWallettestingTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-abort-bank.ts b/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-abort-bank.ts
deleted file mode 100644
index bf2dc0133..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-abort-bank.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- 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 { TalerErrorCode } from "@gnu-taler/taler-util";
-import {
- WalletApiOperation,
- BankApi,
- BankAccessApi,
-} from "@gnu-taler/taler-wallet-core";
-import { GlobalTestState } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runWithdrawalAbortBankTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange } = await createSimpleTestkudosEnvironment(t);
-
- // Create a withdrawal operation
-
- const user = await BankApi.createRandomBankUser(bank);
- const wop = await BankAccessApi.createWithdrawalOperation(
- bank,
- user,
- "TESTKUDOS:10",
- );
-
- // Hand it to the wallet
-
- await wallet.client.call(WalletApiOperation.GetWithdrawalDetailsForUri, {
- talerWithdrawUri: wop.taler_withdraw_uri,
- });
-
- await wallet.runPending();
-
- // Abort it
-
- await BankApi.abortWithdrawalOperation(bank, user, wop);
- //await BankApi.confirmWithdrawalOperation(bank, user, wop);
-
- // Withdraw
-
- // Difference:
- // -> with euFin, the wallet selects
- // -> with PyBank, the wallet stops _before_
- //
- // WHY ?!
- //
- const e = await t.assertThrowsTalerErrorAsync(async () => {
- await wallet.client.call(
- WalletApiOperation.AcceptBankIntegratedWithdrawal,
- {
- exchangeBaseUrl: exchange.baseUrl,
- talerWithdrawUri: wop.taler_withdraw_uri,
- },
- );
- });
- t.assertDeepEqual(
- e.errorDetail.code,
- TalerErrorCode.WALLET_WITHDRAWAL_OPERATION_ABORTED_BY_BANK,
- );
-
- await t.shutdown();
-}
-
-runWithdrawalAbortBankTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-bank-integrated.ts b/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-bank-integrated.ts
deleted file mode 100644
index dc7298e5d..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-bank-integrated.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
-import {
- WalletApiOperation,
- BankApi,
- BankAccessApi,
-} from "@gnu-taler/taler-wallet-core";
-import { j2s } from "@gnu-taler/taler-util";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange } = await createSimpleTestkudosEnvironment(t);
-
- // Create a withdrawal operation
-
- const user = await BankApi.createRandomBankUser(bank);
- const wop = await BankAccessApi.createWithdrawalOperation(
- bank,
- user,
- "TESTKUDOS:10",
- );
-
- // Hand it to the wallet
-
- const r1 = await wallet.client.call(
- WalletApiOperation.GetWithdrawalDetailsForUri,
- {
- talerWithdrawUri: wop.taler_withdraw_uri,
- },
- );
-
- await wallet.runPending();
-
- // Withdraw
-
- const r2 = await wallet.client.call(
- WalletApiOperation.AcceptBankIntegratedWithdrawal,
- {
- exchangeBaseUrl: exchange.baseUrl,
- talerWithdrawUri: wop.taler_withdraw_uri,
- },
- );
- // Do it twice to check idempotency
- const r3 = await wallet.client.call(
- WalletApiOperation.AcceptBankIntegratedWithdrawal,
- {
- exchangeBaseUrl: exchange.baseUrl,
- talerWithdrawUri: wop.taler_withdraw_uri,
- },
- );
- await wallet.runPending();
-
- // Confirm it
-
- await BankApi.confirmWithdrawalOperation(bank, user, wop);
-
- await wallet.runUntilDone();
-
- // Check balance
-
- const balResp = await wallet.client.call(WalletApiOperation.GetBalances, {});
- t.assertAmountEquals("TESTKUDOS:9.72", balResp.balances[0].available);
-
- const txn = await wallet.client.call(WalletApiOperation.GetTransactions, {});
- console.log(`transactions: ${j2s(txn)}`);
-}
-
-runWithdrawalBankIntegratedTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-fakebank.ts b/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-fakebank.ts
deleted file mode 100644
index ec6e54e6c..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-fakebank.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- 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 {
- GlobalTestState,
- WalletCli,
- setupDb,
- ExchangeService,
- FakebankService,
-} from "../harness/harness.js";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
-import { URL } from "@gnu-taler/taler-util";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runWithdrawalFakebankTest(t: GlobalTestState) {
- // Set up test environment
-
- const db = await setupDb(t);
-
- const bank = await FakebankService.create(t, {
- currency: "TESTKUDOS",
- httpPort: 8082,
- allowRegistrations: true,
- // Not used by fakebank
- database: db.connStr,
- });
-
- const exchange = ExchangeService.create(t, {
- name: "testexchange-1",
- currency: "TESTKUDOS",
- httpPort: 8081,
- database: db.connStr,
- });
-
- exchange.addBankAccount("1", {
- accountName: "exchange",
- accountPassword: "x",
- wireGatewayApiBaseUrl: new URL("/exchange/", bank.baseUrl).href,
- accountPaytoUri: "payto://x-taler-bank/localhost/exchange",
- });
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- const coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS"));
- exchange.addCoinConfigList(coinConfig);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: exchange.baseUrl,
- });
-
- await wallet.client.call(WalletApiOperation.WithdrawFakebank, {
- exchange: exchange.baseUrl,
- amount: "TESTKUDOS:10",
- bank: bank.baseUrl,
- });
-
- await exchange.runWirewatchOnce();
-
- await wallet.runUntilDone();
-
- // Check balance
-
- const balResp = await wallet.client.call(WalletApiOperation.GetBalances, {});
- t.assertAmountEquals("TESTKUDOS:9.72", balResp.balances[0].available);
-
- await t.shutdown();
-}
-
-runWithdrawalFakebankTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-high.ts b/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-high.ts
deleted file mode 100644
index deb0e6dde..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-high.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- 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 {
- GlobalTestState,
- WalletCli,
- setupDb,
- ExchangeService,
- FakebankService,
-} from "../harness/harness.js";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
-import { URL } from "@gnu-taler/taler-util";
-
-/**
- * Withdraw a high amount. Mostly intended
- * as a perf test.
- */
-export async function runWithdrawalHighTest(t: GlobalTestState) {
- // Set up test environment
-
- const db = await setupDb(t);
-
- const bank = await FakebankService.create(t, {
- currency: "TESTKUDOS",
- httpPort: 8082,
- allowRegistrations: true,
- // Not used by fakebank
- database: db.connStr,
- });
-
- const exchange = ExchangeService.create(t, {
- name: "testexchange-1",
- currency: "TESTKUDOS",
- httpPort: 8081,
- database: db.connStr,
- });
-
- exchange.addBankAccount("1", {
- accountName: "exchange",
- accountPassword: "x",
- wireGatewayApiBaseUrl: new URL("/exchange/", bank.baseUrl).href,
- accountPaytoUri: "payto://x-taler-bank/localhost/exchange",
- });
-
- await bank.start();
-
- await bank.pingUntilAvailable();
-
- const coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS"));
- exchange.addCoinConfigList(coinConfig);
-
- await exchange.start();
- await exchange.pingUntilAvailable();
-
- console.log("setup done!");
-
- const wallet = new WalletCli(t);
-
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: exchange.baseUrl,
- });
-
- await wallet.client.call(WalletApiOperation.WithdrawFakebank, {
- exchange: exchange.baseUrl,
- amount: "TESTKUDOS:5000",
- bank: bank.baseUrl,
- });
-
- await exchange.runWirewatchOnce();
-
- await wallet.runUntilDone();
-
- // Check balance
-
- const balResp = await wallet.client.call(WalletApiOperation.GetBalances, {});
- console.log(balResp);
-
- await t.shutdown();
-}
-
-runWithdrawalHighTest.suites = ["wallet-perf"];
-runWithdrawalHighTest.excludeByDefault = true;
diff --git a/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-manual.ts b/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-manual.ts
deleted file mode 100644
index b691ae508..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/test-withdrawal-manual.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- 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 { GlobalTestState } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
-import { WalletApiOperation, BankApi } from "@gnu-taler/taler-wallet-core";
-import {
- AbsoluteTime,
- Duration,
- TalerProtocolTimestamp,
-} from "@gnu-taler/taler-util";
-
-/**
- * Run test for basic, bank-integrated withdrawal.
- */
-export async function runTestWithdrawalManualTest(t: GlobalTestState) {
- // Set up test environment
-
- const { wallet, bank, exchange, exchangeBankAccount } =
- await createSimpleTestkudosEnvironment(t);
-
- // Create a withdrawal operation
-
- const user = await BankApi.createRandomBankUser(bank);
-
- await wallet.client.call(WalletApiOperation.AddExchange, {
- exchangeBaseUrl: exchange.baseUrl,
- });
-
- const tStart = AbsoluteTime.now();
-
- // We expect this to return immediately.
- const wres = await wallet.client.call(
- WalletApiOperation.AcceptManualWithdrawal,
- {
- exchangeBaseUrl: exchange.baseUrl,
- amount: "TESTKUDOS:10",
- },
- );
-
- // Check that the request did not go into long-polling.
- const duration = AbsoluteTime.difference(tStart, AbsoluteTime.now());
- if (duration.d_ms > 5 * 1000) {
- throw Error("withdrawal took too long (longpolling issue)");
- }
-
- const reservePub: string = wres.reservePub;
-
- await BankApi.adminAddIncoming(bank, {
- exchangeBankAccount,
- amount: "TESTKUDOS:10",
- debitAccountPayto: user.accountPaytoUri,
- reservePub: reservePub,
- });
-
- await exchange.runWirewatchOnce();
-
- await wallet.runUntilDone();
-
- // Check balance
-
- const balResp = await wallet.client.call(WalletApiOperation.GetBalances, {});
- t.assertAmountEquals("TESTKUDOS:9.72", balResp.balances[0].available);
-
- await t.shutdown();
-}
-
-runTestWithdrawalManualTest.suites = ["wallet"];
diff --git a/packages/taler-wallet-cli/src/integrationtests/testrunner.ts b/packages/taler-wallet-cli/src/integrationtests/testrunner.ts
deleted file mode 100644
index 4b1c28bde..000000000
--- a/packages/taler-wallet-cli/src/integrationtests/testrunner.ts
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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/>
- */
-
-import { CancellationToken, minimatch } from "@gnu-taler/taler-util";
-import * as child_process from "child_process";
-import * as fs from "fs";
-import * as os from "os";
-import * as path from "path";
-import url from "url";
-import {
- GlobalTestState,
- runTestWithState,
- shouldLingerInTest,
- TestRunResult,
-} from "../harness/harness.js";
-import { runAgeRestrictionsMerchantTest } from "./test-age-restrictions-merchant.js";
-import { runBankApiTest } from "./test-bank-api.js";
-import { runClaimLoopTest } from "./test-claim-loop.js";
-import { runClauseSchnorrTest } from "./test-clause-schnorr.js";
-import { runDenomUnofferedTest } from "./test-denom-unoffered.js";
-import { runDepositTest } from "./test-deposit.js";
-import { runExchangeManagementTest } from "./test-exchange-management.js";
-import { runExchangeTimetravelTest } from "./test-exchange-timetravel.js";
-import { runFeeRegressionTest } from "./test-fee-regression.js";
-import { runForcedSelectionTest } from "./test-forced-selection.js";
-import { runLibeufinApiBankaccountTest } from "./test-libeufin-api-bankaccount.js";
-import { runLibeufinApiBankconnectionTest } from "./test-libeufin-api-bankconnection.js";
-import { runLibeufinApiFacadeTest } from "./test-libeufin-api-facade.js";
-import { runLibeufinApiFacadeBadRequestTest } from "./test-libeufin-api-facade-bad-request.js";
-import { runLibeufinApiPermissionsTest } from "./test-libeufin-api-permissions.js";
-import { runLibeufinApiSandboxCamtTest } from "./test-libeufin-api-sandbox-camt.js";
-import { runLibeufinApiSandboxTransactionsTest } from "./test-libeufin-api-sandbox-transactions.js";
-import { runLibeufinApiSchedulingTest } from "./test-libeufin-api-scheduling.js";
-import { runLibeufinApiUsersTest } from "./test-libeufin-api-users.js";
-import { runLibeufinBadGatewayTest } from "./test-libeufin-bad-gateway.js";
-import { runLibeufinBasicTest } from "./test-libeufin-basic.js";
-import { runLibeufinC5xTest } from "./test-libeufin-c5x.js";
-import { runLibeufinAnastasisFacadeTest } from "./test-libeufin-facade-anastasis.js";
-import { runLibeufinKeyrotationTest } from "./test-libeufin-keyrotation.js";
-import { runLibeufinNexusBalanceTest } from "./test-libeufin-nexus-balance.js";
-import { runLibeufinRefundTest } from "./test-libeufin-refund.js";
-import { runLibeufinRefundMultipleUsersTest } from "./test-libeufin-refund-multiple-users.js";
-import { runLibeufinSandboxWireTransferCliTest } from "./test-libeufin-sandbox-wire-transfer-cli.js";
-import { runLibeufinTutorialTest } from "./test-libeufin-tutorial.js";
-import { runMerchantExchangeConfusionTest } from "./test-merchant-exchange-confusion.js";
-import { runMerchantInstancesTest } from "./test-merchant-instances.js";
-import { runMerchantInstancesDeleteTest } from "./test-merchant-instances-delete.js";
-import { runMerchantInstancesUrlsTest } from "./test-merchant-instances-urls.js";
-import { runMerchantLongpollingTest } from "./test-merchant-longpolling.js";
-import { runMerchantRefundApiTest } from "./test-merchant-refund-api.js";
-import { runMerchantSpecPublicOrdersTest } from "./test-merchant-spec-public-orders.js";
-import { runPayPaidTest } from "./test-pay-paid.js";
-import { runPaymentTest } from "./test-payment.js";
-import { runPaymentClaimTest } from "./test-payment-claim.js";
-import { runPaymentFaultTest } from "./test-payment-fault.js";
-import { runPaymentForgettableTest } from "./test-payment-forgettable.js";
-import { runPaymentIdempotencyTest } from "./test-payment-idempotency.js";
-import { runPaymentMultipleTest } from "./test-payment-multiple.js";
-import { runPaymentDemoTest } from "./test-payment-on-demo.js";
-import { runPaymentTransientTest } from "./test-payment-transient.js";
-import { runPaymentZeroTest } from "./test-payment-zero.js";
-import { runPaywallFlowTest } from "./test-paywall-flow.js";
-import { runPeerToPeerPullTest } from "./test-peer-to-peer-pull.js";
-import { runPeerToPeerPushTest } from "./test-peer-to-peer-push.js";
-import { runRefundTest } from "./test-refund.js";
-import { runRefundAutoTest } from "./test-refund-auto.js";
-import { runRefundGoneTest } from "./test-refund-gone.js";
-import { runRefundIncrementalTest } from "./test-refund-incremental.js";
-import { runRevocationTest } from "./test-revocation.js";
-import { runTimetravelAutorefreshTest } from "./test-timetravel-autorefresh.js";
-import { runTimetravelWithdrawTest } from "./test-timetravel-withdraw.js";
-import { runTippingTest } from "./test-tipping.js";
-import { runWalletBackupBasicTest } from "./test-wallet-backup-basic.js";
-import { runWalletBackupDoublespendTest } from "./test-wallet-backup-doublespend.js";
-import { runWalletDblessTest } from "./test-wallet-dbless.js";
-import { runWallettestingTest } from "./test-wallettesting.js";
-import { runWithdrawalAbortBankTest } from "./test-withdrawal-abort-bank.js";
-import { runWithdrawalBankIntegratedTest } from "./test-withdrawal-bank-integrated.js";
-import { runWithdrawalFakebankTest } from "./test-withdrawal-fakebank.js";
-import { runTestWithdrawalManualTest } from "./test-withdrawal-manual.js";
-import { runAgeRestrictionsPeerTest } from "./test-age-restrictions-peer.js";
-import { runWalletBalanceTest } from "./test-wallet-balance.js";
-import { runAgeRestrictionsMixedMerchantTest } from "./test-age-restrictions-mixed-merchant.js";
-import { runWalletCryptoWorkerTest } from "./test-wallet-cryptoworker.js";
-import { runWithdrawalHighTest } from "./test-withdrawal-high.js";
-
-/**
- * Test runner.
- */
-
-/**
- * Spec for one test.
- */
-interface TestMainFunction {
- (t: GlobalTestState): Promise<void>;
- timeoutMs?: number;
- excludeByDefault?: boolean;
- suites?: string[];
-}
-
-const allTests: TestMainFunction[] = [
- runAgeRestrictionsMerchantTest,
- runAgeRestrictionsPeerTest,
- runAgeRestrictionsMixedMerchantTest,
- runBankApiTest,
- runClaimLoopTest,
- runClauseSchnorrTest,
- runWalletCryptoWorkerTest,
- runDepositTest,
- runDenomUnofferedTest,
- runExchangeManagementTest,
- runExchangeTimetravelTest,
- runFeeRegressionTest,
- runForcedSelectionTest,
- runLibeufinBasicTest,
- runLibeufinKeyrotationTest,
- runLibeufinTutorialTest,
- runLibeufinRefundTest,
- runLibeufinC5xTest,
- runLibeufinNexusBalanceTest,
- runLibeufinBadGatewayTest,
- runLibeufinRefundMultipleUsersTest,
- runLibeufinApiPermissionsTest,
- runLibeufinApiFacadeTest,
- runLibeufinApiFacadeBadRequestTest,
- runLibeufinAnastasisFacadeTest,
- runLibeufinApiSchedulingTest,
- runLibeufinApiUsersTest,
- runLibeufinApiBankaccountTest,
- runLibeufinApiBankconnectionTest,
- runLibeufinApiSandboxTransactionsTest,
- runLibeufinApiSandboxCamtTest,
- runLibeufinSandboxWireTransferCliTest,
- runMerchantExchangeConfusionTest,
- runMerchantInstancesTest,
- runMerchantInstancesDeleteTest,
- runMerchantInstancesUrlsTest,
- runMerchantLongpollingTest,
- runMerchantSpecPublicOrdersTest,
- runMerchantRefundApiTest,
- runPaymentClaimTest,
- runPaymentFaultTest,
- runPaymentForgettableTest,
- runPaymentIdempotencyTest,
- runPaymentMultipleTest,
- runPaymentTest,
- runPaymentDemoTest,
- runPaymentTransientTest,
- runPaymentZeroTest,
- runPayPaidTest,
- runPaywallFlowTest,
- runPeerToPeerPushTest,
- runPeerToPeerPullTest,
- runRefundAutoTest,
- runRefundGoneTest,
- runRefundIncrementalTest,
- runRefundTest,
- runRevocationTest,
- runTestWithdrawalManualTest,
- runWithdrawalFakebankTest,
- runTimetravelAutorefreshTest,
- runTimetravelWithdrawTest,
- runTippingTest,
- runWalletBackupBasicTest,
- runWalletBackupDoublespendTest,
- runWalletBalanceTest,
- runWithdrawalHighTest,
- runWallettestingTest,
- runWalletDblessTest,
- runWithdrawalAbortBankTest,
- runWithdrawalBankIntegratedTest,
-];
-
-export interface TestRunSpec {
- includePattern?: string;
- suiteSpec?: string;
- dryRun?: boolean;
- verbosity: number;
-}
-
-export interface TestInfo {
- name: string;
- suites: string[];
- excludeByDefault: boolean;
-}
-
-function updateCurrentSymlink(testDir: string): void {
- const currLink = path.join(
- os.tmpdir(),
- `taler-integrationtests-${os.userInfo().username}-current`,
- );
- try {
- fs.unlinkSync(currLink);
- } catch (e) {
- // Ignore
- }
- try {
- fs.symlinkSync(testDir, currLink);
- } catch (e) {
- console.log(e);
- // Ignore
- }
-}
-
-export function getTestName(tf: TestMainFunction): string {
- const res = tf.name.match(/run([a-zA-Z0-9]*)Test/);
- if (!res) {
- throw Error("invalid test name, must be 'run${NAME}Test'");
- }
- return res[1]
- .replace(/[a-z0-9][A-Z]/g, (x) => {
- return x[0] + "-" + x[1];
- })
- .toLowerCase();
-}
-
-interface RunTestChildInstruction {
- testName: string;
- testRootDir: string;
-}
-
-export async function runTests(spec: TestRunSpec) {
- const testRootDir = fs.mkdtempSync(
- path.join(os.tmpdir(), "taler-integrationtests-"),
- );
- updateCurrentSymlink(testRootDir);
- console.log(`testsuite root directory: ${testRootDir}`);
-
- const testResults: TestRunResult[] = [];
-
- let currentChild: child_process.ChildProcess | undefined;
-
- const handleSignal = (s: NodeJS.Signals) => {
- console.log(`received signal ${s} in test parent`);
- if (currentChild) {
- currentChild.kill("SIGTERM");
- }
- reportAndQuit(testRootDir, testResults, true);
- };
-
- process.on("SIGINT", (s) => handleSignal(s));
- process.on("SIGTERM", (s) => handleSignal(s));
- //process.on("unhandledRejection", handleSignal);
- //process.on("uncaughtException", handleSignal);
-
- let suites: Set<string> | undefined;
-
- if (spec.suiteSpec) {
- suites = new Set(spec.suiteSpec.split(",").map((x) => x.trim()));
- }
-
- for (const [n, testCase] of allTests.entries()) {
- const testName = getTestName(testCase);
- if (spec.includePattern && !minimatch(testName, spec.includePattern)) {
- continue;
- }
-
- if (suites) {
- const ts = new Set(testCase.suites ?? []);
- const intersection = new Set([...suites].filter((x) => ts.has(x)));
- if (intersection.size === 0) {
- continue;
- }
- } else {
- if (testCase.excludeByDefault) {
- continue;
- }
- }
-
- if (spec.dryRun) {
- console.log(`dry run: would run test ${testName}`);
- continue;
- }
-
- const testInstr: RunTestChildInstruction = {
- testName,
- testRootDir,
- };
-
- const myFilename = url.fileURLToPath(import.meta.url);
-
- currentChild = child_process.fork(myFilename, ["__TWCLI_TESTWORKER"], {
- env: {
- TWCLI_RUN_TEST_INSTRUCTION: JSON.stringify(testInstr),
- ...process.env,
- },
- stdio: ["pipe", "pipe", "pipe", "ipc"],
- });
-
- const testDir = path.join(testRootDir, testName);
- fs.mkdirSync(testDir, { recursive: true });
-
- const harnessLogFilename = path.join(testRootDir, testName, "harness.log");
- const harnessLogStream = fs.createWriteStream(harnessLogFilename);
-
- if (spec.verbosity > 0) {
- currentChild.stderr?.pipe(process.stderr);
- currentChild.stdout?.pipe(process.stdout);
- }
-
- currentChild.stdout?.pipe(harnessLogStream);
- currentChild.stderr?.pipe(harnessLogStream);
-
- const defaultTimeout = 60000;
- const testTimeoutMs = testCase.timeoutMs ?? defaultTimeout;
-
- console.log(`running ${testName} with timeout ${testTimeoutMs}ms`);
-
- const { token } = CancellationToken.timeout(testTimeoutMs);
-
- const resultPromise: Promise<TestRunResult> = new Promise(
- (resolve, reject) => {
- let msg: TestRunResult | undefined;
- currentChild!.on("message", (m) => {
- if (token.isCancelled) {
- return;
- }
- msg = m as TestRunResult;
- });
- currentChild!.on("exit", (code, signal) => {
- if (token.isCancelled) {
- return;
- }
- console.log(`process exited code=${code} signal=${signal}`);
- if (signal) {
- reject(new Error(`test worker exited with signal ${signal}`));
- } else if (code != 0) {
- reject(new Error(`test worker exited with code ${code}`));
- } else if (!msg) {
- reject(
- new Error(
- `test worker exited without giving back the test results`,
- ),
- );
- } else {
- resolve(msg);
- }
- });
- currentChild!.on("error", (err) => {
- if (token.isCancelled) {
- return;
- }
- reject(err);
- });
- },
- );
-
- let result: TestRunResult;
-
- try {
- result = await token.racePromise(resultPromise);
- } catch (e: any) {
- console.error(`test ${testName} timed out`);
- if (token.isCancelled) {
- result = {
- status: "fail",
- reason: "timeout",
- timeSec: testTimeoutMs / 1000,
- name: testName,
- };
- currentChild.kill("SIGTERM");
- } else {
- throw Error(e);
- }
- }
-
- harnessLogStream.close();
-
- console.log(`parent: got result ${JSON.stringify(result)}`);
-
- testResults.push(result);
- }
-
- reportAndQuit(testRootDir, testResults);
-}
-
-export function reportAndQuit(
- testRootDir: string,
- testResults: TestRunResult[],
- interrupted: boolean = false,
-): never {
- let numTotal = 0;
- let numFail = 0;
- let numSkip = 0;
- let numPass = 0;
-
- for (const result of testResults) {
- numTotal++;
- if (result.status === "fail") {
- numFail++;
- } else if (result.status === "skip") {
- numSkip++;
- } else if (result.status === "pass") {
- numPass++;
- }
- }
-
- const resultsFile = path.join(testRootDir, "results.json");
- fs.writeFileSync(
- path.join(testRootDir, "results.json"),
- JSON.stringify({ testResults, interrupted }, undefined, 2),
- );
- if (interrupted) {
- console.log("test suite was interrupted");
- }
- console.log(`See ${resultsFile} for details`);
- console.log(`Skipped: ${numSkip}/${numTotal}`);
- console.log(`Failed: ${numFail}/${numTotal}`);
- console.log(`Passed: ${numPass}/${numTotal}`);
-
- if (interrupted) {
- process.exit(3);
- } else if (numPass < numTotal - numSkip) {
- process.exit(1);
- } else {
- process.exit(0);
- }
-}
-
-export function getTestInfo(): TestInfo[] {
- return allTests.map((x) => ({
- name: getTestName(x),
- suites: x.suites ?? [],
- excludeByDefault: x.excludeByDefault ?? false,
- }));
-}
-
-const runTestInstrStr = process.env["TWCLI_RUN_TEST_INSTRUCTION"];
-if (runTestInstrStr && process.argv.includes("__TWCLI_TESTWORKER")) {
- // Test will call taler-wallet-cli, so we must not propagate this variable.
- delete process.env["TWCLI_RUN_TEST_INSTRUCTION"];
- const { testRootDir, testName } = JSON.parse(
- runTestInstrStr,
- ) as RunTestChildInstruction;
- console.log(`running test ${testName} in worker process`);
-
- process.on("disconnect", () => {
- console.log("got disconnect from parent");
- process.exit(3);
- });
-
- const runTest = async () => {
- let testMain: TestMainFunction | undefined;
- for (const t of allTests) {
- if (getTestName(t) === testName) {
- testMain = t;
- break;
- }
- }
-
- if (!process.send) {
- console.error("can't communicate with parent");
- process.exit(2);
- }
-
- if (!testMain) {
- console.log(`test ${testName} not found`);
- process.exit(2);
- }
-
- const testDir = path.join(testRootDir, testName);
- console.log(`running test ${testName}`);
- const gc = new GlobalTestState({
- testDir,
- });
- const testResult = await runTestWithState(gc, testMain, testName);
- process.send(testResult);
- };
-
- runTest()
- .then(() => {
- console.log(`test ${testName} finished in worker`);
- if (shouldLingerInTest()) {
- console.log("lingering ...");
- return;
- }
- process.exit(0);
- })
- .catch((e) => {
- console.log(e);
- process.exit(1);
- });
-}
diff --git a/packages/taler-wallet-cli/src/lint.ts b/packages/taler-wallet-cli/src/lint.ts
deleted file mode 100644
index 49fb9dc86..000000000
--- a/packages/taler-wallet-cli/src/lint.ts
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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/>
- */
-
-/**
- * The deployment linter implements checks for a deployment
- * of the GNU Taler exchange. It is meant to help sysadmins
- * when setting up an exchange.
- *
- * The linter does checks in the configuration and uses
- * various tools of the exchange in test mode (-t).
- *
- * To be able to run the tools as the right user, the linter should be
- * run as root.
- *
- * @author Florian Dold <dold@taler.net>
- */
-
-/**
- * Imports.
- */
-import {
- codecForExchangeKeysJson,
- codecForKeysManagementResponse,
- Configuration,
- decodeCrock,
-} from "@gnu-taler/taler-util";
-import {
- NodeHttpLib,
- readSuccessResponseJsonOrThrow,
-} from "@gnu-taler/taler-wallet-core";
-import { URL } from "url";
-import { spawn } from "child_process";
-import { delayMs } from "./harness/harness.js";
-
-interface BasicConf {
- mainCurrency: string;
-}
-
-interface PubkeyConf {
- masterPublicKey: string;
-}
-
-const httpLib = new NodeHttpLib();
-
-interface ShellResult {
- stdout: string;
- stderr: string;
- status: number;
-}
-
-interface LintContext {
- /**
- * Be more verbose.
- */
- verbose: boolean;
-
- /**
- * Always continue even after errors.
- */
- cont: boolean;
-
- cfg: Configuration;
-
- numErr: number;
-}
-
-/**
- * Run a shell command, return stdout.
- */
-export async function sh(
- context: LintContext,
- command: string,
- env: { [index: string]: string | undefined } = process.env,
-): Promise<ShellResult> {
- if (context.verbose) {
- console.log("executing command:", command);
- }
- return new Promise((resolve, reject) => {
- const stdoutChunks: Buffer[] = [];
- const stderrChunks: Buffer[] = [];
- const proc = spawn(command, {
- stdio: ["inherit", "pipe", "pipe"],
- shell: true,
- env: env,
- });
- proc.stdout.on("data", (x) => {
- if (x instanceof Buffer) {
- stdoutChunks.push(x);
- } else {
- throw Error("unexpected data chunk type");
- }
- });
- proc.stderr.on("data", (x) => {
- if (x instanceof Buffer) {
- stderrChunks.push(x);
- } else {
- throw Error("unexpected data chunk type");
- }
- });
- proc.on("exit", (code, signal) => {
- if (code != 0 && context.verbose) {
- console.log(`child process exited (${code} / ${signal})`);
- }
- const bOut = Buffer.concat(stdoutChunks).toString("utf-8");
- const bErr = Buffer.concat(stderrChunks).toString("utf-8");
- resolve({
- status: code ?? -1,
- stderr: bErr,
- stdout: bOut,
- });
- });
- proc.on("error", () => {
- reject(Error("Child process had error"));
- });
- });
-}
-
-function checkBasicConf(context: LintContext): BasicConf {
- const cfg = context.cfg;
- const currencyEntry = cfg.getString("taler", "currency");
- let mainCurrency: string | undefined;
-
- if (!currencyEntry.value) {
- context.numErr++;
- console.log("error: currency not defined in section TALER option CURRENCY");
- console.log("Aborting further checks.");
- process.exit(1);
- } else {
- mainCurrency = currencyEntry.value.toUpperCase();
- }
-
- if (mainCurrency === "KUDOS") {
- console.log(
- "warning: section TALER option CURRENCY contains toy currency value KUDOS",
- );
- }
-
- const roundUnit = cfg.getAmount("taler", "currency_round_unit");
- const ru = roundUnit.required();
- if (ru.currency.toLowerCase() != mainCurrency.toLowerCase()) {
- context.numErr++;
- console.log(
- "error: [TALER]/CURRENCY_ROUND_UNIT: currency does not match main currency",
- );
- }
- return { mainCurrency };
-}
-
-function checkCoinConfig(context: LintContext, basic: BasicConf): void {
- const cfg = context.cfg;
- const coinPrefix1 = "COIN_";
- const coinPrefix2 = "COIN-";
- let numCoins = 0;
-
- for (const secName of cfg.getSectionNames()) {
- if (!(secName.startsWith(coinPrefix1) || secName.startsWith(coinPrefix2))) {
- continue;
- }
- numCoins++;
-
- // FIXME: check that section is well-formed
- }
-
- if (numCoins == 0) {
- context.numErr++;
- console.log(
- "error: no coin denomination configured, please configure [coin-*] sections",
- );
- }
-}
-
-async function checkWireConfig(context: LintContext): Promise<void> {
- const cfg = context.cfg;
- const accountPrefix = "EXCHANGE-ACCOUNT-";
- const accountCredentialsPrefix = "EXCHANGE-ACCOUNTCREDENTIALS-";
-
- let accounts = new Set<string>();
- let credentials = new Set<string>();
-
- for (const secName of cfg.getSectionNames()) {
- if (secName.startsWith(accountPrefix)) {
- accounts.add(secName.slice(accountPrefix.length));
- // FIXME: check settings
- }
-
- if (secName.startsWith(accountCredentialsPrefix)) {
- credentials.add(secName.slice(accountCredentialsPrefix.length));
- // FIXME: check settings
- }
- }
-
- if (accounts.size === 0) {
- context.numErr++;
- console.log(
- "error: No accounts configured (no sections EXCHANGE-ACCOUNT-*).",
- );
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
-
- for (const acc of accounts) {
- if (!credentials.has(acc)) {
- console.log(
- `warning: no credentials configured for exchange-account-${acc}`,
- );
- }
- }
-
- for (const acc of accounts) {
- // test credit history
- {
- const res = await sh(
- context,
- "su -l --shell /bin/sh " +
- `-c 'taler-exchange-wire-gateway-client -s exchange-accountcredentials-${acc} --credit-history' ` +
- "taler-exchange-wire",
- );
- if (res.status != 0) {
- context.numErr++;
- console.log(res.stdout);
- console.log(res.stderr);
- console.log(
- "error: Could not run taler-exchange-wire-gateway-client. Please review logs above.",
- );
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
- }
- }
-
- // TWG client
- {
- const res = await sh(
- context,
- `su -l --shell /bin/sh -c 'taler-exchange-wirewatch -t' taler-exchange-wire`,
- );
- if (res.status != 0) {
- context.numErr++;
- console.log(res.stdout);
- console.log(res.stderr);
- console.log("error: Could not run wirewatch. Please review logs above.");
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
- }
-
- // Wirewatch
- {
- const res = await sh(
- context,
- `su -l --shell /bin/sh -c 'taler-exchange-wirewatch -t' taler-exchange-wire`,
- );
- if (res.status != 0) {
- context.numErr++;
- console.log(res.stdout);
- console.log(res.stderr);
- console.log("error: Could not run wirewatch. Please review logs above.");
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
- }
-
- // Closer
- {
- const res = await sh(
- context,
- `su -l --shell /bin/sh -c 'taler-exchange-closer -t' taler-exchange-closer`,
- );
- if (res.status != 0) {
- context.numErr++;
- console.log(res.stdout);
- console.log(res.stderr);
- console.log("error: Could not run closer. Please review logs above.");
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
- }
-}
-
-async function checkAggregatorConfig(context: LintContext) {
- const res = await sh(
- context,
- "su -l --shell /bin/sh -c 'taler-exchange-aggregator -t' taler-exchange-aggregator",
- );
- if (res.status != 0) {
- context.numErr++;
- console.log(res.stdout);
- console.log(res.stderr);
- console.log("error: Could not run aggregator. Please review logs above.");
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
-}
-
-async function checkCloserConfig(context: LintContext) {
- const res = await sh(
- context,
- `su -l --shell /bin/sh -c 'taler-exchange-closer -t' taler-exchange-closer`,
- );
- if (res.status != 0) {
- context.numErr++;
- console.log(res.stdout);
- console.log(res.stderr);
- console.log("error: Could not run closer. Please review logs above.");
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
-}
-
-function checkMasterPublicKeyConfig(context: LintContext): PubkeyConf {
- const cfg = context.cfg;
- const pub = cfg.getString("exchange", "master_public_key");
-
- const pubDecoded = decodeCrock(pub.required());
-
- if (pubDecoded.length != 32) {
- context.numErr++;
- console.log("error: invalid master public key");
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
-
- return {
- masterPublicKey: pub.required(),
- };
-}
-
-export async function checkExchangeHttpd(
- context: LintContext,
- pubConf: PubkeyConf,
-): Promise<void> {
- const cfg = context.cfg;
- const baseUrlEntry = cfg.getString("exchange", "base_url");
-
- if (!baseUrlEntry.isDefined) {
- context.numErr++;
- console.log(
- "error: configuration needs to specify section EXCHANGE option BASE_URL",
- );
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
-
- const baseUrl = baseUrlEntry.required();
-
- if (!baseUrl.startsWith("http")) {
- context.numErr++;
- console.log(
- "error: section EXCHANGE option BASE_URL needs to be an http or https URL",
- );
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
-
- if (!baseUrl.endsWith("/")) {
- context.numErr++;
- console.log(
- "error: section EXCHANGE option BASE_URL needs to end with a slash",
- );
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
-
- if (!baseUrl.startsWith("https://")) {
- console.log(
- "warning: section EXCHANGE option BASE_URL: it is recommended to serve the exchange via HTTPS",
- );
- }
-
- {
- const mgmtUrl = new URL("management/keys", baseUrl);
- const resp = await httpLib.get(mgmtUrl.href);
-
- const futureKeys = await readSuccessResponseJsonOrThrow(
- resp,
- codecForKeysManagementResponse(),
- );
-
- if (futureKeys.future_denoms.length > 0) {
- console.log(
- `warning: exchange has denomination keys that need to be signed by the offline signing procedure`,
- );
- }
-
- if (futureKeys.future_signkeys.length > 0) {
- console.log(
- `warning: exchange has signing keys that need to be signed by the offline signing procedure`,
- );
- }
- }
-
- // Check if we can use /keys already
- {
- const keysUrl = new URL("keys", baseUrl);
-
- const resp = await Promise.race([httpLib.get(keysUrl.href), delayMs(2000)]);
-
- if (!resp) {
- context.numErr++;
- console.log(
- "error: request to /keys timed out. " +
- "Make sure to sign and upload denomination and signing keys " +
- "with taler-exchange-offline.",
- );
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- } else {
- const keys = await readSuccessResponseJsonOrThrow(
- resp,
- codecForExchangeKeysJson(),
- );
-
- if (keys.master_public_key !== pubConf.masterPublicKey) {
- context.numErr++;
- console.log(
- "error: master public key of exchange does not match public key of live exchange",
- );
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- }
- }
- }
-
- // Check /wire
- {
- const keysUrl = new URL("wire", baseUrl);
-
- const resp = await Promise.race([httpLib.get(keysUrl.href), delayMs(2000)]);
-
- if (!resp) {
- context.numErr++;
- console.log(
- "error: request to /wire timed out. " +
- "Make sure to sign and upload accounts and wire fees " +
- "using the taler-exchange-offline tool.",
- );
- if (!context.cont) {
- console.log("Aborting further checks.");
- process.exit(1);
- }
- } else {
- if (resp.status !== 200) {
- console.log(
- "error: Can't access exchange /wire. Please check " +
- "the logs of taler-exchange-httpd for further information.",
- );
- }
- }
- }
-}
-
-/**
- * Do some basic checks in the configuration of a Taler deployment.
- */
-export async function lintExchangeDeployment(
- verbose: boolean,
- cont: boolean,
-): Promise<void> {
- if (process.getuid!() != 0) {
- console.log(
- "warning: the exchange deployment linter is designed to be run as root",
- );
- }
-
- const cfg = Configuration.load();
-
- const context: LintContext = {
- cont,
- verbose,
- cfg,
- numErr: 0,
- };
-
- const basic = checkBasicConf(context);
-
- checkCoinConfig(context, basic);
-
- await checkWireConfig(context);
-
- await checkAggregatorConfig(context);
-
- await checkCloserConfig(context);
-
- const pubConf = checkMasterPublicKeyConfig(context);
-
- await checkExchangeHttpd(context, pubConf);
-
- if (context.numErr == 0) {
- console.log("Linting completed without errors.");
- process.exit(0);
- } else {
- console.log(`Linting completed with ${context.numErr} errors.`);
- process.exit(1);
- }
-}