aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÖzgür Kesim <oec-taler@kesim.org>2023-08-25 13:24:30 +0200
committerÖzgür Kesim <oec-taler@kesim.org>2023-08-25 13:24:30 +0200
commita58f73ecdb995e02a770338aa8a8aa529ccfdfaa (patch)
treee1f329bb59ffd1fa4419241cf3bc849738103b54
parent5ab3070b3a63c2e8fed0e413dea06cf03fb48f1e (diff)
parent896841aec5dc3594d83cc300349d20ec2270f88e (diff)
Merge branch 'master' into age-withdraw
-rw-r--r--packages/demobank-ui/src/components/app.tsx6
-rw-r--r--packages/taler-harness/src/harness/harness.ts188
-rw-r--r--packages/taler-harness/src/harness/helpers.ts197
-rw-r--r--packages/taler-harness/src/index.ts45
-rw-r--r--packages/taler-harness/src/integrationtests/test-age-restrictions-mixed-merchant.ts64
-rw-r--r--packages/taler-harness/src/integrationtests/test-bank-api.ts21
-rw-r--r--packages/taler-harness/src/integrationtests/test-claim-loop.ts21
-rw-r--r--packages/taler-harness/src/integrationtests/test-denom-unoffered.ts40
-rw-r--r--packages/taler-harness/src/integrationtests/test-exchange-deposit.ts7
-rw-r--r--packages/taler-harness/src/integrationtests/test-fee-regression.ts40
-rw-r--r--packages/taler-harness/src/integrationtests/test-forced-selection.ts16
-rw-r--r--packages/taler-harness/src/integrationtests/test-libeufin-api-bankaccount.ts1
-rw-r--r--packages/taler-harness/src/integrationtests/test-libeufin-nexus-balance.ts1
-rw-r--r--packages/taler-harness/src/integrationtests/test-merchant-instances-urls.ts8
-rw-r--r--packages/taler-harness/src/integrationtests/test-merchant-longpolling.ts33
-rw-r--r--packages/taler-harness/src/integrationtests/test-payment-abort.ts1
-rw-r--r--packages/taler-harness/src/integrationtests/test-payment-claim.ts24
-rw-r--r--packages/taler-harness/src/integrationtests/test-payment-forgettable.ts26
-rw-r--r--packages/taler-harness/src/integrationtests/test-payment-idempotency.ts29
-rw-r--r--packages/taler-harness/src/integrationtests/test-payment-share.ts14
-rw-r--r--packages/taler-harness/src/integrationtests/test-payment-template.ts20
-rw-r--r--packages/taler-harness/src/integrationtests/test-payment-zero.ts22
-rw-r--r--packages/taler-harness/src/integrationtests/test-paywall-flow.ts73
-rw-r--r--packages/taler-harness/src/integrationtests/test-refund-auto.ts30
-rw-r--r--packages/taler-harness/src/integrationtests/test-refund-incremental.ts68
-rw-r--r--packages/taler-harness/src/integrationtests/test-revocation.ts1
-rw-r--r--packages/taler-harness/src/integrationtests/test-simple-payment.ts7
-rw-r--r--packages/taler-harness/src/integrationtests/test-tipping.ts32
-rw-r--r--packages/taler-harness/src/integrationtests/test-tos-format.ts101
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-backup-basic.ts36
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-backup-doublespend.ts35
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-balance.ts81
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-dbless.ts4
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-notifications.ts23
-rw-r--r--packages/taler-harness/src/integrationtests/test-withdrawal-abort-bank.ts18
-rw-r--r--packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts20
-rw-r--r--packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts15
-rw-r--r--packages/taler-harness/src/integrationtests/test-withdrawal-huge.ts9
-rw-r--r--packages/taler-harness/src/integrationtests/test-withdrawal-manual.ts27
-rw-r--r--packages/taler-harness/src/integrationtests/testrunner.ts4
-rw-r--r--packages/taler-harness/src/sandcastle-config.ts10
-rw-r--r--packages/taler-util/src/logging.ts10
-rw-r--r--packages/taler-util/src/talerconfig.ts193
-rw-r--r--packages/taler-wallet-core/src/bank-api-client.ts153
44 files changed, 1244 insertions, 530 deletions
diff --git a/packages/demobank-ui/src/components/app.tsx b/packages/demobank-ui/src/components/app.tsx
index d65398765..ea86da518 100644
--- a/packages/demobank-ui/src/components/app.tsx
+++ b/packages/demobank-ui/src/components/app.tsx
@@ -15,7 +15,7 @@
*/
import {
- globalLogLevel,
+ getGlobalLogLevel,
setGlobalLogLevelFromString,
} from "@gnu-taler/taler-util";
import { TranslationProvider } from "@gnu-taler/web-util/browser";
@@ -62,9 +62,7 @@ const App: FunctionalComponent = () => {
);
};
(window as any).setGlobalLogLevelFromString = setGlobalLogLevelFromString;
-(window as any).getGlobaLevel = () => {
- return globalLogLevel;
-};
+(window as any).getGlobalLevel = getGlobalLogLevel;
function localStorageProvider(): Map<unknown, unknown> {
const map = new Map(JSON.parse(localStorage.getItem("app-cache") || "[]"));
diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts
index c9202c60e..926a0c93b 100644
--- a/packages/taler-harness/src/harness/harness.ts
+++ b/packages/taler-harness/src/harness/harness.ts
@@ -467,12 +467,29 @@ export async function setupDb(t: GlobalTestState): Promise<DbInfo> {
};
}
+/**
+ * Make sure that the taler-integrationtest-shared database exists.
+ * Don't delete it if it already exists.
+ */
+export async function setupSharedDb(t: GlobalTestState): Promise<DbInfo> {
+ const dbname = "taler-integrationtest-shared";
+ const databases = await runCommand(t, "list-dbs", "psql", ["-Aqtl"]);
+ if (databases.indexOf("taler-integrationtest-shared") < 0) {
+ await runCommand(t, "createdb", "createdb", [dbname]);
+ }
+ return {
+ connStr: `postgres:///${dbname}`,
+ dbname,
+ };
+}
+
export interface BankConfig {
currency: string;
httpPort: number;
database: string;
allowRegistrations: boolean;
maxDebt?: string;
+ overrideTestDir?: string;
}
export interface FakeBankConfig {
@@ -518,6 +535,14 @@ function setCoin(config: Configuration, c: CoinConfig) {
}
}
+function backoffStart(): number {
+ return 10;
+}
+
+function backoffIncrement(n: number): number {
+ return Math.min(Math.floor(n * 1.5), 1000);
+}
+
/**
* Send an HTTP request until it succeeds or the process dies.
*/
@@ -529,6 +554,7 @@ export async function pingProc(
if (!proc || proc.proc.exitCode !== null) {
throw Error(`service process ${serviceName} not started, can't ping`);
}
+ let nextDelay = backoffStart();
while (true) {
try {
logger.trace(`pinging ${serviceName} at ${url}`);
@@ -537,8 +563,9 @@ export async function pingProc(
return;
} catch (e: any) {
logger.warn(`service ${serviceName} not ready:`, e.toString());
- //console.log(e);
- await delayMs(1000);
+ logger.info(`waiting ${nextDelay}ms on ${serviceName}`);
+ await delayMs(nextDelay);
+ nextDelay = backoffIncrement(nextDelay);
}
if (!proc || proc.proc.exitCode != null || proc.proc.signalCode != null) {
throw Error(`service process ${serviceName} stopped unexpectedly`);
@@ -857,31 +884,57 @@ export class FakebankService
accountPassword: string;
}[] = [];
+ /**
+ * Create a new fakebank service handle.
+ *
+ * First generates the configuration for the fakebank and
+ * then creates a fakebank handle, but doesn't start the fakebank
+ * service yet.
+ */
static async create(
gc: GlobalTestState,
bc: BankConfig,
): Promise<FakebankService> {
const config = new Configuration();
- setTalerPaths(config, gc.testDir + "/talerhome");
+ const testDir = bc.overrideTestDir ?? gc.testDir;
+ setTalerPaths(config, 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);
+ const cfgFilename = testDir + "/bank.conf";
+ config.write(cfgFilename, { excludeDefaults: true });
return new FakebankService(gc, bc, cfgFilename);
}
+ static fromExistingConfig(
+ gc: GlobalTestState,
+ opts: { overridePath?: string },
+ ): FakebankService {
+ const testDir = opts.overridePath ?? gc.testDir;
+ const cfgFilename = testDir + `/bank.conf`;
+ const config = Configuration.load(cfgFilename);
+ const bc: BankConfig = {
+ allowRegistrations:
+ config.getYesNo("bank", "allow_registrations").orUndefined() ?? true,
+ currency: config.getString("taler", "currency").required(),
+ database: "none",
+ httpPort: config.getNumber("bank", "http_port").required(),
+ maxDebt: config.getString("bank", "max_debt").required(),
+ };
+ 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);
+ config.write(this.configFile, { excludeDefaults: true });
}
get baseUrl(): string {
@@ -958,6 +1011,7 @@ export interface ExchangeConfig {
roundUnit?: string;
httpPort: number;
database: string;
+ overrideTestDir?: string;
}
export interface ExchangeServiceInterface {
@@ -968,8 +1022,13 @@ export interface ExchangeServiceInterface {
}
export class ExchangeService implements ExchangeServiceInterface {
- static fromExistingConfig(gc: GlobalTestState, exchangeName: string) {
- const cfgFilename = gc.testDir + `/exchange-${exchangeName}.conf`;
+ static fromExistingConfig(
+ gc: GlobalTestState,
+ exchangeName: string,
+ opts: { overridePath?: string },
+ ) {
+ const testDir = opts.overridePath ?? gc.testDir;
+ const cfgFilename = testDir + `/exchange-${exchangeName}.conf`;
const config = Configuration.load(cfgFilename);
const ec: ExchangeConfig = {
currency: config.getString("taler", "currency").required(),
@@ -978,7 +1037,9 @@ export class ExchangeService implements ExchangeServiceInterface {
name: exchangeName,
roundUnit: config.getString("taler", "currency_round_unit").required(),
};
- const privFile = config.getPath("exchange", "master_priv_file").required();
+ const privFile = config
+ .getPath("exchange-offline", "master_priv_file")
+ .required();
const eddsaPriv = fs.readFileSync(privFile);
const keyPair: EddsaKeyPair = {
eddsaPriv,
@@ -1076,11 +1137,13 @@ export class ExchangeService implements ExchangeServiceInterface {
changeConfig(f: (config: Configuration) => void) {
const config = Configuration.load(this.configFilename);
f(config);
- config.write(this.configFilename);
+ config.write(this.configFilename, { excludeDefaults: true });
}
static create(gc: GlobalTestState, e: ExchangeConfig) {
+ const testDir = e.overrideTestDir ?? gc.testDir;
const config = new Configuration();
+ setTalerPaths(config, testDir + "/talerhome");
config.setString("taler", "currency", e.currency);
// Required by the exchange but not really used yet.
config.setString("exchange", "aml_threshold", `${e.currency}:1000000`);
@@ -1089,7 +1152,6 @@ export class ExchangeService implements ExchangeServiceInterface {
"currency_round_unit",
e.roundUnit ?? `${e.currency}:0.01`,
);
- setTalerPaths(config, gc.testDir + "/talerhome");
config.setString(
"exchange",
"revocation_dir",
@@ -1124,10 +1186,16 @@ export class ExchangeService implements ExchangeServiceInterface {
fs.mkdirSync(path.dirname(masterPrivFile), { recursive: true });
+ if (fs.existsSync(masterPrivFile)) {
+ throw new Error(
+ "master priv file already exists, can't create new exchange config",
+ );
+ }
+
fs.writeFileSync(masterPrivFile, Buffer.from(exchangeMasterKey.eddsaPriv));
- const cfgFilename = gc.testDir + `/exchange-${e.name}.conf`;
- config.write(cfgFilename);
+ const cfgFilename = testDir + `/exchange-${e.name}.conf`;
+ config.write(cfgFilename, { excludeDefaults: true });
return new ExchangeService(gc, e, cfgFilename, exchangeMasterKey);
}
@@ -1136,13 +1204,13 @@ export class ExchangeService implements ExchangeServiceInterface {
offeredCoins.forEach((cc) =>
setCoin(config, cc(this.exchangeConfig.currency)),
);
- config.write(this.configFilename);
+ config.write(this.configFilename, { excludeDefaults: true });
}
addCoinConfigList(ccs: CoinConfig[]) {
const config = Configuration.load(this.configFilename);
ccs.forEach((cc) => setCoin(config, cc));
- config.write(this.configFilename);
+ config.write(this.configFilename, { excludeDefaults: true });
}
enableAgeRestrictions(maskStr: string) {
@@ -1153,7 +1221,7 @@ export class ExchangeService implements ExchangeServiceInterface {
"age_groups",
maskStr,
);
- config.write(this.configFilename);
+ config.write(this.configFilename, { excludeDefaults: true });
}
get masterPub() {
@@ -1174,7 +1242,7 @@ export class ExchangeService implements ExchangeServiceInterface {
): Promise<void> {
const config = Configuration.load(this.configFilename);
await f(config);
- config.write(this.configFilename);
+ config.write(this.configFilename, { excludeDefaults: true });
}
async addBankAccount(
@@ -1214,7 +1282,7 @@ export class ExchangeService implements ExchangeServiceInterface {
"password",
exchangeBankAccount.accountPassword,
);
- config.write(this.configFilename);
+ config.write(this.configFilename, { excludeDefaults: true });
}
exchangeHttpProc: ProcessWrapper | undefined;
@@ -1475,15 +1543,26 @@ export class ExchangeService implements ExchangeServiceInterface {
);
}
- async start(): Promise<void> {
- if (this.isRunning()) {
- throw Error("exchange is already running");
- }
+ async dbinit() {
await sh(
this.globalState,
"exchange-dbinit",
`taler-exchange-dbinit -c "${this.configFilename}"`,
);
+ }
+
+ async start(
+ opts: { skipDbinit?: boolean; skipKeyup?: boolean } = {},
+ ): Promise<void> {
+ if (this.isRunning()) {
+ throw Error("exchange is already running");
+ }
+
+ const skipDbinit = opts.skipDbinit ?? false;
+
+ if (!skipDbinit) {
+ await this.dbinit();
+ }
this.helperCryptoEddsaProc = this.globalState.spawnService(
"taler-exchange-secmod-eddsa",
@@ -1514,7 +1593,14 @@ export class ExchangeService implements ExchangeServiceInterface {
);
await this.pingUntilAvailable();
- await this.keyup();
+
+ const skipKeyup = opts.skipKeyup ?? false;
+
+ if (!skipKeyup) {
+ await this.keyup();
+ } else {
+ logger.info("skipping keyup");
+ }
}
async pingUntilAvailable(): Promise<void> {
@@ -1530,6 +1616,7 @@ export interface MerchantConfig {
currency: string;
httpPort: number;
database: string;
+ overrideTestDir?: string;
}
export interface PrivateOrderStatusQuery {
@@ -1775,8 +1862,13 @@ export interface CreateMerchantTippingReserveRequest {
}
export class MerchantService implements MerchantServiceInterface {
- static fromExistingConfig(gc: GlobalTestState, name: string) {
- const cfgFilename = gc.testDir + `/merchant-${name}.conf`;
+ static fromExistingConfig(
+ gc: GlobalTestState,
+ name: string,
+ opts: { overridePath?: string },
+ ) {
+ const testDir = opts.overridePath ?? gc.testDir;
+ const cfgFilename = testDir + `/merchant-${name}.conf`;
const config = Configuration.load(cfgFilename);
const mc: MerchantConfig = {
currency: config.getString("taler", "currency").required(),
@@ -1846,13 +1938,24 @@ export class MerchantService implements MerchantServiceInterface {
}
}
- async start(): Promise<void> {
+ async dbinit() {
await runCommand(
this.globalState,
"merchant-dbinit",
"taler-merchant-dbinit",
["-c", this.configFilename],
);
+ }
+
+ /**
+ * Start the merchant,
+ */
+ async start(opts: { skipDbinit?: boolean } = {}): Promise<void> {
+ const skipSetup = opts.skipDbinit ?? false;
+
+ if (!skipSetup) {
+ await this.dbinit();
+ }
this.proc = this.globalState.spawnService(
"taler-merchant-httpd",
@@ -1871,11 +1974,12 @@ export class MerchantService implements MerchantServiceInterface {
gc: GlobalTestState,
mc: MerchantConfig,
): Promise<MerchantService> {
+ const testDir = mc.overrideTestDir ?? gc.testDir;
const config = new Configuration();
config.setString("taler", "currency", mc.currency);
- const cfgFilename = gc.testDir + `/merchant-${mc.name}.conf`;
- setTalerPaths(config, gc.testDir + "/talerhome");
+ const cfgFilename = testDir + `/merchant-${mc.name}.conf`;
+ setTalerPaths(config, testDir + "/talerhome");
config.setString("merchant", "serve", "tcp");
config.setString("merchant", "port", `${mc.httpPort}`);
config.setString(
@@ -1884,7 +1988,7 @@ export class MerchantService implements MerchantServiceInterface {
"${TALER_DATA_HOME}/merchant/merchant.priv",
);
config.setString("merchantdb-postgres", "config", mc.database);
- config.write(cfgFilename);
+ config.write(cfgFilename, { excludeDefaults: true });
return new MerchantService(gc, mc, cfgFilename);
}
@@ -1902,7 +2006,7 @@ export class MerchantService implements MerchantServiceInterface {
this.merchantConfig.currency,
);
config.setString(`merchant-exchange-${e.name}`, "master_key", e.masterPub);
- config.write(this.configFilename);
+ config.write(this.configFilename, { excludeDefaults: true });
}
async addDefaultInstance(): Promise<void> {
@@ -1935,14 +2039,8 @@ export class MerchantService implements MerchantServiceInterface {
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`,
+ // FIXME: In some tests, we might want to make this configurable
+ use_stefan: true,
default_wire_transfer_delay:
instanceConfig.defaultWireTransferDelay ??
Duration.toTalerProtocolDuration(
@@ -1984,9 +2082,6 @@ export interface PartialMerchantInstanceConfig {
paytoUris: string[];
address?: unknown;
jurisdiction?: unknown;
- defaultMaxWireFee?: string;
- defaultMaxDepositFee?: string;
- defaultWireFeeAmortization?: number;
defaultWireTransferDelay?: TalerProtocolDuration;
defaultPayDelay?: TalerProtocolDuration;
}
@@ -2029,9 +2124,7 @@ export interface MerchantInstanceConfig {
name: string;
address: unknown;
jurisdiction: unknown;
- default_max_wire_fee: string;
- default_max_deposit_fee: string;
- default_wire_fee_amortization: number;
+ use_stefan: boolean;
default_wire_transfer_delay: TalerProtocolDuration;
default_pay_delay: TalerProtocolDuration;
}
@@ -2229,12 +2322,15 @@ export class WalletService {
}
async pingUntilAvailable(): Promise<void> {
+ let nextDelay = backoffStart();
while (1) {
try {
await tryUnixConnect(this.socketPath);
} catch (e) {
- logger.info(`connection attempt failed: ${e}`);
- await delayMs(200);
+ logger.info(`wallet connection attempt failed: ${e}`);
+ logger.info(`waiting on wallet for ${nextDelay}ms`);
+ await delayMs(nextDelay);
+ nextDelay = backoffIncrement(nextDelay);
continue;
}
logger.info("connection to wallet-core succeeded");
diff --git a/packages/taler-harness/src/harness/helpers.ts b/packages/taler-harness/src/harness/helpers.ts
index 3e91c8bd9..d41ffdd00 100644
--- a/packages/taler-harness/src/harness/helpers.ts
+++ b/packages/taler-harness/src/harness/helpers.ts
@@ -32,6 +32,7 @@ import {
NotificationType,
WalletNotification,
TransactionMajorState,
+ Logger,
} from "@gnu-taler/taler-util";
import {
BankAccessApi,
@@ -49,18 +50,24 @@ import {
DbInfo,
ExchangeService,
ExchangeServiceInterface,
+ FakebankService,
getPayto,
GlobalTestState,
MerchantPrivateApi,
MerchantService,
MerchantServiceInterface,
setupDb,
+ setupSharedDb,
WalletCli,
WalletClient,
WalletService,
WithAuthorization,
} from "./harness.js";
+import * as fs from "fs";
+
+const logger = new Logger("helpers.ts");
+
/**
* @deprecated
*/
@@ -94,6 +101,10 @@ export interface EnvOptions {
ageMaskSpec?: string;
mixedAgeRestriction?: boolean;
+
+ additionalExchangeConfig?(e: ExchangeService): void;
+ additionalMerchantConfig?(m: MerchantService): void;
+ additionalBankConfig?(b: BankService): void;
}
/**
@@ -204,6 +215,179 @@ export async function createSimpleTestkudosEnvironment(
};
}
+export async function useSharedTestkudosEnvironment(t: GlobalTestState) {
+ const coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS"));
+
+ const sharedDir = `/tmp/taler-harness@${process.env.USER}`;
+
+ fs.mkdirSync(sharedDir, { recursive: true });
+
+ const db = await setupSharedDb(t);
+
+ let bank: FakebankService;
+
+ const prevSetupDone = fs.existsSync(sharedDir + "/setup-done");
+
+ logger.info(`previous setup done: ${prevSetupDone}`);
+
+
+ // Wallet has longer startup-time and no dependencies,
+ // so we start it rather early.
+ const walletStartProm = createWalletDaemonWithClient(t, { name: "wallet" })
+
+ if (fs.existsSync(sharedDir + "/bank.conf")) {
+ logger.info("reusing existing bank");
+ bank = BankService.fromExistingConfig(t, {
+ overridePath: sharedDir,
+ });
+ } else {
+ logger.info("creating new bank config");
+ bank = await BankService.create(t, {
+ allowRegistrations: true,
+ currency: "TESTKUDOS",
+ database: db.connStr,
+ httpPort: 8082,
+ overrideTestDir: sharedDir,
+ });
+ }
+
+ logger.info("setting up exchange");
+
+ const exchangeName = "testexchange-1";
+ const exchangeConfigFilename = sharedDir + `/exchange-${exchangeName}.conf`;
+
+ logger.info(`exchange config filename: ${exchangeConfigFilename}`);
+
+ let exchange: ExchangeService;
+
+ if (fs.existsSync(exchangeConfigFilename)) {
+ logger.info("reusing existing exchange config");
+ exchange = ExchangeService.fromExistingConfig(t, exchangeName, {
+ overridePath: sharedDir,
+ });
+ } else {
+ logger.info("creating new exchange config");
+ exchange = ExchangeService.create(t, {
+ name: "testexchange-1",
+ currency: "TESTKUDOS",
+ httpPort: 8081,
+ database: db.connStr,
+ overrideTestDir: sharedDir,
+ });
+ }
+
+ logger.info("setting up merchant");
+
+ let merchant: MerchantService;
+ const merchantName = "testmerchant-1";
+ const merchantConfigFilename = sharedDir + `/merchant-${merchantName}}`;
+
+ if (fs.existsSync(merchantConfigFilename)) {
+ merchant = MerchantService.fromExistingConfig(t, merchantName, {
+ overridePath: sharedDir,
+ });
+ } else {
+ merchant = await MerchantService.create(t, {
+ name: "testmerchant-1",
+ currency: "TESTKUDOS",
+ httpPort: 8083,
+ database: db.connStr,
+ overrideTestDir: sharedDir,
+ });
+ }
+
+ logger.info("creating bank account for exchange");
+
+ const exchangeBankAccount = await bank.createExchangeAccount(
+ "myexchange",
+ "x",
+ );
+
+ logger.info("creating exchange bank account");
+ await exchange.addBankAccount("1", exchangeBankAccount);
+
+ bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
+
+ exchange.addCoinConfigList(coinConfig);
+
+ merchant.addExchange(exchange);
+
+ logger.info("basic setup done, starting services");
+
+ if (!prevSetupDone) {
+ // Must be done sequentially, due to a concurrency
+ // issue in the *-dbinit tools.
+ await exchange.dbinit();
+ await merchant.dbinit();
+ }
+
+ const bankStart = async () => {
+ await bank.start();
+ await bank.pingUntilAvailable();
+ };
+
+ const exchangeStart = async () => {
+ await exchange.start({
+ skipDbinit: true,
+ skipKeyup: prevSetupDone,
+ });
+ await exchange.pingUntilAvailable();
+ };
+
+ const merchStart = async () => {
+ await merchant.start({
+ skipDbinit: true,
+ });
+ await merchant.pingUntilAvailable();
+
+ if (!prevSetupDone) {
+ 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 }),
+ ),
+ });
+ }
+ };
+
+ await bankStart()
+
+ const res = await Promise.all([
+ exchangeStart(),
+ merchStart(),
+ undefined,
+ walletStartProm,
+ ]);
+
+ const walletClient = res[3].walletClient;
+ const walletService = res[3].walletService;
+
+ fs.writeFileSync(sharedDir + "/setup-done", "OK");
+
+ logger.info("setup done!");
+
+ return {
+ commonDb: db,
+ exchange,
+ merchant,
+ walletClient,
+ walletService,
+ bank,
+ exchangeBankAccount,
+ };
+}
+
/**
* Run a test case with a simple TESTKUDOS Taler environment, consisting
* of one exchange, one bank and one merchant.
@@ -246,6 +430,9 @@ export async function createSimpleTestkudosEnvironmentV2(
bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
+ if (opts.additionalBankConfig) {
+ opts.additionalBankConfig(bank);
+ }
await bank.start();
await bank.pingUntilAvailable();
@@ -272,11 +459,17 @@ export async function createSimpleTestkudosEnvironmentV2(
exchange.addCoinConfigList(coinConfig);
}
+ if (opts.additionalExchangeConfig) {
+ opts.additionalExchangeConfig(exchange);
+ }
await exchange.start();
await exchange.pingUntilAvailable();
merchant.addExchange(exchange);
+ if (opts.additionalMerchantConfig) {
+ opts.additionalMerchantConfig(merchant);
+ }
await merchant.start();
await merchant.pingUntilAvailable();
@@ -336,7 +529,7 @@ export async function createWalletDaemonWithClient(
const walletClient = new WalletClient({
unixPath: walletService.socketPath,
onNotification(n) {
- console.log("got notification", n);
+ console.log(`got ${args.name} notification`, n);
if (args.handleNotification) {
args.handleNotification(n);
}
@@ -610,6 +803,8 @@ export async function applyTimeTravel(
/**
* Make a simple payment and check that it succeeded.
+ *
+ * @deprecated
*/
export async function makeTestPayment(
t: GlobalTestState,
diff --git a/packages/taler-harness/src/index.ts b/packages/taler-harness/src/index.ts
index ec99232f5..841e17dc7 100644
--- a/packages/taler-harness/src/index.ts
+++ b/packages/taler-harness/src/index.ts
@@ -170,6 +170,39 @@ const sandcastleCli = testingCli.subcommand("sandcastleArgs", "sandcastle", {
help: "Subcommands for handling GNU Taler sandcastle deployments.",
});
+const configCli = testingCli.subcommand("configArgs", "config", {
+ help: "Subcommands for handling the Taler configuration.",
+});
+
+configCli.subcommand("show", "show").action(async (args) => {
+ const config = Configuration.load();
+ const cfgStr = config.stringify({
+ diagnostics: true,
+ });
+ console.log(cfgStr);
+});
+
+configCli
+ .subcommand("get", "get")
+ .requiredArgument("section", clk.STRING)
+ .requiredArgument("option", clk.STRING)
+ .flag("file", ["-f"])
+ .action(async (args) => {
+ const config = Configuration.load();
+ let res;
+ if (args.get.file) {
+ res = config.getString(args.get.section, args.get.option);
+ } else {
+ res = config.getPath(args.get.section, args.get.option);
+ }
+ if (res.isDefined()) {
+ console.log(res.value);
+ } else {
+ console.warn("not found");
+ process.exit(1);
+ }
+ });
+
const deploymentCli = testingCli.subcommand("deploymentArgs", "deployment", {
help: "Subcommands for handling GNU Taler deployments.",
});
@@ -208,8 +241,10 @@ deploymentCli
const bankAccessApiClient = new BankAccessApiClient({
baseUrl: args.tipTopup.bankAccessUrl,
- username: args.tipTopup.bankAccount,
- password: args.tipTopup.bankPassword,
+ auth: {
+ username: args.tipTopup.bankAccount,
+ password: args.tipTopup.bankPassword,
+ },
allowHttp: true,
});
@@ -219,10 +254,12 @@ deploymentCli
console.log("payto URI:", paytoUri);
- const transactions = await bankAccessApiClient.getTransactions();
+ const transactions = await bankAccessApiClient.getTransactions(
+ args.tipTopup.bankAccount,
+ );
console.log("transactions:", j2s(transactions));
- await bankAccessApiClient.createTransaction({
+ await bankAccessApiClient.createTransaction(args.tipTopup.bankAccount, {
amount,
paytoUri,
});
diff --git a/packages/taler-harness/src/integrationtests/test-age-restrictions-mixed-merchant.ts b/packages/taler-harness/src/integrationtests/test-age-restrictions-mixed-merchant.ts
index 8bf71b63d..af90ef1c5 100644
--- a/packages/taler-harness/src/integrationtests/test-age-restrictions-mixed-merchant.ts
+++ b/packages/taler-harness/src/integrationtests/test-age-restrictions-mixed-merchant.ts
@@ -17,12 +17,14 @@
/**
* Imports.
*/
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { defaultCoinConfig } from "../harness/denomStructures.js";
-import { GlobalTestState, WalletCli } from "../harness/harness.js";
+import { GlobalTestState } from "../harness/harness.js";
import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- makeTestPayment,
+ createSimpleTestkudosEnvironmentV2,
+ createWalletDaemonWithClient,
+ makeTestPaymentV2,
+ withdrawViaBankV2,
} from "../harness/helpers.js";
/**
@@ -32,11 +34,11 @@ export async function runAgeRestrictionsMixedMerchantTest(t: GlobalTestState) {
// Set up test environment
const {
- wallet: walletOne,
+ walletClient: walletOne,
bank,
exchange,
merchant,
- } = await createSimpleTestkudosEnvironment(
+ } = await createSimpleTestkudosEnvironmentV2(
t,
defaultCoinConfig.map((x) => x("TESTKUDOS")),
{
@@ -45,20 +47,27 @@ export async function runAgeRestrictionsMixedMerchantTest(t: GlobalTestState) {
},
);
- const walletTwo = new WalletCli(t, "walletTwo");
- const walletThree = new WalletCli(t, "walletThree");
+ const { walletClient: walletTwo } = await createWalletDaemonWithClient(t, {
+ name: "w2",
+ });
+
+ const { walletClient: walletThree } = await createWalletDaemonWithClient(t, {
+ name: "w3",
+ });
{
- const wallet = walletOne;
+ const walletClient = walletOne;
- await withdrawViaBank(t, {
- wallet,
+ const wres = await withdrawViaBankV2(t, {
+ walletClient,
bank,
exchange,
amount: "TESTKUDOS:20",
restrictAge: 13,
});
+ await wres.withdrawalFinishedCond;
+
const order = {
summary: "Buy me!",
amount: "TESTKUDOS:5",
@@ -66,41 +75,46 @@ export async function runAgeRestrictionsMixedMerchantTest(t: GlobalTestState) {
minimum_age: 9,
};
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
+ await makeTestPaymentV2(t, { walletClient, merchant, order });
+ await walletClient.call(
+ WalletApiOperation.TestingWaitTransactionsFinal,
+ {},
+ );
}
{
- const wallet = walletTwo;
-
- await withdrawViaBank(t, {
- wallet,
+ const wres = await withdrawViaBankV2(t, {
+ walletClient: walletTwo,
bank,
exchange,
amount: "TESTKUDOS:20",
restrictAge: 13,
});
+
+ await wres.withdrawalFinishedCond;
+
const order = {
summary: "Buy me!",
amount: "TESTKUDOS:5",
fulfillment_url: "taler://fulfillment-success/thx",
};
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
+ await makeTestPaymentV2(t, { walletClient: walletTwo, merchant, order });
+ await walletTwo.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
}
{
- const wallet = walletThree;
-
- await withdrawViaBank(t, {
- wallet,
+ const wres = await withdrawViaBankV2(t, {
+ walletClient: walletThree,
bank,
exchange,
amount: "TESTKUDOS:20",
});
+
+ await wres.withdrawalFinishedCond;
+
const order = {
summary: "Buy me!",
amount: "TESTKUDOS:5",
@@ -108,8 +122,8 @@ export async function runAgeRestrictionsMixedMerchantTest(t: GlobalTestState) {
minimum_age: 9,
};
- await makeTestPayment(t, { wallet, merchant, order });
- await wallet.runUntilDone();
+ await makeTestPaymentV2(t, { walletClient: walletThree, merchant, order });
+ await walletThree.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
}
}
diff --git a/packages/taler-harness/src/integrationtests/test-bank-api.ts b/packages/taler-harness/src/integrationtests/test-bank-api.ts
index a0e1c2085..9ac16980b 100644
--- a/packages/taler-harness/src/integrationtests/test-bank-api.ts
+++ b/packages/taler-harness/src/integrationtests/test-bank-api.ts
@@ -17,23 +17,22 @@
/**
* 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,
+ BankApi,
CreditDebitIndicator,
WireGatewayApiClient,
} from "@gnu-taler/taler-wallet-core";
+import { defaultCoinConfig } from "../harness/denomStructures.js";
+import {
+ BankService,
+ ExchangeService,
+ GlobalTestState,
+ MerchantService,
+ getPayto,
+ setupDb,
+} from "../harness/harness.js";
/**
* Run test for basic, bank-integrated withdrawal.
diff --git a/packages/taler-harness/src/integrationtests/test-claim-loop.ts b/packages/taler-harness/src/integrationtests/test-claim-loop.ts
index 921391283..32706c28b 100644
--- a/packages/taler-harness/src/integrationtests/test-claim-loop.ts
+++ b/packages/taler-harness/src/integrationtests/test-claim-loop.ts
@@ -17,13 +17,13 @@
/**
* Imports.
*/
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { URL } from "url";
import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
+ createSimpleTestkudosEnvironmentV2,
+ withdrawViaBankV2,
} from "../harness/helpers.js";
-import { URL } from "url";
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
/**
* Run test for the merchant's order lifecycle.
@@ -34,10 +34,15 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
export async function runClaimLoopTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(t);
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ await withdrawViaBankV2(t, {
+ walletClient,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
// Set up order.
const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
@@ -61,7 +66,7 @@ export async function runClaimLoopTest(t: GlobalTestState) {
// Make wallet claim the unpaid order.
t.assertTrue(orderStatusBefore.order_status === "unpaid");
const talerPayUri = orderStatusBefore.taler_pay_uri;
- await wallet.client.call(WalletApiOperation.PreparePayForUri, {
+ await walletClient.call(WalletApiOperation.PreparePayForUri, {
talerPayUri,
});
diff --git a/packages/taler-harness/src/integrationtests/test-denom-unoffered.ts b/packages/taler-harness/src/integrationtests/test-denom-unoffered.ts
index 27c336ea6..5a471b9aa 100644
--- a/packages/taler-harness/src/integrationtests/test-denom-unoffered.ts
+++ b/packages/taler-harness/src/integrationtests/test-denom-unoffered.ts
@@ -18,22 +18,29 @@
* Imports.
*/
import { PreparePayResultType, TalerErrorCode } from "@gnu-taler/taler-util";
-import { Wallet, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
+ createSimpleTestkudosEnvironmentV2,
+ withdrawViaBankV2,
} from "../harness/helpers.js";
export async function runDenomUnofferedTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(t);
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ const wres = await withdrawViaBankV2(t, {
+ walletClient,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
+
+ await wres.withdrawalFinishedCond;
// Make the exchange forget the denomination.
// Effectively we completely reset the exchange,
@@ -67,7 +74,7 @@ export async function runDenomUnofferedTest(t: GlobalTestState) {
// Make wallet pay for the order
- const preparePayResult = await wallet.client.call(
+ const preparePayResult = await walletClient.call(
WalletApiOperation.PreparePayForUri,
{
talerPayUri: orderStatus.taler_pay_uri,
@@ -78,11 +85,11 @@ export async function runDenomUnofferedTest(t: GlobalTestState) {
preparePayResult.status === PreparePayResultType.PaymentPossible,
);
- const confirmResp = await wallet.client.call(WalletApiOperation.ConfirmPay, {
+ const confirmResp = await walletClient.call(WalletApiOperation.ConfirmPay, {
proposalId: preparePayResult.proposalId,
});
- const tx = await wallet.client.call(WalletApiOperation.GetTransactionById, {
+ const tx = await walletClient.call(WalletApiOperation.GetTransactionById, {
transactionId: confirmResp.transactionId,
});
@@ -96,21 +103,26 @@ export async function runDenomUnofferedTest(t: GlobalTestState) {
TalerErrorCode.MERCHANT_POST_ORDERS_ID_PAY_DENOMINATION_KEY_NOT_FOUND,
);
- await wallet.client.call(WalletApiOperation.AddExchange, {
+ await walletClient.call(WalletApiOperation.AddExchange, {
exchangeBaseUrl: exchange.baseUrl,
forceUpdate: true,
});
- await wallet.client.call(WalletApiOperation.DeleteTransaction, {
+ await walletClient.call(WalletApiOperation.DeleteTransaction, {
transactionId: confirmResp.transactionId,
});
// Now withdrawal should work again.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ await withdrawViaBankV2(t, {
+ walletClient,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
- const txs = await wallet.client.call(WalletApiOperation.GetTransactions, {});
+ const txs = await walletClient.call(WalletApiOperation.GetTransactions, {});
console.log(JSON.stringify(txs, undefined, 2));
}
diff --git a/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts b/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts
index 6c0d070d0..05bbbfaa1 100644
--- a/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts
+++ b/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts
@@ -30,14 +30,15 @@ import {
depositCoin,
downloadExchangeInfo,
findDenomOrThrow,
- refreshCoin,
SynchronousCryptoWorkerFactoryPlain,
topupReserveWithDemobank,
Wallet,
withdrawCoin,
} from "@gnu-taler/taler-wallet-core";
import { GlobalTestState } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
+import {
+ createSimpleTestkudosEnvironmentV2,
+} from "../harness/helpers.js";
/**
* Run test for basic, bank-integrated withdrawal and payment.
@@ -45,7 +46,7 @@ import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
export async function runExchangeDepositTest(t: GlobalTestState) {
// Set up test environment
- const { bank, exchange } = await createSimpleTestkudosEnvironment(t);
+ const { bank, exchange } = await createSimpleTestkudosEnvironmentV2(t);
const http = createPlatformHttpLib({
allowHttp: true,
diff --git a/packages/taler-harness/src/integrationtests/test-fee-regression.ts b/packages/taler-harness/src/integrationtests/test-fee-regression.ts
index 8c5a5bea4..e0dc4bc3b 100644
--- a/packages/taler-harness/src/integrationtests/test-fee-regression.ts
+++ b/packages/taler-harness/src/integrationtests/test-fee-regression.ts
@@ -19,18 +19,18 @@
*/
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import {
- GlobalTestState,
BankService,
ExchangeService,
+ GlobalTestState,
MerchantService,
- setupDb,
- WalletCli,
getPayto,
+ setupDb,
} from "../harness/harness.js";
import {
- withdrawViaBank,
- makeTestPayment,
- SimpleTestEnvironment,
+ SimpleTestEnvironmentNg,
+ createWalletDaemonWithClient,
+ makeTestPaymentV2,
+ withdrawViaBankV2,
} from "../harness/helpers.js";
/**
@@ -39,7 +39,7 @@ import {
*/
export async function createMyTestkudosEnvironment(
t: GlobalTestState,
-): Promise<SimpleTestEnvironment> {
+): Promise<SimpleTestEnvironmentNg> {
const db = await setupDb(t);
const bank = await BankService.create(t, {
@@ -147,13 +147,19 @@ export async function createMyTestkudosEnvironment(
console.log("setup done!");
- const wallet = new WalletCli(t);
+ const { walletClient, walletService } = await createWalletDaemonWithClient(
+ t,
+ {
+ name: "w1",
+ },
+ );
return {
commonDb: db,
exchange,
merchant,
- wallet,
+ walletClient,
+ walletService,
bank,
exchangeBankAccount,
};
@@ -165,19 +171,21 @@ export async function createMyTestkudosEnvironment(
export async function runFeeRegressionTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
+ const { walletClient, bank, exchange, merchant } =
await createMyTestkudosEnvironment(t);
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, {
- wallet,
+ const wres = await withdrawViaBankV2(t, {
+ walletClient,
bank,
exchange,
amount: "TESTKUDOS:1.92",
});
- const coins = await wallet.client.call(WalletApiOperation.DumpCoins, {});
+ await wres.withdrawalFinishedCond;
+
+ const coins = await walletClient.call(WalletApiOperation.DumpCoins, {});
// Make sure we really withdraw one 0.64 and one 1.28 coin.
t.assertTrue(coins.coins.length === 2);
@@ -188,11 +196,11 @@ export async function runFeeRegressionTest(t: GlobalTestState) {
fulfillment_url: "taler://fulfillment-success/thx",
};
- await makeTestPayment(t, { wallet, merchant, order });
+ await makeTestPaymentV2(t, { walletClient, merchant, order });
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
- const txs = await wallet.client.call(WalletApiOperation.GetTransactions, {});
+ const txs = await walletClient.call(WalletApiOperation.GetTransactions, {});
t.assertAmountEquals(txs.transactions[1].amountEffective, "TESTKUDOS:1.30");
console.log(txs);
}
diff --git a/packages/taler-harness/src/integrationtests/test-forced-selection.ts b/packages/taler-harness/src/integrationtests/test-forced-selection.ts
index d0621f000..3425dadf1 100644
--- a/packages/taler-harness/src/integrationtests/test-forced-selection.ts
+++ b/packages/taler-harness/src/integrationtests/test-forced-selection.ts
@@ -20,7 +20,7 @@
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";
+import { createSimpleTestkudosEnvironmentV2 } from "../harness/helpers.js";
/**
* Run test for forced denom/coin selection.
@@ -28,14 +28,14 @@ import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
export async function runForcedSelectionTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(t);
- await wallet.client.call(WalletApiOperation.AddExchange, {
+ await walletClient.call(WalletApiOperation.AddExchange, {
exchangeBaseUrl: exchange.baseUrl,
});
- await wallet.client.call(WalletApiOperation.WithdrawTestBalance, {
+ await walletClient.call(WalletApiOperation.WithdrawTestBalance, {
exchangeBaseUrl: exchange.baseUrl,
amount: "TESTKUDOS:10",
bankAccessApiBaseUrl: bank.bankAccessApiBaseUrl,
@@ -49,13 +49,13 @@ export async function runForcedSelectionTest(t: GlobalTestState) {
},
});
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
- const coinDump = await wallet.client.call(WalletApiOperation.DumpCoins, {});
+ const coinDump = await walletClient.call(WalletApiOperation.DumpCoins, {});
console.log(coinDump);
t.assertDeepEqual(coinDump.coins.length, 3);
- const payResp = await wallet.client.call(WalletApiOperation.TestPay, {
+ const payResp = await walletClient.call(WalletApiOperation.TestPay, {
amount: "TESTKUDOS:3",
merchantBaseUrl: merchant.makeInstanceBaseUrl(),
summary: "bla",
diff --git a/packages/taler-harness/src/integrationtests/test-libeufin-api-bankaccount.ts b/packages/taler-harness/src/integrationtests/test-libeufin-api-bankaccount.ts
index a5396a472..f36168301 100644
--- a/packages/taler-harness/src/integrationtests/test-libeufin-api-bankaccount.ts
+++ b/packages/taler-harness/src/integrationtests/test-libeufin-api-bankaccount.ts
@@ -19,7 +19,6 @@
*/
import { GlobalTestState } from "../harness/harness.js";
import {
- NexusUserBundle,
LibeufinNexusApi,
LibeufinNexusService,
LibeufinSandboxService,
diff --git a/packages/taler-harness/src/integrationtests/test-libeufin-nexus-balance.ts b/packages/taler-harness/src/integrationtests/test-libeufin-nexus-balance.ts
index 5c10c029e..68b0174cc 100644
--- a/packages/taler-harness/src/integrationtests/test-libeufin-nexus-balance.ts
+++ b/packages/taler-harness/src/integrationtests/test-libeufin-nexus-balance.ts
@@ -23,7 +23,6 @@ import {
NexusUserBundle,
launchLibeufinServices,
LibeufinNexusApi,
- LibeufinCli,
} from "../harness/libeufin.js";
/**
diff --git a/packages/taler-harness/src/integrationtests/test-merchant-instances-urls.ts b/packages/taler-harness/src/integrationtests/test-merchant-instances-urls.ts
index 1b5d50fd1..534b35278 100644
--- a/packages/taler-harness/src/integrationtests/test-merchant-instances-urls.ts
+++ b/packages/taler-harness/src/integrationtests/test-merchant-instances-urls.ts
@@ -67,12 +67,10 @@ export async function runMerchantInstancesUrlsTest(t: GlobalTestState) {
await clientForDefault.createInstance({
id: "default",
address: {},
- default_max_deposit_fee: "TESTKUDOS:1",
- default_max_wire_fee: "TESTKUDOS:1",
+ use_stefan: true,
default_pay_delay: Duration.toTalerProtocolDuration(
Duration.fromSpec({ seconds: 60 }),
),
- default_wire_fee_amortization: 1,
default_wire_transfer_delay: Duration.toTalerProtocolDuration(
Duration.fromSpec({ seconds: 60 }),
),
@@ -92,12 +90,10 @@ export async function runMerchantInstancesUrlsTest(t: GlobalTestState) {
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,
+ use_stefan: true,
default_wire_transfer_delay: Duration.toTalerProtocolDuration(
Duration.fromSpec({ seconds: 60 }),
),
diff --git a/packages/taler-harness/src/integrationtests/test-merchant-longpolling.ts b/packages/taler-harness/src/integrationtests/test-merchant-longpolling.ts
index 7d2ba99b2..59f23fe5d 100644
--- a/packages/taler-harness/src/integrationtests/test-merchant-longpolling.ts
+++ b/packages/taler-harness/src/integrationtests/test-merchant-longpolling.ts
@@ -17,20 +17,20 @@
/**
* Imports.
*/
-import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
-import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
-} from "../harness/helpers.js";
import {
- PreparePayResultType,
- codecForMerchantOrderStatusUnpaid,
ConfirmPayResultType,
+ PreparePayResultType,
URL,
+ codecForMerchantOrderStatusUnpaid,
} from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import axiosImp from "axios";
+import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
+import {
+ createSimpleTestkudosEnvironmentV2,
+ withdrawViaBankV2
+} from "../harness/helpers.js";
const axios = axiosImp.default;
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
/**
* Run test for basic, bank-integrated withdrawal.
@@ -38,12 +38,19 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
export async function runMerchantLongpollingTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(t);
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ const wres = await withdrawViaBankV2(t, {
+ walletClient,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
+
+ await wres.withdrawalFinishedCond;
/**
* =========================================================================
@@ -113,7 +120,7 @@ export async function runMerchantLongpollingTest(t: GlobalTestState) {
* =========================================================================
*/
- let preparePayResp = await wallet.client.call(
+ let preparePayResp = await walletClient.call(
WalletApiOperation.PreparePayForUri,
{
talerPayUri: pubUnpaidStatus.taler_pay_uri,
@@ -148,7 +155,7 @@ export async function runMerchantLongpollingTest(t: GlobalTestState) {
publicOrderStatusResp.data,
);
- const confirmPayRes = await wallet.client.call(
+ const confirmPayRes = await walletClient.call(
WalletApiOperation.ConfirmPay,
{
proposalId: proposalId,
diff --git a/packages/taler-harness/src/integrationtests/test-payment-abort.ts b/packages/taler-harness/src/integrationtests/test-payment-abort.ts
index 0ac953240..40438c583 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-abort.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-abort.ts
@@ -24,7 +24,6 @@ import {
} from "../harness/helpers.js";
import {
FaultInjectionRequestContext,
- FaultInjectionResponseContext,
} from "../harness/faultInjection.js";
import {
codecForMerchantOrderStatusUnpaid,
diff --git a/packages/taler-harness/src/integrationtests/test-payment-claim.ts b/packages/taler-harness/src/integrationtests/test-payment-claim.ts
index e93d2c44c..eb219c1e7 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-claim.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-claim.ts
@@ -17,18 +17,17 @@
/**
* Imports.
*/
+import { PreparePayResultType, TalerErrorCode } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import {
GlobalTestState,
MerchantPrivateApi,
WalletCli,
} from "../harness/harness.js";
import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
+ createSimpleTestkudosEnvironmentV2,
+ withdrawViaBankV2,
} 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.
@@ -36,14 +35,19 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
export async function runPaymentClaimTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(t);
const walletTwo = new WalletCli(t, "two");
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ await withdrawViaBankV2(t, {
+ walletClient,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
// Set up order.
@@ -65,7 +69,7 @@ export async function runPaymentClaimTest(t: GlobalTestState) {
// Make wallet pay for the order
- const preparePayResult = await wallet.client.call(
+ const preparePayResult = await walletClient.call(
WalletApiOperation.PreparePayForUri,
{
talerPayUri,
@@ -82,7 +86,7 @@ export async function runPaymentClaimTest(t: GlobalTestState) {
});
});
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
+ await walletClient.call(WalletApiOperation.ConfirmPay, {
proposalId: preparePayResult.proposalId,
});
diff --git a/packages/taler-harness/src/integrationtests/test-payment-forgettable.ts b/packages/taler-harness/src/integrationtests/test-payment-forgettable.ts
index b66eda2f1..21d76397d 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-forgettable.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-forgettable.ts
@@ -17,11 +17,12 @@
/**
* Imports.
*/
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState } from "../harness/harness.js";
import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- makeTestPayment,
+ createSimpleTestkudosEnvironmentV2,
+ makeTestPaymentV2,
+ withdrawViaBankV2,
} from "../harness/helpers.js";
/**
@@ -30,12 +31,19 @@ import {
export async function runPaymentForgettableTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(t);
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ const wres = await withdrawViaBankV2(t, {
+ walletClient,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
+
+ await wres.withdrawalFinishedCond;
{
const order = {
@@ -50,7 +58,7 @@ export async function runPaymentForgettableTest(t: GlobalTestState) {
},
};
- await makeTestPayment(t, { wallet, merchant, order });
+ await makeTestPaymentV2(t, { walletClient, merchant, order });
}
console.log("testing with forgettable field without hash");
@@ -68,10 +76,10 @@ export async function runPaymentForgettableTest(t: GlobalTestState) {
},
};
- await makeTestPayment(t, { wallet, merchant, order });
+ await makeTestPaymentV2(t, { walletClient, merchant, order });
}
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
}
runPaymentForgettableTest.suites = ["wallet", "merchant"];
diff --git a/packages/taler-harness/src/integrationtests/test-payment-idempotency.ts b/packages/taler-harness/src/integrationtests/test-payment-idempotency.ts
index 1099a8188..e16cf9dd1 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-idempotency.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-idempotency.ts
@@ -17,13 +17,13 @@
/**
* Imports.
*/
+import { PreparePayResultType } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
+ createSimpleTestkudosEnvironmentV2,
+ withdrawViaBankV2,
} 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
@@ -32,12 +32,17 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
export async function runPaymentIdempotencyTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(t);
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ await withdrawViaBankV2(t, {
+ walletClient,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
// Set up order.
@@ -59,14 +64,14 @@ export async function runPaymentIdempotencyTest(t: GlobalTestState) {
// Make wallet pay for the order
- const preparePayResult = await wallet.client.call(
+ const preparePayResult = await walletClient.call(
WalletApiOperation.PreparePayForUri,
{
talerPayUri: orderStatus.taler_pay_uri,
},
);
- const preparePayResultRep = await wallet.client.call(
+ const preparePayResultRep = await walletClient.call(
WalletApiOperation.PreparePayForUri,
{
talerPayUri: orderStatus.taler_pay_uri,
@@ -82,7 +87,7 @@ export async function runPaymentIdempotencyTest(t: GlobalTestState) {
const proposalId = preparePayResult.proposalId;
- const confirmPayResult = await wallet.client.call(
+ const confirmPayResult = await walletClient.call(
WalletApiOperation.ConfirmPay,
{
proposalId: proposalId,
@@ -91,7 +96,7 @@ export async function runPaymentIdempotencyTest(t: GlobalTestState) {
console.log("confirm pay result", confirmPayResult);
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
// Check if payment was successful.
@@ -101,7 +106,7 @@ export async function runPaymentIdempotencyTest(t: GlobalTestState) {
t.assertTrue(orderStatus.order_status === "paid");
- const preparePayResultAfter = await wallet.client.call(
+ const preparePayResultAfter = await walletClient.call(
WalletApiOperation.PreparePayForUri,
{
talerPayUri,
diff --git a/packages/taler-harness/src/integrationtests/test-payment-share.ts b/packages/taler-harness/src/integrationtests/test-payment-share.ts
index 2f853b91b..156571372 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-share.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-share.ts
@@ -17,21 +17,17 @@
/**
* Imports.
*/
+import {
+ ConfirmPayResultType,
+ PreparePayResultType,
+} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
import {
createSimpleTestkudosEnvironmentV2,
- withdrawViaBankV2,
- makeTestPaymentV2,
createWalletDaemonWithClient,
+ withdrawViaBankV2,
} from "../harness/helpers.js";
-import {
- ConfirmPayResultType,
- PreparePayResultType,
- j2s,
- parsePayUri,
- stringifyPayUri,
-} from "@gnu-taler/taler-util";
/**
* Run test for basic, bank-integrated withdrawal and payment.
diff --git a/packages/taler-harness/src/integrationtests/test-payment-template.ts b/packages/taler-harness/src/integrationtests/test-payment-template.ts
index 41e43e28a..172791648 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-template.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-template.ts
@@ -17,13 +17,12 @@
/**
* Imports.
*/
-import { ConfirmPayResultType, Duration, PreparePayResultType, TalerProtocolTimestamp } from "@gnu-taler/taler-util";
+import { ConfirmPayResultType, Duration, PreparePayResultType } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- makeTestPayment,
+ createSimpleTestkudosEnvironmentV2,
+ withdrawViaBankV2
} from "../harness/helpers.js";
/**
@@ -32,8 +31,8 @@ import {
export async function runPaymentTemplateTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(t);
await MerchantPrivateApi.createTemplate(merchant, "default", {
template_id: "template1",
@@ -51,11 +50,11 @@ export async function runPaymentTemplateTest(t: GlobalTestState) {
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ await withdrawViaBankV2(t, { walletClient, bank, exchange, amount: "TESTKUDOS:20" });
// Request a template payment
- const preparePayResult = await wallet.client.call(
+ const preparePayResult = await walletClient.call(
WalletApiOperation.PreparePayForTemplate,
{
talerPayTemplateUri: `taler+http://pay-template/localhost:${merchant.port}/template1?amount=TESTKUDOS:1`,
@@ -71,7 +70,7 @@ export async function runPaymentTemplateTest(t: GlobalTestState) {
// Pay for it
- const r2 = await wallet.client.call(WalletApiOperation.ConfirmPay, {
+ const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, {
proposalId: preparePayResult.proposalId,
});
@@ -88,8 +87,7 @@ export async function runPaymentTemplateTest(t: GlobalTestState) {
);
t.assertTrue(orderStatus.order_status === "paid");
-
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
}
runPaymentTemplateTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/test-payment-zero.ts b/packages/taler-harness/src/integrationtests/test-payment-zero.ts
index 264cffd06..7423751a5 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-zero.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-zero.ts
@@ -20,9 +20,9 @@
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState } from "../harness/harness.js";
import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
- makeTestPayment,
+ createSimpleTestkudosEnvironmentV2,
+ withdrawViaBankV2,
+ makeTestPaymentV2,
} from "../harness/helpers.js";
import { TransactionMajorState } from "@gnu-taler/taler-util";
@@ -33,19 +33,19 @@ import { TransactionMajorState } from "@gnu-taler/taler-util";
export async function runPaymentZeroTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(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 withdrawViaBankV2(t, { walletClient, bank, exchange, amount: "TESTKUDOS:20" });
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
- await makeTestPayment(t, {
- wallet,
+ await makeTestPaymentV2(t, {
+ walletClient,
merchant,
order: {
summary: "I am free!",
@@ -54,9 +54,9 @@ export async function runPaymentZeroTest(t: GlobalTestState) {
},
});
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
- const transactions = await wallet.client.call(
+ const transactions = await walletClient.call(
WalletApiOperation.GetTransactions,
{},
);
diff --git a/packages/taler-harness/src/integrationtests/test-paywall-flow.ts b/packages/taler-harness/src/integrationtests/test-paywall-flow.ts
index a9601c625..b0477a049 100644
--- a/packages/taler-harness/src/integrationtests/test-paywall-flow.ts
+++ b/packages/taler-harness/src/integrationtests/test-paywall-flow.ts
@@ -19,18 +19,22 @@
*/
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";
+import {
+ createSimpleTestkudosEnvironmentV2,
+ withdrawViaBankV2,
+} from "../harness/helpers.js";
+import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
+
+const httpLib = createPlatformHttpLib({
+ allowHttp: true,
+ enableThrottling: false,
+});
/**
* Run test for basic, bank-integrated withdrawal.
@@ -38,12 +42,17 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
export async function runPaywallFlowTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(t);
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ await withdrawViaBankV2(t, {
+ walletClient,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
/**
* =========================================================================
@@ -77,9 +86,7 @@ export async function runPaywallFlowTest(t: GlobalTestState) {
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,
- });
+ let publicOrderStatusResp = await httpLib.fetch(publicOrderStatusUrl.href);
if (publicOrderStatusResp.status != 402) {
throw Error(
@@ -88,12 +95,12 @@ export async function runPaywallFlowTest(t: GlobalTestState) {
}
let pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
+ publicOrderStatusResp.json(),
);
console.log(pubUnpaidStatus);
- let preparePayResp = await wallet.client.call(
+ let preparePayResp = await walletClient.call(
WalletApiOperation.PreparePayForUri,
{
talerPayUri: pubUnpaidStatus.taler_pay_uri,
@@ -105,10 +112,8 @@ export async function runPaywallFlowTest(t: GlobalTestState) {
const proposalId = preparePayResp.proposalId;
console.log("requesting", publicOrderStatusUrl.href);
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
- console.log("response body", publicOrderStatusResp.data);
+ publicOrderStatusResp = await httpLib.fetch(publicOrderStatusUrl.href);
+ console.log("response body", publicOrderStatusResp.json());
if (publicOrderStatusResp.status != 402) {
throw Error(
`expected status 402 (after claiming), but got ${publicOrderStatusResp.status}`,
@@ -116,26 +121,20 @@ export async function runPaywallFlowTest(t: GlobalTestState) {
}
pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
+ publicOrderStatusResp.json(),
);
- const confirmPayRes = await wallet.client.call(
- WalletApiOperation.ConfirmPay,
- {
- proposalId: proposalId,
- },
- );
+ const confirmPayRes = await walletClient.call(WalletApiOperation.ConfirmPay, {
+ proposalId: proposalId,
+ });
t.assertTrue(confirmPayRes.type === ConfirmPayResultType.Done);
+ publicOrderStatusResp = await httpLib.fetch(publicOrderStatusUrl.href);
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
-
- console.log(publicOrderStatusResp.data);
+ console.log(publicOrderStatusResp.json());
if (publicOrderStatusResp.status != 200) {
- console.log(publicOrderStatusResp.data);
+ console.log(publicOrderStatusResp.json());
throw Error(
`expected status 200 (after paying), but got ${publicOrderStatusResp.status}`,
);
@@ -158,7 +157,7 @@ export async function runPaywallFlowTest(t: GlobalTestState) {
// 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(
+ preparePayResp = await walletClient.call(
WalletApiOperation.PreparePayForUri,
{
talerPayUri: talerPayUriOne,
@@ -199,7 +198,7 @@ export async function runPaywallFlowTest(t: GlobalTestState) {
// 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(
+ preparePayResp = await walletClient.call(
WalletApiOperation.PreparePayForUri,
{
talerPayUri: orderStatus.taler_pay_uri,
@@ -232,19 +231,17 @@ export async function runPaywallFlowTest(t: GlobalTestState) {
console.log("requesting public status", publicOrderStatusUrl);
// Ask the order status of the claimed-but-unpaid order
- publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
- validateStatus: () => true,
- });
+ publicOrderStatusResp = await httpLib.fetch(publicOrderStatusUrl.href);
if (publicOrderStatusResp.status != 402) {
throw Error(`expected status 402, but got ${publicOrderStatusResp.status}`);
}
pubUnpaidStatus = codecForMerchantOrderStatusUnpaid().decode(
- publicOrderStatusResp.data,
+ publicOrderStatusResp.json(),
);
- console.log(publicOrderStatusResp.data);
+ console.log(publicOrderStatusResp.json());
t.assertTrue(pubUnpaidStatus.already_paid_order_id === firstOrderId);
}
diff --git a/packages/taler-harness/src/integrationtests/test-refund-auto.ts b/packages/taler-harness/src/integrationtests/test-refund-auto.ts
index 4c2a2f94a..607080e68 100644
--- a/packages/taler-harness/src/integrationtests/test-refund-auto.ts
+++ b/packages/taler-harness/src/integrationtests/test-refund-auto.ts
@@ -17,13 +17,13 @@
/**
* 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,
+ createSimpleTestkudosEnvironmentV2,
+ withdrawViaBankV2,
} 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.
@@ -31,12 +31,17 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
export async function runRefundAutoTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(t);
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ await withdrawViaBankV2(t, {
+ walletClient,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
// Set up order.
const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
@@ -61,13 +66,12 @@ export async function runRefundAutoTest(t: GlobalTestState) {
// Make wallet pay for the order
- const r1 = await wallet.client.call(WalletApiOperation.PreparePayForUri, {
+ const r1 = await walletClient.call(WalletApiOperation.PreparePayForUri, {
talerPayUri: orderStatus.taler_pay_uri,
});
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
- // FIXME: should be validated, don't cast!
- proposalId: r1.proposalId,
+ await walletClient.call(WalletApiOperation.ConfirmPay, {
+ transactionId: r1.transactionId,
});
// Check if payment was successful.
@@ -88,9 +92,9 @@ export async function runRefundAutoTest(t: GlobalTestState) {
console.log(ref);
// The wallet should now automatically pick up the refund.
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
- const transactions = await wallet.client.call(
+ const transactions = await walletClient.call(
WalletApiOperation.GetTransactions,
{},
);
diff --git a/packages/taler-harness/src/integrationtests/test-refund-incremental.ts b/packages/taler-harness/src/integrationtests/test-refund-incremental.ts
index c8fcfc831..8e7e38b71 100644
--- a/packages/taler-harness/src/integrationtests/test-refund-incremental.ts
+++ b/packages/taler-harness/src/integrationtests/test-refund-incremental.ts
@@ -18,21 +18,21 @@
* Imports.
*/
import {
+ Amounts,
+ Duration,
+ TransactionType,
+ durationFromSpec,
+} from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import {
GlobalTestState,
- delayMs,
MerchantPrivateApi,
+ delayMs,
} from "../harness/harness.js";
import {
- createSimpleTestkudosEnvironment,
- withdrawViaBank,
+ createSimpleTestkudosEnvironmentV2,
+ withdrawViaBankV2,
} 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.
@@ -40,12 +40,17 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
export async function runRefundIncrementalTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant } =
+ await createSimpleTestkudosEnvironmentV2(t);
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ await withdrawViaBankV2(t, {
+ walletClient,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
// Set up order.
@@ -68,11 +73,11 @@ export async function runRefundIncrementalTest(t: GlobalTestState) {
// Make wallet pay for the order
- const r1 = await wallet.client.call(WalletApiOperation.PreparePayForUri, {
+ const r1 = await walletClient.call(WalletApiOperation.PreparePayForUri, {
talerPayUri: orderStatus.taler_pay_uri,
});
- await wallet.client.call(WalletApiOperation.ConfirmPay, {
+ await walletClient.call(WalletApiOperation.ConfirmPay, {
proposalId: r1.proposalId,
});
@@ -94,15 +99,15 @@ export async function runRefundIncrementalTest(t: GlobalTestState) {
console.log("first refund increase response", ref);
{
- let wr = await wallet.client.call(WalletApiOperation.StartRefundQuery, {
+ let wr = await walletClient.call(WalletApiOperation.StartRefundQuery, {
transactionId: r1.transactionId,
});
- await wallet.runUntilDone();
- console.log(wr);
- const txs = await wallet.client.call(
- WalletApiOperation.GetTransactions,
+ await walletClient.call(
+ WalletApiOperation.TestingWaitTransactionsFinal,
{},
);
+ console.log(wr);
+ const txs = await walletClient.call(WalletApiOperation.GetTransactions, {});
console.log(
"transactions after applying first refund:",
JSON.stringify(txs, undefined, 2),
@@ -136,10 +141,13 @@ export async function runRefundIncrementalTest(t: GlobalTestState) {
console.log("third refund increase response", ref);
{
- let wr = await wallet.client.call(WalletApiOperation.StartRefundQuery, {
+ let wr = await walletClient.call(WalletApiOperation.StartRefundQuery, {
transactionId: r1.transactionId,
});
- await wallet.runUntilDone();
+ await walletClient.call(
+ WalletApiOperation.TestingWaitTransactionsFinal,
+ {},
+ );
console.log(wr);
}
@@ -153,25 +161,17 @@ export async function runRefundIncrementalTest(t: GlobalTestState) {
console.log(JSON.stringify(orderStatus, undefined, 2));
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
- const bal = await wallet.client.call(WalletApiOperation.GetBalances, {});
+ const bal = await walletClient.call(WalletApiOperation.GetBalances, {});
console.log(JSON.stringify(bal, undefined, 2));
{
- const txs = await wallet.client.call(
- WalletApiOperation.GetTransactions,
- {},
- );
+ const txs = await walletClient.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",
- ]);
+ t.assertDeepEqual(txTypes, ["withdrawal", "payment", "refund", "refund"]);
for (const tx of txs.transactions) {
if (tx.type !== TransactionType.Refund) {
diff --git a/packages/taler-harness/src/integrationtests/test-revocation.ts b/packages/taler-harness/src/integrationtests/test-revocation.ts
index 0fbb4960e..04707e51a 100644
--- a/packages/taler-harness/src/integrationtests/test-revocation.ts
+++ b/packages/taler-harness/src/integrationtests/test-revocation.ts
@@ -213,3 +213,4 @@ export async function runRevocationTest(t: GlobalTestState) {
runRevocationTest.timeoutMs = 120000;
runRevocationTest.suites = ["wallet"];
+runRevocationTest.excludeByDefault = true; \ No newline at end of file
diff --git a/packages/taler-harness/src/integrationtests/test-simple-payment.ts b/packages/taler-harness/src/integrationtests/test-simple-payment.ts
index 82fa5f21d..58ab61435 100644
--- a/packages/taler-harness/src/integrationtests/test-simple-payment.ts
+++ b/packages/taler-harness/src/integrationtests/test-simple-payment.ts
@@ -1,6 +1,6 @@
/*
This file is part of GNU Taler
- (C) 2020 Taler Systems S.A.
+ (C) 2023 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
@@ -20,11 +20,10 @@
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState } from "../harness/harness.js";
import {
- createSimpleTestkudosEnvironmentV2,
withdrawViaBankV2,
makeTestPaymentV2,
+ useSharedTestkudosEnvironment,
} from "../harness/helpers.js";
-import { j2s } from "@gnu-taler/taler-util";
/**
* Run test for basic, bank-integrated withdrawal and payment.
@@ -33,7 +32,7 @@ export async function runSimplePaymentTest(t: GlobalTestState) {
// Set up test environment
const { walletClient, bank, exchange, merchant } =
- await createSimpleTestkudosEnvironmentV2(t);
+ await useSharedTestkudosEnvironment(t);
// Withdraw digital cash into the wallet.
diff --git a/packages/taler-harness/src/integrationtests/test-tipping.ts b/packages/taler-harness/src/integrationtests/test-tipping.ts
index 332f702d7..53d7f08c8 100644
--- a/packages/taler-harness/src/integrationtests/test-tipping.ts
+++ b/packages/taler-harness/src/integrationtests/test-tipping.ts
@@ -18,8 +18,8 @@
* Imports.
*/
import {
+ BankAccessApiClient,
WalletApiOperation,
- BankApi,
WireGatewayApiClient,
} from "@gnu-taler/taler-wallet-core";
import {
@@ -28,7 +28,7 @@ import {
MerchantPrivateApi,
getWireMethodForTest,
} from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
+import { createSimpleTestkudosEnvironmentV2 } from "../harness/helpers.js";
import { TransactionMajorState } from "@gnu-taler/taler-util";
/**
@@ -37,10 +37,14 @@ import { TransactionMajorState } from "@gnu-taler/taler-util";
export async function runTippingTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, merchant, exchangeBankAccount } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, merchant, exchangeBankAccount } =
+ await createSimpleTestkudosEnvironmentV2(t);
- const mbu = await BankApi.createRandomBankUser(bank);
+ const bankAccessApiClient = new BankAccessApiClient({
+ allowHttp: true,
+ baseUrl: bank.bankAccessApiBaseUrl,
+ });
+ const mbu = await bankAccessApiClient.createRandomBankUser();
const merchantClient = new MerchantApiClient(
merchant.makeInstanceBaseUrl("default"),
@@ -99,7 +103,7 @@ export async function runTippingTest(t: GlobalTestState) {
console.log("created tip", tip);
const doTip = async (): Promise<void> => {
- const ptr = await wallet.client.call(WalletApiOperation.PrepareReward, {
+ const ptr = await walletClient.call(WalletApiOperation.PrepareReward, {
talerRewardUri: tip.taler_reward_uri,
});
@@ -108,19 +112,22 @@ export async function runTippingTest(t: GlobalTestState) {
t.assertAmountEquals(ptr.rewardAmountRaw, "TESTKUDOS:5");
t.assertAmountEquals(ptr.rewardAmountEffective, "TESTKUDOS:4.85");
- await wallet.client.call(WalletApiOperation.AcceptReward, {
+ await walletClient.call(WalletApiOperation.AcceptReward, {
walletRewardId: ptr.walletRewardId,
});
- await wallet.runUntilDone();
+ await walletClient.call(
+ WalletApiOperation.TestingWaitTransactionsFinal,
+ {},
+ );
- const bal = await wallet.client.call(WalletApiOperation.GetBalances, {});
+ const bal = await walletClient.call(WalletApiOperation.GetBalances, {});
console.log(bal);
t.assertAmountEquals(bal.balances[0].available, "TESTKUDOS:4.85");
- const txns = await wallet.client.call(
+ const txns = await walletClient.call(
WalletApiOperation.GetTransactions,
{},
);
@@ -128,7 +135,10 @@ export async function runTippingTest(t: GlobalTestState) {
console.log("Transactions:", JSON.stringify(txns, undefined, 2));
t.assertDeepEqual(txns.transactions[0].type, "reward");
- t.assertDeepEqual(txns.transactions[0].txState.major, TransactionMajorState.Done);
+ t.assertDeepEqual(
+ txns.transactions[0].txState.major,
+ TransactionMajorState.Done,
+ );
t.assertAmountEquals(
txns.transactions[0].amountEffective,
"TESTKUDOS:4.85",
diff --git a/packages/taler-harness/src/integrationtests/test-tos-format.ts b/packages/taler-harness/src/integrationtests/test-tos-format.ts
new file mode 100644
index 000000000..e6087af9d
--- /dev/null
+++ b/packages/taler-harness/src/integrationtests/test-tos-format.ts
@@ -0,0 +1,101 @@
+/*
+ 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 {
+ createSimpleTestkudosEnvironmentV2,
+} from "../harness/helpers.js";
+import * as fs from "fs";
+
+/**
+ * Run test for basic, bank-integrated withdrawal and payment.
+ */
+export async function runTermOfServiceFormatTest(t: GlobalTestState) {
+ // Set up test environment
+ const tosDir = t.testDir + `/tos/`;
+ const langs = ["es", "en", "de"]
+
+ langs.forEach(l => {
+ const langDir = tosDir + l + "/"
+ fs.mkdirSync(langDir, { recursive: true });
+ fs.writeFileSync(langDir + "v1.txt", "text content");
+ fs.writeFileSync(langDir + "v1.md", "markdown content");
+ fs.writeFileSync(langDir + "v1.html", "html content");
+ });
+
+ const { walletClient, exchange, } =
+ await createSimpleTestkudosEnvironmentV2(t, undefined, {
+ additionalExchangeConfig: (ex) => {
+ ex.changeConfig((cfg) => {
+ cfg.setString("exchange", "terms_etag", "v1")
+ cfg.setString("exchange", "terms_dir", tosDir)
+ })
+ }
+ });
+
+
+ {
+ const tos = await walletClient.client.call(WalletApiOperation.GetExchangeTos, {
+ exchangeBaseUrl: exchange.baseUrl,
+ })
+
+ t.assertDeepEqual(tos.content, "text content");
+ }
+
+ {
+ const tos = await walletClient.client.call(WalletApiOperation.GetExchangeTos, {
+ exchangeBaseUrl: exchange.baseUrl,
+ acceptedFormat: ["text/html"]
+ })
+
+ t.assertDeepEqual(tos.content, "html content");
+ }
+
+ {
+ const tos = await walletClient.client.call(WalletApiOperation.GetExchangeTos, {
+ exchangeBaseUrl: exchange.baseUrl,
+ acceptedFormat: ["text/markdown"]
+ })
+
+ t.assertDeepEqual(tos.content, "markdown content");
+ }
+
+ {
+ const tos = await walletClient.client.call(WalletApiOperation.GetExchangeTos, {
+ exchangeBaseUrl: exchange.baseUrl,
+ acceptedFormat: ["text/markdown", "text/html"]
+ })
+
+ // prefer markdown since its the first one in the list
+ t.assertDeepEqual(tos.content, "markdown content");
+ }
+
+ {
+ const tos = await walletClient.client.call(WalletApiOperation.GetExchangeTos, {
+ exchangeBaseUrl: exchange.baseUrl,
+ acceptedFormat: ["text/pdf", "text/html"]
+ })
+
+ // there is no pdf so fallback in html
+ t.assertDeepEqual(tos.content, "html content");
+ }
+}
+
+runTermOfServiceFormatTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-backup-basic.ts b/packages/taler-harness/src/integrationtests/test-wallet-backup-basic.ts
index f36e2e4f1..5321cf5c7 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-backup-basic.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-backup-basic.ts
@@ -22,7 +22,9 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState, WalletCli } from "../harness/harness.js";
import {
createSimpleTestkudosEnvironment,
+ createSimpleTestkudosEnvironmentV2,
withdrawViaBank,
+ withdrawViaBankV2,
} from "../harness/helpers.js";
import { SyncService } from "../harness/sync.js";
@@ -32,8 +34,8 @@ import { SyncService } from "../harness/sync.js";
export async function runWalletBackupBasicTest(t: GlobalTestState) {
// Set up test environment
- const { commonDb, merchant, wallet, bank, exchange } =
- await createSimpleTestkudosEnvironment(t);
+ const { commonDb, merchant, walletClient, bank, exchange } =
+ await createSimpleTestkudosEnvironmentV2(t);
const sync = await SyncService.create(t, {
currency: "TESTKUDOS",
@@ -49,32 +51,32 @@ export async function runWalletBackupBasicTest(t: GlobalTestState) {
await sync.start();
await sync.pingUntilAvailable();
- await wallet.client.call(WalletApiOperation.AddBackupProvider, {
+ await walletClient.call(WalletApiOperation.AddBackupProvider, {
backupProviderBaseUrl: sync.baseUrl,
activate: false,
name: sync.baseUrl,
});
{
- const bi = await wallet.client.call(WalletApiOperation.GetBackupInfo, {});
+ const bi = await walletClient.call(WalletApiOperation.GetBackupInfo, {});
t.assertDeepEqual(bi.providers[0].active, false);
}
- await wallet.client.call(WalletApiOperation.AddBackupProvider, {
+ await walletClient.call(WalletApiOperation.AddBackupProvider, {
backupProviderBaseUrl: sync.baseUrl,
activate: true,
name: sync.baseUrl,
});
{
- const bi = await wallet.client.call(WalletApiOperation.GetBackupInfo, {});
+ const bi = await walletClient.call(WalletApiOperation.GetBackupInfo, {});
t.assertDeepEqual(bi.providers[0].active, true);
}
- await wallet.client.call(WalletApiOperation.RunBackupCycle, {});
+ await walletClient.call(WalletApiOperation.RunBackupCycle, {});
{
- const bi = await wallet.client.call(WalletApiOperation.GetBackupInfo, {});
+ const bi = await walletClient.call(WalletApiOperation.GetBackupInfo, {});
console.log(bi);
t.assertDeepEqual(
bi.providers[0].paymentStatus.type,
@@ -82,32 +84,32 @@ export async function runWalletBackupBasicTest(t: GlobalTestState) {
);
}
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:10" });
+ await withdrawViaBankV2(t, { walletClient, bank, exchange, amount: "TESTKUDOS:10" });
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
- await wallet.client.call(WalletApiOperation.RunBackupCycle, {});
+ await walletClient.call(WalletApiOperation.RunBackupCycle, {});
{
- const bi = await wallet.client.call(WalletApiOperation.GetBackupInfo, {});
+ const bi = await walletClient.call(WalletApiOperation.GetBackupInfo, {});
console.log(bi);
}
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:5" });
+ await withdrawViaBankV2(t, { walletClient, bank, exchange, amount: "TESTKUDOS:5" });
- await wallet.client.call(WalletApiOperation.RunBackupCycle, {});
+ await walletClient.call(WalletApiOperation.RunBackupCycle, {});
{
- const bi = await wallet.client.call(WalletApiOperation.GetBackupInfo, {});
+ const bi = await walletClient.call(WalletApiOperation.GetBackupInfo, {});
console.log(bi);
}
- const backupRecovery = await wallet.client.call(
+ const backupRecovery = await walletClient.call(
WalletApiOperation.ExportBackupRecovery,
{},
);
- const txs = await wallet.client.call(WalletApiOperation.GetTransactions, {});
+ const txs = await walletClient.call(WalletApiOperation.GetTransactions, {});
console.log(`backed up transactions ${j2s(txs)}`);
const wallet2 = new WalletCli(t, "wallet2");
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-backup-doublespend.ts b/packages/taler-harness/src/integrationtests/test-wallet-backup-doublespend.ts
index 2aceab86e..e3e18d5a4 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-backup-doublespend.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-backup-doublespend.ts
@@ -21,21 +21,22 @@ import { PreparePayResultType } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import {
GlobalTestState,
- WalletCli,
MerchantPrivateApi,
+ WalletCli,
} from "../harness/harness.js";
import {
- createSimpleTestkudosEnvironment,
- makeTestPayment,
+ createSimpleTestkudosEnvironmentV2,
+ makeTestPaymentV2,
withdrawViaBank,
+ withdrawViaBankV2
} 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 { commonDb, merchant, walletClient, bank, exchange } =
+ await createSimpleTestkudosEnvironmentV2(t);
const sync = await SyncService.create(t, {
currency: "TESTKUDOS",
@@ -51,21 +52,21 @@ export async function runWalletBackupDoublespendTest(t: GlobalTestState) {
await sync.start();
await sync.pingUntilAvailable();
- await wallet.client.call(WalletApiOperation.AddBackupProvider, {
+ await walletClient.call(WalletApiOperation.AddBackupProvider, {
backupProviderBaseUrl: sync.baseUrl,
activate: true,
name: sync.baseUrl,
});
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:10" });
+ await withdrawViaBankV2(t, { walletClient, bank, exchange, amount: "TESTKUDOS:10" });
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
- await wallet.client.call(WalletApiOperation.RunBackupCycle, {});
- await wallet.runUntilDone();
- await wallet.client.call(WalletApiOperation.RunBackupCycle, {});
+ await walletClient.call(WalletApiOperation.RunBackupCycle, {});
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
+ await walletClient.call(WalletApiOperation.RunBackupCycle, {});
- const backupRecovery = await wallet.client.call(
+ const backupRecovery = await walletClient.call(
WalletApiOperation.ExportBackupRecovery,
{},
);
@@ -80,23 +81,23 @@ export async function runWalletBackupDoublespendTest(t: GlobalTestState) {
console.log(
"wallet1 balance before spend:",
- await wallet.client.call(WalletApiOperation.GetBalances, {}),
+ await walletClient.call(WalletApiOperation.GetBalances, {}),
);
- await makeTestPayment(t, {
+ await makeTestPaymentV2(t, {
merchant,
- wallet,
+ walletClient,
order: {
summary: "foo",
amount: "TESTKUDOS:7",
},
});
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
console.log(
"wallet1 balance after spend:",
- await wallet.client.call(WalletApiOperation.GetBalances, {}),
+ await walletClient.call(WalletApiOperation.GetBalances, {}),
);
{
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-balance.ts b/packages/taler-harness/src/integrationtests/test-wallet-balance.ts
index b5b1917a6..0f75bd96e 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-balance.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-balance.ts
@@ -30,7 +30,11 @@ import {
setupDb,
WalletCli,
} from "../harness/harness.js";
-import { withdrawViaBank } from "../harness/helpers.js";
+import {
+ createSimpleTestkudosEnvironmentV2,
+ withdrawViaBank,
+ withdrawViaBankV2,
+} from "../harness/helpers.js";
/**
* Test for wallet balance error messages / different types of insufficient balance.
@@ -41,72 +45,17 @@ import { withdrawViaBank } from "../harness/helpers.js";
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);
+ const { merchant, walletClient, exchange, bank } =
+ await createSimpleTestkudosEnvironmentV2(t);
// Withdraw digital cash into the wallet.
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ await withdrawViaBankV2(t, {
+ walletClient,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:20",
+ });
const order = {
summary: "Buy me!",
@@ -126,7 +75,7 @@ export async function runWalletBalanceTest(t: GlobalTestState) {
// Make wallet pay for the order
- const preparePayResult = await wallet.client.call(
+ const preparePayResult = await walletClient.call(
WalletApiOperation.PreparePayForUri,
{
talerPayUri: orderStatus.taler_pay_uri,
@@ -152,7 +101,7 @@ export async function runWalletBalanceTest(t: GlobalTestState) {
Amounts.isZero(preparePayResult.balanceDetails.balanceMerchantDepositable),
);
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
}
runWalletBalanceTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts b/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts
index c384a6e74..58f564f34 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts
@@ -37,7 +37,7 @@ import {
withdrawCoin,
} from "@gnu-taler/taler-wallet-core";
import { GlobalTestState } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
+import { createSimpleTestkudosEnvironmentV2 } from "../harness/helpers.js";
/**
* Run test for basic, bank-integrated withdrawal and payment.
@@ -45,7 +45,7 @@ import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
export async function runWalletDblessTest(t: GlobalTestState) {
// Set up test environment
- const { bank, exchange } = await createSimpleTestkudosEnvironment(t);
+ const { bank, exchange } = await createSimpleTestkudosEnvironmentV2(t);
const http = createPlatformHttpLib({
allowHttp: true,
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts b/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts
index 810250f53..c70fd51d4 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts
@@ -18,27 +18,24 @@
* Imports.
*/
import {
- Amounts,
Duration,
NotificationType,
- PreparePayResultType,
TransactionMajorState,
} from "@gnu-taler/taler-util";
import {
- BankAccessApi,
- BankApi,
+ BankAccessApiClient,
WalletApiOperation,
} from "@gnu-taler/taler-wallet-core";
import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
import {
ExchangeService,
FakebankService,
- getRandomIban,
GlobalTestState,
MerchantService,
- setupDb,
WalletClient,
WalletService,
+ getRandomIban,
+ setupDb,
} from "../harness/harness.js";
/**
@@ -126,10 +123,14 @@ export async function runWalletNotificationsTest(t: GlobalTestState) {
skipDefaults: true,
});
- const user = await BankApi.createRandomBankUser(bank);
- const wop = await BankAccessApi.createWithdrawalOperation(
- bank,
- user,
+ const bankAccessApiClient = new BankAccessApiClient({
+ allowHttp: true,
+ baseUrl: bank.bankAccessApiBaseUrl,
+ });
+ const user = await bankAccessApiClient.createRandomBankUser();
+ bankAccessApiClient.setAuth(user);
+ const wop = await bankAccessApiClient.createWithdrawalOperation(
+ user.username,
"TESTKUDOS:20",
);
@@ -163,7 +164,7 @@ export async function runWalletNotificationsTest(t: GlobalTestState) {
// Confirm it
- await BankApi.confirmWithdrawalOperation(bank, user, wop);
+ await bankAccessApiClient.confirmWithdrawalOperation(user.username, wop);
await withdrawalFinishedReceivedPromise;
}
diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-abort-bank.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-abort-bank.ts
index bf2dc0133..c3069c317 100644
--- a/packages/taler-harness/src/integrationtests/test-withdrawal-abort-bank.ts
+++ b/packages/taler-harness/src/integrationtests/test-withdrawal-abort-bank.ts
@@ -20,8 +20,7 @@
import { TalerErrorCode } from "@gnu-taler/taler-util";
import {
WalletApiOperation,
- BankApi,
- BankAccessApi,
+ BankAccessApiClient,
} from "@gnu-taler/taler-wallet-core";
import { GlobalTestState } from "../harness/harness.js";
import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
@@ -36,10 +35,14 @@ export async function runWithdrawalAbortBankTest(t: GlobalTestState) {
// Create a withdrawal operation
- const user = await BankApi.createRandomBankUser(bank);
- const wop = await BankAccessApi.createWithdrawalOperation(
- bank,
- user,
+ const bankAccessApiClient = new BankAccessApiClient({
+ allowHttp: true,
+ baseUrl: bank.bankAccessApiBaseUrl,
+ });
+ const user = await bankAccessApiClient.createRandomBankUser();
+ bankAccessApiClient.setAuth(user);
+ const wop = await bankAccessApiClient.createWithdrawalOperation(
+ user.username,
"TESTKUDOS:10",
);
@@ -53,8 +56,7 @@ export async function runWithdrawalAbortBankTest(t: GlobalTestState) {
// Abort it
- await BankApi.abortWithdrawalOperation(bank, user, wop);
- //await BankApi.confirmWithdrawalOperation(bank, user, wop);
+ await bankAccessApiClient.abortWithdrawalOperation(user.username, wop);
// Withdraw
diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts
index 396f0f03f..61687ec02 100644
--- a/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts
+++ b/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts
@@ -19,11 +19,7 @@
*/
import { GlobalTestState } from "../harness/harness.js";
import { createSimpleTestkudosEnvironmentV2 } from "../harness/helpers.js";
-import {
- WalletApiOperation,
- BankApi,
- BankAccessApi,
-} from "@gnu-taler/taler-wallet-core";
+import { BankAccessApiClient, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import {
j2s,
NotificationType,
@@ -44,10 +40,14 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) {
// Create a withdrawal operation
- const user = await BankApi.createRandomBankUser(bank);
- const wop = await BankAccessApi.createWithdrawalOperation(
- bank,
- user,
+ const bankAccessApiClient = new BankAccessApiClient({
+ allowHttp: true,
+ baseUrl: bank.bankAccessApiBaseUrl,
+ });
+ const user = await bankAccessApiClient.createRandomBankUser();
+ bankAccessApiClient.setAuth(user);
+ const wop = await bankAccessApiClient.createWithdrawalOperation(
+ user.username,
"TESTKUDOS:10",
);
@@ -129,7 +129,7 @@ export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) {
// Confirm it
- await BankApi.confirmWithdrawalOperation(bank, user, wop);
+ await bankAccessApiClient.confirmWithdrawalOperation(user.username, wop);
await withdrawalBankConfirmedCond;
diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts
index 065b134c4..06355b964 100644
--- a/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts
+++ b/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts
@@ -26,6 +26,7 @@ import {
} from "../harness/harness.js";
import {
BankAccessApi,
+ BankAccessApiClient,
BankApi,
WalletApiOperation,
} from "@gnu-taler/taler-wallet-core";
@@ -112,8 +113,13 @@ export async function runWithdrawalFeesTest(t: GlobalTestState) {
const amount = "TESTKUDOS:7.5";
- const user = await BankApi.createRandomBankUser(bank);
- const wop = await BankAccessApi.createWithdrawalOperation(bank, user, amount);
+ const bankAccessApiClient = new BankAccessApiClient({
+ allowHttp: true,
+ baseUrl: bank.bankAccessApiBaseUrl,
+ });
+ const user = await bankAccessApiClient.createRandomBankUser();
+ bankAccessApiClient.setAuth(user);
+ const wop = await bankAccessApiClient.createWithdrawalOperation(user.username, amount);
// Hand it to the wallet
@@ -150,10 +156,7 @@ export async function runWithdrawalFeesTest(t: GlobalTestState) {
// Confirm it
- await BankApi.confirmWithdrawalOperation(bank, user, wop);
-
- await exchange.runWirewatchOnce();
-
+ await bankAccessApiClient.confirmWithdrawalOperation(user.username, wop);
await wallet.runUntilDone();
// Check balance
diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-huge.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-huge.ts
index f56e4d24d..a9d544ee0 100644
--- a/packages/taler-harness/src/integrationtests/test-withdrawal-huge.ts
+++ b/packages/taler-harness/src/integrationtests/test-withdrawal-huge.ts
@@ -27,7 +27,11 @@ import {
} from "../harness/harness.js";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
-import { NotificationType, TransactionMajorState, URL } from "@gnu-taler/taler-util";
+import {
+ NotificationType,
+ TransactionMajorState,
+ URL,
+} from "@gnu-taler/taler-util";
/**
* Withdraw a high amount. Mostly intended as a perf test.
@@ -84,7 +88,8 @@ export async function runWithdrawalHugeTest(t: GlobalTestState) {
await wallet.connect();
const withdrawalFinishedCond = wallet.waitForNotificationCond(
- (wn) => wn.type === NotificationType.TransactionStateTransition &&
+ (wn) =>
+ wn.type === NotificationType.TransactionStateTransition &&
wn.transactionId.startsWith("txn:withdrawal:") &&
wn.newTxState.major === TransactionMajorState.Done,
);
diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-manual.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-manual.ts
index a356a5c1a..d49235f89 100644
--- a/packages/taler-harness/src/integrationtests/test-withdrawal-manual.ts
+++ b/packages/taler-harness/src/integrationtests/test-withdrawal-manual.ts
@@ -17,14 +17,14 @@
/**
* Imports.
*/
-import { GlobalTestState } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
+import { AbsoluteTime, Logger, j2s } from "@gnu-taler/taler-util";
import {
+ BankAccessApiClient,
WalletApiOperation,
- BankApi,
WireGatewayApiClient,
} from "@gnu-taler/taler-wallet-core";
-import { AbsoluteTime, j2s, Logger } from "@gnu-taler/taler-util";
+import { GlobalTestState } from "../harness/harness.js";
+import { createSimpleTestkudosEnvironmentV2 } from "../harness/helpers.js";
const logger = new Logger("test-withdrawal-manual.ts");
@@ -34,14 +34,19 @@ const logger = new Logger("test-withdrawal-manual.ts");
export async function runWithdrawalManualTest(t: GlobalTestState) {
// Set up test environment
- const { wallet, bank, exchange, exchangeBankAccount } =
- await createSimpleTestkudosEnvironment(t);
+ const { walletClient, bank, exchange, exchangeBankAccount } =
+ await createSimpleTestkudosEnvironmentV2(t);
// Create a withdrawal operation
- const user = await BankApi.createRandomBankUser(bank);
+ const bankAccessApiClient = new BankAccessApiClient({
+ baseUrl: bank.bankAccessApiBaseUrl,
+ allowHttp: true,
+ });
+
+ const user = await bankAccessApiClient.createRandomBankUser();
- await wallet.client.call(WalletApiOperation.AddExchange, {
+ await walletClient.call(WalletApiOperation.AddExchange, {
exchangeBaseUrl: exchange.baseUrl,
});
@@ -50,7 +55,7 @@ export async function runWithdrawalManualTest(t: GlobalTestState) {
logger.info("starting AcceptManualWithdrawal request");
// We expect this to return immediately.
- const wres = await wallet.client.call(
+ const wres = await walletClient.call(
WalletApiOperation.AcceptManualWithdrawal,
{
exchangeBaseUrl: exchange.baseUrl,
@@ -84,11 +89,11 @@ export async function runWithdrawalManualTest(t: GlobalTestState) {
await exchange.runWirewatchOnce();
- await wallet.runUntilDone();
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
// Check balance
- const balResp = await wallet.client.call(WalletApiOperation.GetBalances, {});
+ const balResp = await walletClient.call(WalletApiOperation.GetBalances, {});
t.assertAmountEquals("TESTKUDOS:9.72", balResp.balances[0].available);
await t.shutdown();
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts
index 58e2a20f7..cbdca04b9 100644
--- a/packages/taler-harness/src/integrationtests/testrunner.ts
+++ b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { CancellationToken, Logger, minimatch } from "@gnu-taler/taler-util";
+import { CancellationToken, Logger, minimatch, setGlobalLogLevelFromString } from "@gnu-taler/taler-util";
import * as child_process from "child_process";
import * as fs from "fs";
import * as os from "os";
@@ -104,6 +104,7 @@ import { runExchangeDepositTest } from "./test-exchange-deposit.js";
import { runPeerRepairTest } from "./test-peer-repair.js";
import { runPaymentShareTest } from "./test-payment-share.js";
import { runSimplePaymentTest } from "./test-simple-payment.js";
+import { runTermOfServiceFormatTest } from "./test-tos-format.js";
/**
* Test runner.
@@ -200,6 +201,7 @@ const allTests: TestMainFunction[] = [
runWithdrawalFakebankTest,
runWithdrawalFeesTest,
runWithdrawalHugeTest,
+ runTermOfServiceFormatTest,
];
export interface TestRunSpec {
diff --git a/packages/taler-harness/src/sandcastle-config.ts b/packages/taler-harness/src/sandcastle-config.ts
new file mode 100644
index 000000000..a7f7233ac
--- /dev/null
+++ b/packages/taler-harness/src/sandcastle-config.ts
@@ -0,0 +1,10 @@
+// Work in progress.
+// TS-based schema for the sandcastle configuration.
+
+export interface SandcastleConfig {
+ currency: string;
+ merchant: {
+ apiKey: string;
+ baseUrl: string;
+ };
+}
diff --git a/packages/taler-util/src/logging.ts b/packages/taler-util/src/logging.ts
index c4b2a3da0..79fc49cdd 100644
--- a/packages/taler-util/src/logging.ts
+++ b/packages/taler-util/src/logging.ts
@@ -32,13 +32,17 @@ export enum LogLevel {
None = "none",
}
-export let globalLogLevel = LogLevel.Info;
+let globalLogLevel = LogLevel.Info;
+const byTagLogLevel: Record<string, LogLevel> = {};
+
+export function getGlobalLogLevel(): string {
+ return globalLogLevel;
+}
export function setGlobalLogLevelFromString(logLevelStr: string): void {
globalLogLevel = getLevelForString(logLevelStr);
}
-export const byTagLogLevel: Record<string, LogLevel> = {};
export function setLogLevelFromString(tag: string, logLevelStr: string): void {
byTagLogLevel[tag] = getLevelForString(logLevelStr);
}
@@ -98,7 +102,7 @@ function writeNodeLog(
* and uses the corresponding console.* method to log in the browser.
*/
export class Logger {
- constructor(private tag: string) {}
+ constructor(private tag: string) { }
shouldLogTrace(): boolean {
const level = byTagLogLevel[this.tag] ?? globalLogLevel;
diff --git a/packages/taler-util/src/talerconfig.ts b/packages/taler-util/src/talerconfig.ts
index 59c789cae..d86c58678 100644
--- a/packages/taler-util/src/talerconfig.ts
+++ b/packages/taler-util/src/talerconfig.ts
@@ -1,6 +1,6 @@
/*
This file is part of GNU Taler
- (C) 2020 Taler Systems S.A.
+ (C) 2020-2023 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
@@ -39,10 +39,30 @@ export class ConfigError extends Error {
}
}
+enum EntryOrigin {
+ /**
+ * From a default file.
+ */
+ DefaultFile = 1,
+ /**
+ * From a system/installation specific default value.
+ */
+ DefaultSystem = 2,
+ /**
+ * Loaded from file or string
+ */
+ Loaded = 3,
+ /**
+ * Changed after loading
+ */
+ Changed = 4,
+}
+
interface Entry {
value: string;
sourceLine: number;
sourceFile: string;
+ origin: EntryOrigin;
}
interface Section {
@@ -159,12 +179,12 @@ export function pathsub(
const r = lookup(inner, depth + 1);
if (r !== undefined) {
- s = s.substr(0, start) + r + s.substr(p + 1);
+ s = s.substring(0, start) + r + s.substring(p + 1);
l = start + r.length;
continue;
} else if (defaultValue !== undefined) {
const resolvedDefault = pathsub(defaultValue, lookup, depth + 1);
- s = s.substr(0, start) + resolvedDefault + s.substr(p + 1);
+ s = s.substring(0, start) + resolvedDefault + s.substring(p + 1);
l = start + resolvedDefault.length;
continue;
}
@@ -176,7 +196,7 @@ export function pathsub(
if (m && m[0]) {
const r = lookup(m[0], depth + 1);
if (r !== undefined) {
- s = s.substr(0, l) + r + s.substr(l + 1 + m[0].length);
+ s = s.substring(0, l) + r + s.substring(l + 1 + m[0].length);
l = l + r.length;
continue;
}
@@ -195,6 +215,7 @@ export interface LoadOptions {
export interface StringifyOptions {
diagnostics?: boolean;
+ excludeDefaults?: boolean;
}
export interface LoadedFile {
@@ -282,7 +303,11 @@ export class Configuration {
private nestLevel = 0;
- private loadFromFilename(filename: string, opts: LoadOptions = {}): void {
+ private loadFromFilename(
+ filename: string,
+ isDefaultSource: boolean,
+ opts: LoadOptions = {},
+ ): void {
filename = expandPath(filename);
const checkCycle = () => {
@@ -309,7 +334,7 @@ export class Configuration {
const oldNestLevel = this.nestLevel;
this.nestLevel += 1;
try {
- this.loadFromString(s, {
+ this.internalLoadFromString(s, isDefaultSource, {
...opts,
filename: filename,
});
@@ -318,7 +343,11 @@ export class Configuration {
}
}
- private loadGlob(parentFilename: string, fileglob: string): void {
+ private loadGlob(
+ parentFilename: string,
+ isDefaultSource: boolean,
+ fileglob: string,
+ ): void {
const resolvedParent = nodejs_fs.realpathSync(parentFilename);
const parentDir = nodejs_path.dirname(resolvedParent);
@@ -339,12 +368,16 @@ export class Configuration {
for (const f of files) {
if (globMatch(tail, f)) {
const fullPath = nodejs_path.join(head, f);
- this.loadFromFilename(fullPath);
+ this.loadFromFilename(fullPath, isDefaultSource);
}
}
}
- private loadSecret(sectionName: string, filename: string): void {
+ private loadSecret(
+ sectionName: string,
+ filename: string,
+ isDefaultSource: boolean,
+ ): void {
const sec = this.provideSection(sectionName);
sec.secretFilename = filename;
const otherCfg = new Configuration();
@@ -354,7 +387,7 @@ export class Configuration {
sec.inaccessible = true;
return;
}
- otherCfg.loadFromFilename(filename, {
+ otherCfg.loadFromFilename(filename, isDefaultSource, {
banDirectives: true,
});
const otherSec = otherCfg.provideSection(sectionName);
@@ -363,7 +396,11 @@ export class Configuration {
}
}
- loadFromString(s: string, opts: LoadOptions = {}): void {
+ private internalLoadFromString(
+ s: string,
+ isDefaultSource: boolean,
+ opts: LoadOptions = {},
+ ): void {
let lineNo = 0;
const fn = opts.filename ?? "<input>";
const reComment = /^\s*#.*$/;
@@ -399,7 +436,10 @@ export class Configuration {
);
}
const arg = directiveMatch[2].trim();
- this.loadFromFilename(normalizeInlineFilename(opts.filename, arg));
+ this.loadFromFilename(
+ normalizeInlineFilename(opts.filename, arg),
+ isDefaultSource,
+ );
break;
}
case "inline-secret": {
@@ -419,7 +459,7 @@ export class Configuration {
opts.filename,
sp[1],
);
- this.loadSecret(sp[0], secretFilename);
+ this.loadSecret(sp[0], secretFilename, isDefaultSource);
break;
}
case "inline-matching": {
@@ -429,7 +469,7 @@ export class Configuration {
`invalid configuration, @inline-matching@ directive in ${fn}:${lineNo} can only be used from a file`,
);
}
- this.loadGlob(opts.filename, arg);
+ this.loadGlob(opts.filename, isDefaultSource, arg);
break;
}
default:
@@ -462,6 +502,9 @@ export class Configuration {
value: val,
sourceFile: opts.filename ?? "<unknown>",
sourceLine: lineNo,
+ origin: isDefaultSource
+ ? EntryOrigin.DefaultFile
+ : EntryOrigin.Loaded,
};
continue;
}
@@ -471,6 +514,10 @@ export class Configuration {
}
}
+ loadFromString(s: string, opts: LoadOptions = {}): void {
+ return this.internalLoadFromString(s, false, opts);
+ }
+
private provideSection(section: string): Section {
const secNorm = section.toUpperCase();
if (this.sectionMap[secNorm]) {
@@ -496,6 +543,24 @@ export class Configuration {
value,
sourceLine: 0,
sourceFile: "<unknown>",
+ origin: EntryOrigin.Changed,
+ };
+ }
+
+ /**
+ * Set a string value to a value from default locations.
+ */
+ private setStringSystemDefault(
+ section: string,
+ option: string,
+ value: string,
+ ): void {
+ const sec = this.provideSection(section);
+ sec.entries[option.toUpperCase()] = {
+ value,
+ sourceLine: 0,
+ sourceFile: "<unknown>",
+ origin: EntryOrigin.DefaultSystem,
};
}
@@ -559,7 +624,7 @@ export class Configuration {
lookupVariable(x: string, depth: number = 0): string | undefined {
// We loop up options in PATHS in upper case, as option names
// are case insensitive
- const val = this.findEntry("PATHS", x)?.value;
+ let val = this.findEntry("PATHS", x)?.value;
if (val !== undefined) {
return pathsub(val, (v, d) => this.lookupVariable(v, d), depth);
}
@@ -578,30 +643,63 @@ export class Configuration {
);
}
- loadFrom(dirname: string): void {
+ loadDefaultsFromDir(dirname: string): void {
const files = nodejs_fs.readdirSync(dirname);
for (const f of files) {
const fn = nodejs_path.join(dirname, f);
- this.loadFromFilename(fn);
+ this.loadFromFilename(fn, true);
}
}
private loadDefaults(): void {
- let bc = process.env["TALER_BASE_CONFIG"];
- if (!bc) {
+ let baseConfigDir = process.env["TALER_BASE_CONFIG"];
+ if (!baseConfigDir) {
/* Try to locate the configuration based on the location
* of the taler-config binary. */
const path = which("taler-config");
if (path) {
- bc = nodejs_fs.realpathSync(
+ baseConfigDir = nodejs_fs.realpathSync(
nodejs_path.dirname(path) + "/../share/taler/config.d",
);
}
}
- if (!bc) {
- bc = "/usr/share/taler/config.d";
+ if (!baseConfigDir) {
+ baseConfigDir = "/usr/share/taler/config.d";
}
- this.loadFrom(bc);
+
+ let installPrefix = process.env["TALER_PREFIX"];
+ if (!installPrefix) {
+ /* Try to locate install path based on the location
+ * of the taler-config binary. */
+ const path = which("taler-config");
+ if (path) {
+ installPrefix = nodejs_fs.realpathSync(
+ nodejs_path.dirname(path) + "/..",
+ );
+ }
+ }
+ if (!installPrefix) {
+ installPrefix = "/usr";
+ }
+
+ this.setStringSystemDefault(
+ "PATHS",
+ "LIBEXECDIR",
+ `${installPrefix}/taler/libexec/`,
+ );
+ this.setStringSystemDefault(
+ "PATHS",
+ "DOCDIR",
+ `${installPrefix}/share/doc/taler/`,
+ );
+ this.setStringSystemDefault("PATHS", "ICONDIR", `${installPrefix}/share/icons/`);
+ this.setStringSystemDefault("PATHS", "LOCALEDIR", `${installPrefix}/share/locale/`);
+ this.setStringSystemDefault("PATHS", "PREFIX", `${installPrefix}/`);
+ this.setStringSystemDefault("PATHS", "BINDIR", `${installPrefix}/bin`);
+ this.setStringSystemDefault("PATHS", "LIBDIR", `${installPrefix}/lib/taler/`);
+ this.setStringSystemDefault("PATHS", "DATADIR", `${installPrefix}/share/taler/`);
+
+ this.loadDefaultsFromDir(baseConfigDir);
}
getDefaultConfigFilename(): string | undefined {
@@ -631,11 +729,13 @@ export class Configuration {
const cfg = new Configuration();
cfg.loadDefaults();
if (filename) {
- cfg.loadFromFilename(filename);
+ cfg.loadFromFilename(filename, false);
} else {
const fn = cfg.getDefaultConfigFilename();
if (fn) {
- cfg.loadFromFilename(fn);
+ // It's the default filename for the main config file,
+ // but we don't consider the values default values.
+ cfg.loadFromFilename(fn, false);
}
}
cfg.hintEntrypoint = filename;
@@ -657,26 +757,51 @@ export class Configuration {
}
for (const sectionName of Object.keys(this.sectionMap)) {
const sec = this.sectionMap[sectionName];
- if (opts.diagnostics && sec.secretFilename) {
- s += `# Secret section from ${sec.secretFilename}\n`;
- s += `# Secret accessible: ${!sec.inaccessible}\n`;
- }
- s += `[${sectionName}]\n`;
+ let headerWritten = false;
for (const optionName of Object.keys(sec.entries)) {
const entry = this.sectionMap[sectionName].entries[optionName];
+ if (
+ opts.excludeDefaults &&
+ (entry.origin === EntryOrigin.DefaultSystem ||
+ entry.origin === EntryOrigin.DefaultFile)
+ ) {
+ continue;
+ }
+ if (!headerWritten) {
+ if (opts.diagnostics && sec.secretFilename) {
+ s += `# Secret section from ${sec.secretFilename}\n`;
+ s += `# Secret accessible: ${!sec.inaccessible}\n`;
+ }
+ s += `[${sectionName}]\n`;
+ headerWritten = true;
+ }
if (entry !== undefined) {
if (opts.diagnostics) {
- s += `# ${entry.sourceFile}:${entry.sourceLine}\n`;
+ switch (entry.origin) {
+ case EntryOrigin.DefaultFile:
+ case EntryOrigin.Changed:
+ case EntryOrigin.Loaded:
+ s += `# ${entry.sourceFile}:${entry.sourceLine}\n`;
+ break;
+ case EntryOrigin.DefaultSystem:
+ s += `# (system/installation default)\n`;
+ break;
+ }
}
s += `${optionName} = ${entry.value}\n`;
}
}
- s += "\n";
+ if (headerWritten) {
+ s += "\n";
+ }
}
return s;
}
- write(filename: string): void {
- nodejs_fs.writeFileSync(filename, this.stringify());
+ write(filename: string, opts: { excludeDefaults?: boolean } = {}): void {
+ nodejs_fs.writeFileSync(
+ filename,
+ this.stringify({ excludeDefaults: opts.excludeDefaults }),
+ );
}
}
diff --git a/packages/taler-wallet-core/src/bank-api-client.ts b/packages/taler-wallet-core/src/bank-api-client.ts
index a7484b0b2..8e351cb48 100644
--- a/packages/taler-wallet-core/src/bank-api-client.ts
+++ b/packages/taler-wallet-core/src/bank-api-client.ts
@@ -267,8 +267,7 @@ export namespace BankAccessApi {
export interface BankAccessApiClientArgs {
baseUrl: string;
- username: string;
- password: string;
+ auth?: { username: string; password: string };
enableThrottling?: boolean;
allowHttp?: boolean;
}
@@ -330,7 +329,7 @@ export class WireGatewayApiClient {
* but it will be nice to have in utils to be used by others
*/
export class BankAccessApiClient {
- httpLib;
+ httpLib: HttpRequestLibrary;
constructor(private args: BankAccessApiClientArgs) {
this.httpLib = createPlatformHttpLib({
@@ -339,19 +338,33 @@ export class BankAccessApiClient {
});
}
- async getTransactions(): Promise<void> {
+ setAuth(auth: { username: string; password: string }) {
+ this.args.auth = auth;
+ }
+
+ private makeAuthHeader(): Record<string, string> {
+ if (!this.args.auth) {
+ return {};
+ }
+ const authHeaderValue = makeBasicAuthHeader(
+ this.args.auth.username,
+ this.args.auth.password,
+ );
+ return {
+ Authorization: authHeaderValue,
+ };
+ }
+
+ async getTransactions(username: string): Promise<void> {
+ const auth = this.args.auth;
const reqUrl = new URL(
- `accounts/${this.args.username}/transactions`,
+ `accounts/${username}/transactions`,
this.args.baseUrl,
);
- const authHeaderValue = makeBasicAuthHeader(
- this.args.username,
- this.args.password,
- );
const resp = await this.httpLib.fetch(reqUrl.href, {
method: "GET",
headers: {
- Authorization: authHeaderValue,
+ ...this.makeAuthHeader(),
},
});
@@ -360,24 +373,128 @@ export class BankAccessApiClient {
}
async createTransaction(
+ username: string,
req: BankAccessApiCreateTransactionRequest,
): Promise<any> {
const reqUrl = new URL(
- `accounts/${this.args.username}/transactions`,
+ `accounts/${username}/transactions`,
this.args.baseUrl,
);
- const authHeaderValue = makeBasicAuthHeader(
- this.args.username,
- this.args.password,
- );
+
const resp = await this.httpLib.fetch(reqUrl.href, {
method: "POST",
body: req,
- headers: {
- Authorization: authHeaderValue,
- },
+ headers: this.makeAuthHeader(),
});
return await readSuccessResponseJsonOrThrow(resp, codecForAny());
}
+
+ async registerAccount(
+ username: string,
+ password: string,
+ options: {
+ iban?: string;
+ },
+ ): Promise<BankUser> {
+ const url = new URL("testing/register", this.args.baseUrl);
+ const resp = await this.httpLib.fetch(url.href, {
+ method: "POST",
+ body: {
+ username,
+ password,
+ iban: options?.iban,
+ },
+ });
+ let paytoUri = `payto://x-taler-bank/localhost/${username}`;
+ if (resp.status !== 200 && resp.status !== 202 && resp.status !== 204) {
+ logger.error(`${j2s(await resp.json())}`);
+ throw TalerError.fromDetail(
+ TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR,
+ {
+ httpStatusCode: resp.status,
+ },
+ );
+ }
+ try {
+ // Pybank has no body, thus this might throw.
+ const respJson = await resp.json();
+ // LibEuFin demobank returns payto URI in response
+ if (respJson.paytoUri) {
+ paytoUri = respJson.paytoUri;
+ }
+ } catch (e) {
+ // Do nothing
+ }
+ return {
+ password,
+ username,
+ accountPaytoUri: paytoUri,
+ };
+ }
+
+ async createRandomBankUser(): Promise<BankUser> {
+ const username = "user-" + encodeCrock(getRandomBytes(10)).toLowerCase();
+ const password = "pw-" + encodeCrock(getRandomBytes(10)).toLowerCase();
+ // FIXME: This is just a temporary workaround, because demobank is running out of short IBANs
+ const iban = generateIban("DE", 15);
+ return await this.registerAccount(username, password, {
+ iban,
+ });
+ }
+
+ async createWithdrawalOperation(
+ user: string,
+ amount: string,
+ ): Promise<WithdrawalOperationInfo> {
+ const url = new URL(`accounts/${user}/withdrawals`, this.args.baseUrl);
+ const resp = await this.httpLib.fetch(url.href, {
+ method: "POST",
+ body: {
+ amount,
+ },
+ headers: this.makeAuthHeader(),
+ });
+ return readSuccessResponseJsonOrThrow(
+ resp,
+ codecForWithdrawalOperationInfo(),
+ );
+ }
+
+ async confirmWithdrawalOperation(
+ username: string,
+ wopi: WithdrawalOperationInfo,
+ ): Promise<void> {
+ const url = new URL(
+ `accounts/${username}/withdrawals/${wopi.withdrawal_id}/confirm`,
+ this.args.baseUrl,
+ );
+ logger.info(`confirming withdrawal operation via ${url.href}`);
+ const resp = await this.httpLib.fetch(url.href, {
+ method: "POST",
+ body: {},
+ headers: this.makeAuthHeader(),
+ });
+
+ logger.info(`response status ${resp.status}`);
+ const respJson = await readSuccessResponseJsonOrThrow(resp, codecForAny());
+
+ // FIXME: We don't check the status here!
+ }
+
+ async abortWithdrawalOperation(
+ accountName: string,
+ wopi: WithdrawalOperationInfo,
+ ): Promise<void> {
+ const url = new URL(
+ `accounts/${accountName}/withdrawals/${wopi.withdrawal_id}/abort`,
+ this.args.baseUrl,
+ );
+ const resp = await this.httpLib.fetch(url.href, {
+ method: "POST",
+ body: {},
+ headers: this.makeAuthHeader(),
+ });
+ await readSuccessResponseJsonOrThrow(resp, codecForAny());
+ }
}