gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: harness: remove deprecated te


From: gnunet
Subject: [taler-wallet-core] branch master updated: harness: remove deprecated testing APIs
Date: Tue, 05 Sep 2023 10:48:42 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new a60a1d867 harness: remove deprecated testing APIs
a60a1d867 is described below

commit a60a1d867cfe6a12f1e6fadfa037f022e9385107
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Sep 5 10:46:06 2023 +0200

    harness: remove deprecated testing APIs
---
 packages/taler-harness/src/env-full.ts             |   4 +-
 packages/taler-harness/src/harness/harness.ts      | 103 +++++--
 packages/taler-harness/src/harness/helpers.ts      | 326 +++------------------
 .../test-age-restrictions-merchant.ts              | 127 +++++---
 .../src/integrationtests/test-bank-api.ts          |   4 +-
 .../src/integrationtests/test-clause-schnorr.ts    |  32 +-
 .../integrationtests/test-exchange-management.ts   |   4 +-
 .../integrationtests/test-exchange-timetravel.ts   |  63 ++--
 .../src/integrationtests/test-fee-regression.ts    |   2 +-
 .../taler-harness/src/integrationtests/test-kyc.ts |   4 +-
 .../src/integrationtests/test-libeufin-basic.ts    |  32 +-
 .../test-merchant-exchange-confusion.ts            |  24 +-
 .../test-merchant-instances-delete.ts              |   4 +-
 .../integrationtests/test-merchant-instances.ts    |   4 +-
 .../integrationtests/test-merchant-refund-api.ts   |  49 ++--
 .../test-merchant-spec-public-orders.ts            |  61 ++--
 .../src/integrationtests/test-pay-paid.ts          |  22 +-
 .../src/integrationtests/test-payment-abort.ts     |  29 +-
 .../src/integrationtests/test-payment-fault.ts     |   2 +-
 .../src/integrationtests/test-payment-multiple.ts  |  27 +-
 .../src/integrationtests/test-payment-transient.ts |  15 +-
 .../src/integrationtests/test-refund-gone.ts       |  34 ++-
 .../src/integrationtests/test-revocation.ts        |  80 +++--
 .../test-timetravel-autorefresh.ts                 |  66 ++---
 .../integrationtests/test-timetravel-withdraw.ts   |  40 ++-
 .../integrationtests/test-wallet-backup-basic.ts   |  29 +-
 .../test-wallet-backup-doublespend.ts              |  47 +--
 .../integrationtests/test-wallet-notifications.ts  |   2 +-
 .../src/integrationtests/test-wallettesting.ts     |   2 +-
 .../integrationtests/test-withdrawal-abort-bank.ts |  20 +-
 .../src/integrationtests/test-withdrawal-fees.ts   |  24 +-
 .../src/integrationtests/testrunner.ts             |   2 +
 packages/taler-util/src/merchant-api-types.ts      |  35 +++
 packages/taler-util/src/time.ts                    |  14 +
 packages/taler-util/src/wallet-types.ts            |  10 +
 packages/taler-wallet-core/src/wallet-api-types.ts |  12 +
 packages/taler-wallet-core/src/wallet.ts           |   7 +
 37 files changed, 673 insertions(+), 689 deletions(-)

diff --git a/packages/taler-harness/src/env-full.ts 
b/packages/taler-harness/src/env-full.ts
index 3a684db0b..210d38e32 100644
--- a/packages/taler-harness/src/env-full.ts
+++ b/packages/taler-harness/src/env-full.ts
@@ -79,7 +79,7 @@ export async function runEnvFull(t: GlobalTestState): 
Promise<void> {
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
@@ -88,7 +88,7 @@ export async function runEnvFull(t: GlobalTestState): 
Promise<void> {
     ),
   });
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
diff --git a/packages/taler-harness/src/harness/harness.ts 
b/packages/taler-harness/src/harness/harness.ts
index 337f3ca44..b5197afd7 100644
--- a/packages/taler-harness/src/harness/harness.ts
+++ b/packages/taler-harness/src/harness/harness.ts
@@ -56,6 +56,7 @@ import {
   TippingReserveStatus,
   WalletNotification,
   codecForAny,
+  AccountAddDetails,
 } from "@gnu-taler/taler-util";
 import {
   createPlatformHttpLib,
@@ -760,19 +761,19 @@ export class ExchangeService implements 
ExchangeServiceInterface {
     return new ExchangeService(gc, ec, cfgFilename, keyPair);
   }
 
-  private currentTimetravel: Duration | undefined;
+  private currentTimetravelOffsetMs: number | undefined;
 
-  setTimetravel(t: Duration | undefined): void {
+  setTimetravel(t: number | undefined): void {
     if (this.isRunning()) {
       throw Error("can't set time travel while the exchange is running");
     }
-    this.currentTimetravel = t;
+    this.currentTimetravelOffsetMs = t;
   }
 
   private get timetravelArg(): string | undefined {
-    if (this.currentTimetravel && this.currentTimetravel.d_ms !== "forever") {
+    if (this.currentTimetravelOffsetMs != null) {
       // Convert to microseconds
-      return `--timetravel=+${this.currentTimetravel.d_ms * 1000}`;
+      return `--timetravel=+${this.currentTimetravelOffsetMs * 1000}`;
     }
     return undefined;
   }
@@ -1360,12 +1361,26 @@ export const harnessHttpLib = createPlatformHttpLib({
 });
 
 export class MerchantApiClient {
-  constructor(
-    private baseUrl: string,
-    public readonly auth: MerchantAuthConfiguration,
-  ) {}
+  /**
+   * Base URL for the particular instance that this merchant API client
+   * is for.
+   */
+  private baseUrl: string;
 
-  httpClient = createPlatformHttpLib({ allowHttp: true, enableThrottling: 
false });
+  readonly auth: MerchantAuthConfiguration;
+
+  constructor(baseUrl: string, auth?: MerchantAuthConfiguration) {
+    this.baseUrl = baseUrl;
+
+    this.auth = auth ?? {
+      method: "external",
+    };
+  }
+
+  httpClient = createPlatformHttpLib({
+    allowHttp: true,
+    enableThrottling: false,
+  });
 
   async changeAuth(auth: MerchantAuthConfiguration): Promise<void> {
     const url = new URL("private/auth", this.baseUrl);
@@ -1463,7 +1478,38 @@ export class MerchantApiClient {
     }
   }
 
-  makeAuthHeader(): Record<string, string> {
+  async createOrder(
+    req: MerchantPostOrderRequest,
+  ): Promise<MerchantPostOrderResponse> {
+    let url = new URL("private/orders", this.baseUrl);
+    const resp = await harnessHttpLib.fetch(url.href, {
+      method: "POST",
+      body: req,
+      headers: this.makeAuthHeader(),
+    });
+    return readSuccessResponseJsonOrThrow(
+      resp,
+      codecForMerchantPostOrderResponse(),
+    );
+  }
+
+  async queryPrivateOrderStatus(
+    query: PrivateOrderStatusQuery,
+  ): Promise<MerchantOrderPrivateStatusResponse> {
+    const reqUrl = new URL(`private/orders/${query.orderId}`, this.baseUrl);
+    if (query.sessionId) {
+      reqUrl.searchParams.set("session_id", query.sessionId);
+    }
+    const resp = await harnessHttpLib.fetch(reqUrl.href, {
+      headers: this.makeAuthHeader(),
+    });
+    return readSuccessResponseJsonOrThrow(
+      resp,
+      codecForMerchantOrderPrivateStatusResponse(),
+    );
+  }
+
+  private makeAuthHeader(): Record<string, string> {
     switch (this.auth.method) {
       case "external":
         return {};
@@ -1633,23 +1679,23 @@ export class MerchantService implements 
MerchantServiceInterface {
     private configFilename: string,
   ) {}
 
-  private currentTimetravel: Duration | undefined;
+  private currentTimetravelOffsetMs: number | undefined;
 
   private isRunning(): boolean {
     return !!this.proc;
   }
 
-  setTimetravel(t: Duration | undefined): void {
+  setTimetravel(t: number | undefined): void {
     if (this.isRunning()) {
       throw Error("can't set time travel while the exchange is running");
     }
-    this.currentTimetravel = t;
+    this.currentTimetravelOffsetMs = t;
   }
 
   private get timetravelArg(): string | undefined {
-    if (this.currentTimetravel && this.currentTimetravel.d_ms !== "forever") {
+    if (this.currentTimetravelOffsetMs != null) {
       // Convert to microseconds
-      return `--timetravel=+${this.currentTimetravel.d_ms * 1000}`;
+      return `--timetravel=+${this.currentTimetravelOffsetMs * 1000}`;
     }
     return undefined;
   }
@@ -1756,7 +1802,7 @@ export class MerchantService implements 
MerchantServiceInterface {
   }
 
   async addDefaultInstance(): Promise<void> {
-    return await this.addInstance({
+    return await this.addInstanceWithWireAccount({
       id: "default",
       name: "Default Instance",
       paytoUris: [getPayto("merchant-default")],
@@ -1766,7 +1812,10 @@ export class MerchantService implements 
MerchantServiceInterface {
     });
   }
 
-  async addInstance(
+  /**
+   * Add an instance together with a wire account.
+   */
+  async addInstanceWithWireAccount(
     instanceConfig: PartialMerchantInstanceConfig,
   ): Promise<void> {
     if (!this.proc) {
@@ -1798,12 +1847,20 @@ export class MerchantService implements 
MerchantServiceInterface {
         instanceConfig.defaultPayDelay ??
         Duration.toTalerProtocolDuration(Duration.getForever()),
     };
-    const httpLib = createPlatformHttpLib({
-      allowHttp: true,
-      enableThrottling: false,
-    });
-    const resp = await httpLib.fetch(url, { method: "POST", body });
+    const resp = await harnessHttpLib.fetch(url, { method: "POST", body });
     await expectSuccessResponseOrThrow(resp);
+
+    const accountCreateUrl = 
`http://localhost:${this.merchantConfig.httpPort}/instances/${instanceConfig.id}/private/accounts`;
+    for (const paytoUri of instanceConfig.paytoUris) {
+      const accountReq: AccountAddDetails = {
+        payto_uri: paytoUri,
+      };
+      const acctResp = await harnessHttpLib.fetch(accountCreateUrl, {
+        method: "POST",
+        body: accountReq,
+      });
+      await expectSuccessResponseOrThrow(acctResp);
+    }
   }
 
   makeInstanceBaseUrl(instanceName?: string): string {
diff --git a/packages/taler-harness/src/harness/helpers.ts 
b/packages/taler-harness/src/harness/helpers.ts
index d1d0ea104..39d411a46 100644
--- a/packages/taler-harness/src/harness/helpers.ts
+++ b/packages/taler-harness/src/harness/helpers.ts
@@ -53,6 +53,7 @@ import {
   FakebankService,
   getPayto,
   GlobalTestState,
+  MerchantApiClient,
   MerchantPrivateApi,
   MerchantService,
   MerchantServiceInterface,
@@ -107,114 +108,6 @@ export interface EnvOptions {
   additionalBankConfig?(b: BankService): void;
 }
 
-/**
- * Run a test case with a simple TESTKUDOS Taler environment, consisting
- * of one exchange, one bank and one merchant.
- *
- * @deprecated use {@link createSimpleTestkudosEnvironmentV2} instead
- */
-export async function createSimpleTestkudosEnvironment(
-  t: GlobalTestState,
-  coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS")),
-  opts: EnvOptions = {},
-): Promise<SimpleTestEnvironment> {
-  const db = await setupDb(t);
-
-  const bank = await BankService.create(t, {
-    allowRegistrations: true,
-    currency: "TESTKUDOS",
-    database: db.connStr,
-    httpPort: 8082,
-  });
-
-  const exchange = ExchangeService.create(t, {
-    name: "testexchange-1",
-    currency: "TESTKUDOS",
-    httpPort: 8081,
-    database: db.connStr,
-  });
-
-  const merchant = await MerchantService.create(t, {
-    name: "testmerchant-1",
-    currency: "TESTKUDOS",
-    httpPort: 8083,
-    database: db.connStr,
-  });
-
-  const exchangeBankAccount = await bank.createExchangeAccount(
-    "myexchange",
-    "x",
-  );
-  await exchange.addBankAccount("1", exchangeBankAccount);
-
-  bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
-
-  await bank.start();
-
-  await bank.pingUntilAvailable();
-
-  const ageMaskSpec = opts.ageMaskSpec;
-
-  if (ageMaskSpec) {
-    exchange.enableAgeRestrictions(ageMaskSpec);
-    // Enable age restriction for all coins.
-    exchange.addCoinConfigList(
-      coinConfig.map((x) => ({
-        ...x,
-        name: `${x.name}-age`,
-        ageRestricted: true,
-      })),
-    );
-    // For mixed age restrictions, we also offer coins without age restrictions
-    if (opts.mixedAgeRestriction) {
-      exchange.addCoinConfigList(
-        coinConfig.map((x) => ({ ...x, ageRestricted: false })),
-      );
-    }
-  } else {
-    exchange.addCoinConfigList(coinConfig);
-  }
-
-  await exchange.start();
-  await exchange.pingUntilAvailable();
-
-  merchant.addExchange(exchange);
-
-  await merchant.start();
-  await merchant.pingUntilAvailable();
-
-  await merchant.addInstance({
-    id: "default",
-    name: "Default Instance",
-    paytoUris: [getPayto("merchant-default")],
-    defaultWireTransferDelay: Duration.toTalerProtocolDuration(
-      Duration.fromSpec({ minutes: 1 }),
-    ),
-  });
-
-  await merchant.addInstance({
-    id: "minst1",
-    name: "minst1",
-    paytoUris: [getPayto("minst1")],
-    defaultWireTransferDelay: Duration.toTalerProtocolDuration(
-      Duration.fromSpec({ minutes: 1 }),
-    ),
-  });
-
-  console.log("setup done!");
-
-  const wallet = new WalletCli(t);
-
-  return {
-    commonDb: db,
-    exchange,
-    merchant,
-    wallet,
-    bank,
-    exchangeBankAccount,
-  };
-}
-
 export function getSharedTestDir(): string {
   return `/tmp/taler-harness@${process.env.USER}`;
 }
@@ -344,7 +237,7 @@ export async function useSharedTestkudosEnvironment(t: 
GlobalTestState) {
     await merchant.pingUntilAvailable();
 
     if (!prevSetupDone) {
-      await merchant.addInstance({
+      await merchant.addInstanceWithWireAccount({
         id: "default",
         name: "Default Instance",
         paytoUris: [getPayto("merchant-default")],
@@ -353,7 +246,7 @@ export async function useSharedTestkudosEnvironment(t: 
GlobalTestState) {
         ),
       });
 
-      await merchant.addInstance({
+      await merchant.addInstanceWithWireAccount({
         id: "minst1",
         name: "minst1",
         paytoUris: [getPayto("minst1")],
@@ -476,7 +369,7 @@ export async function createSimpleTestkudosEnvironmentV2(
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
@@ -485,7 +378,7 @@ export async function createSimpleTestkudosEnvironmentV2(
     ),
   });
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
@@ -554,7 +447,7 @@ export interface FaultyMerchantTestEnvironment {
   exchangeBankAccount: HarnessExchangeBankAccount;
   merchant: MerchantService;
   faultyMerchant: FaultInjectedMerchantService;
-  wallet: WalletCli;
+  walletClient: WalletClient;
 }
 
 /**
@@ -620,13 +513,13 @@ export async function 
createFaultInjectedMerchantTestkudosEnvironment(
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
   });
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
@@ -634,13 +527,15 @@ export async function 
createFaultInjectedMerchantTestkudosEnvironment(
 
   console.log("setup done!");
 
-  const wallet = new WalletCli(t);
+  const { walletClient } = await createWalletDaemonWithClient(t, {
+    name: "default",
+  });
 
   return {
     commonDb: db,
     exchange,
     merchant,
-    wallet,
+    walletClient,
     bank,
     exchangeBankAccount,
     faultyMerchant,
@@ -648,51 +543,6 @@ export async function 
createFaultInjectedMerchantTestkudosEnvironment(
   };
 }
 
-/**
- * Start withdrawing into the wallet.
- *
- * Only starts the operation, does not wait for it to finish.
- */
-export async function startWithdrawViaBank(
-  t: GlobalTestState,
-  p: {
-    wallet: WalletCli;
-    bank: BankService;
-    exchange: ExchangeServiceInterface;
-    amount: AmountString;
-    restrictAge?: number;
-  },
-): Promise<void> {
-  const { wallet, bank, exchange, amount } = p;
-
-  const user = await BankApi.createRandomBankUser(bank);
-  const wop = await BankAccessApi.createWithdrawalOperation(bank, user, 
amount);
-
-  // Hand it to the wallet
-
-  await wallet.client.call(WalletApiOperation.GetWithdrawalDetailsForUri, {
-    talerWithdrawUri: wop.taler_withdraw_uri,
-    restrictAge: p.restrictAge,
-  });
-
-  await wallet.runPending();
-
-  // Withdraw (AKA select)
-
-  await wallet.client.call(WalletApiOperation.AcceptBankIntegratedWithdrawal, {
-    exchangeBaseUrl: exchange.baseUrl,
-    talerWithdrawUri: wop.taler_withdraw_uri,
-    restrictAge: p.restrictAge,
-  });
-
-  // Confirm it
-
-  await BankApi.confirmWithdrawalOperation(bank, user, wop);
-
-  // We do *not* call runPending / runUntilDone on the wallet here.
-  // Some tests rely on the final withdraw failing.
-}
-
 export interface WithdrawViaBankResult {
   withdrawalFinishedCond: Promise<true>;
 }
@@ -751,131 +601,35 @@ export async function withdrawViaBankV2(
   };
 }
 
-/**
- * Withdraw balance.
- *
- * @deprecated use {@link withdrawViaBankV2 instead}
- */
-export async function withdrawViaBank(
-  t: GlobalTestState,
-  p: {
-    wallet: WalletCli;
-    bank: BankService;
-    exchange: ExchangeServiceInterface;
-    amount: AmountString;
-    restrictAge?: number;
-  },
-): Promise<void> {
-  const { wallet } = p;
-
-  await startWithdrawViaBank(t, p);
-
-  await wallet.runUntilDone();
-
-  // Check balance
-
-  await wallet.client.call(WalletApiOperation.GetBalances, {});
-}
-
-export async function applyTimeTravel(
-  timetravelDuration: Duration,
+export async function applyTimeTravelV2(
+  timetravelOffsetMs: number,
   s: {
     exchange?: ExchangeService;
     merchant?: MerchantService;
-    wallet?: WalletCli;
+    walletClient?: WalletClient;
   },
 ): Promise<void> {
   if (s.exchange) {
     await s.exchange.stop();
-    s.exchange.setTimetravel(timetravelDuration);
+    s.exchange.setTimetravel(timetravelOffsetMs);
     await s.exchange.start();
     await s.exchange.pingUntilAvailable();
   }
 
   if (s.merchant) {
     await s.merchant.stop();
-    s.merchant.setTimetravel(timetravelDuration);
+    s.merchant.setTimetravel(timetravelOffsetMs);
     await s.merchant.start();
     await s.merchant.pingUntilAvailable();
   }
 
-  if (s.wallet) {
-    s.wallet.setTimetravel(timetravelDuration);
+  if (s.walletClient) {
+    s.walletClient.call(WalletApiOperation.TestingSetTimetravel, {
+      offsetMs: timetravelOffsetMs,
+    });
   }
 }
 
-/**
- * Make a simple payment and check that it succeeded.
- *
- * @deprecated
- */
-export async function makeTestPayment(
-  t: GlobalTestState,
-  args: {
-    merchant: MerchantServiceInterface;
-    wallet: WalletCli;
-    order: Partial<MerchantContractTerms>;
-    instance?: string;
-  },
-  auth: WithAuthorization = {},
-): Promise<void> {
-  // Set up order.
-
-  const { wallet, merchant } = args;
-  const instance = args.instance ?? "default";
-
-  const orderResp = await MerchantPrivateApi.createOrder(
-    merchant,
-    instance,
-    {
-      order: args.order,
-    },
-    auth,
-  );
-
-  let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(
-    merchant,
-    {
-      orderId: orderResp.order_id,
-    },
-    auth,
-  );
-
-  t.assertTrue(orderStatus.order_status === "unpaid");
-
-  // Make wallet pay for the order
-
-  const preparePayResult = await wallet.client.call(
-    WalletApiOperation.PreparePayForUri,
-    {
-      talerPayUri: orderStatus.taler_pay_uri,
-    },
-  );
-
-  t.assertTrue(
-    preparePayResult.status === PreparePayResultType.PaymentPossible,
-  );
-
-  const r2 = await wallet.client.call(WalletApiOperation.ConfirmPay, {
-    proposalId: preparePayResult.proposalId,
-  });
-
-  t.assertTrue(r2.type === ConfirmPayResultType.Done);
-
-  // Check if payment was successful.
-
-  orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(
-    merchant,
-    {
-      orderId: orderResp.order_id,
-      instance,
-    },
-    auth,
-  );
-
-  t.assertTrue(orderStatus.order_status === "paid");
-}
-
 /**
  * Make a simple payment and check that it succeeded.
  */
@@ -891,25 +645,19 @@ export async function makeTestPaymentV2(
 ): Promise<void> {
   // Set up order.
 
-  const { walletClient, merchant } = args;
-  const instance = args.instance ?? "default";
+  const { walletClient, merchant, instance } = args;
 
-  const orderResp = await MerchantPrivateApi.createOrder(
-    merchant,
-    instance,
-    {
-      order: args.order,
-    },
-    auth,
+  const merchantClient = new MerchantApiClient(
+    merchant.makeInstanceBaseUrl(instance),
   );
 
-  let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(
-    merchant,
-    {
-      orderId: orderResp.order_id,
-    },
-    auth,
-  );
+  const orderResp = await merchantClient.createOrder({
+    order: args.order,
+  });
+
+  let orderStatus = await merchantClient.queryPrivateOrderStatus({
+    orderId: orderResp.order_id,
+  });
 
   t.assertTrue(orderStatus.order_status === "unpaid");
 
@@ -934,14 +682,10 @@ export async function makeTestPaymentV2(
 
   // Check if payment was successful.
 
-  orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(
-    merchant,
-    {
-      orderId: orderResp.order_id,
-      instance,
-    },
-    auth,
-  );
+  orderStatus = await merchantClient.queryPrivateOrderStatus({
+    orderId: orderResp.order_id,
+    instance,
+  });
 
   t.assertTrue(orderStatus.order_status === "paid");
 }
diff --git 
a/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts 
b/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts
index 919097deb..5ee35a377 100644
--- 
a/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts
+++ 
b/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts
@@ -31,9 +31,10 @@ import {
   WalletCli,
 } from "../harness/harness.js";
 import {
-  createSimpleTestkudosEnvironment,
-  withdrawViaBank,
-  makeTestPayment,
+  createSimpleTestkudosEnvironmentV2,
+  createWalletDaemonWithClient,
+  makeTestPaymentV2,
+  withdrawViaBankV2,
 } from "../harness/helpers.js";
 
 /**
@@ -43,12 +44,12 @@ export async function runAgeRestrictionsMerchantTest(t: 
GlobalTestState) {
   // Set up test environment
 
   const {
-    wallet: walletOne,
+    walletClient: walletClientOne,
     bank,
     exchange,
     merchant,
     exchangeBankAccount,
-  } = await createSimpleTestkudosEnvironment(
+  } = await createSimpleTestkudosEnvironmentV2(
     t,
     defaultCoinConfig.map((x) => x("TESTKUDOS")),
     {
@@ -63,14 +64,26 @@ export async function runAgeRestrictionsMerchantTest(t: 
GlobalTestState) {
     },
   );
 
-  const walletTwo = new WalletCli(t, "walletTwo");
-  const walletThree = new WalletCli(t, "walletThree");
+  const { walletClient: walletClientTwo } = await createWalletDaemonWithClient(
+    t,
+    {
+      name: "w2",
+    },
+  );
+
+  const { walletClient: walletClientThree } =
+    await createWalletDaemonWithClient(t, {
+      name: "w3",
+    });
 
   {
-    const walletZero = new WalletCli(t, "walletZero");
+    const { walletClient: walletClientZero } =
+      await createWalletDaemonWithClient(t, {
+        name: "w0",
+      });
 
-    await withdrawViaBank(t, {
-      wallet: walletZero,
+    await withdrawViaBankV2(t, {
+      walletClient: walletClientZero,
       bank,
       exchange,
       amount: "TESTKUDOS:20",
@@ -84,15 +97,22 @@ export async function runAgeRestrictionsMerchantTest(t: 
GlobalTestState) {
       minimum_age: 9,
     };
 
-    await makeTestPayment(t, { wallet: walletZero, merchant, order });
-    await walletZero.runUntilDone();
+    await makeTestPaymentV2(t, {
+      walletClient: walletClientZero,
+      merchant,
+      order,
+    });
+    await walletClientZero.call(
+      WalletApiOperation.TestingWaitTransactionsFinal,
+      {},
+    );
   }
 
   {
-    const wallet = walletOne;
+    const walletClient = walletClientOne;
 
-    await withdrawViaBank(t, {
-      wallet,
+    await withdrawViaBankV2(t, {
+      walletClient,
       bank,
       exchange,
       amount: "TESTKUDOS:20",
@@ -106,15 +126,18 @@ export async function runAgeRestrictionsMerchantTest(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;
+    const walletClient = walletClientTwo;
 
-    await withdrawViaBank(t, {
-      wallet,
+    await withdrawViaBankV2(t, {
+      walletClient,
       bank,
       exchange,
       amount: "TESTKUDOS:20",
@@ -127,15 +150,18 @@ export async function runAgeRestrictionsMerchantTest(t: 
GlobalTestState) {
       fulfillment_url: "taler://fulfillment-success/thx",
     };
 
-    await makeTestPayment(t, { wallet, merchant, order });
-    await wallet.runUntilDone();
+    await makeTestPaymentV2(t, { walletClient, merchant, order });
+    await walletClient.call(
+      WalletApiOperation.TestingWaitTransactionsFinal,
+      {},
+    );
   }
 
   {
-    const wallet = walletThree;
+    const walletClient = walletClientThree;
 
-    await withdrawViaBank(t, {
-      wallet,
+    await withdrawViaBankV2(t, {
+      walletClient,
       bank,
       exchange,
       amount: "TESTKUDOS:20",
@@ -148,20 +174,21 @@ export async function runAgeRestrictionsMerchantTest(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,
+      {},
+    );
   }
 
   // Pay with coin from tipping
   {
     const mbu = await BankApi.createRandomBankUser(bank);
-    const tipReserveResp = await merchantClient.createTippingReserve(
-      {
-        exchange_url: exchange.baseUrl,
-        initial_balance: "TESTKUDOS:10",
-        wire_method: getWireMethodForTest(),
-      },
-    );
+    const tipReserveResp = await merchantClient.createTippingReserve({
+      exchange_url: exchange.baseUrl,
+      initial_balance: "TESTKUDOS:10",
+      wire_method: getWireMethodForTest(),
+    });
 
     t.assertDeepEqual(
       tipReserveResp.accounts[0].payto_uri,
@@ -189,17 +216,26 @@ export async function runAgeRestrictionsMerchantTest(t: 
GlobalTestState) {
       next_url: "https://example.com/after-tip";,
     });
 
-    const walletTipping = new WalletCli(t, "age-tipping");
+    const { walletClient: walletClientTipping } =
+      await createWalletDaemonWithClient(t, {
+        name: "age-tipping",
+      });
 
-    const ptr = await 
walletTipping.client.call(WalletApiOperation.PrepareReward, {
-      talerRewardUri: tip.taler_reward_uri,
-    });
+    const ptr = await walletClientTipping.call(
+      WalletApiOperation.PrepareReward,
+      {
+        talerRewardUri: tip.taler_reward_uri,
+      },
+    );
 
-    await walletTipping.client.call(WalletApiOperation.AcceptReward, {
+    await walletClientTipping.call(WalletApiOperation.AcceptReward, {
       walletRewardId: ptr.walletRewardId,
     });
 
-    await walletTipping.runUntilDone();
+    await walletClientTipping.call(
+      WalletApiOperation.TestingWaitTransactionsFinal,
+      {},
+    );
 
     const order = {
       summary: "Buy me!",
@@ -208,8 +244,15 @@ export async function runAgeRestrictionsMerchantTest(t: 
GlobalTestState) {
       minimum_age: 9,
     };
 
-    await makeTestPayment(t, { wallet: walletTipping, merchant, order });
-    await walletTipping.runUntilDone();
+    await makeTestPaymentV2(t, {
+      walletClient: walletClientTipping,
+      merchant,
+      order,
+    });
+    await walletClientTipping.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 9ac16980b..041b10cc0 100644
--- a/packages/taler-harness/src/integrationtests/test-bank-api.ts
+++ b/packages/taler-harness/src/integrationtests/test-bank-api.ts
@@ -85,13 +85,13 @@ export async function runBankApiTest(t: GlobalTestState) {
   await merchant.start();
   await merchant.pingUntilAvailable();
   await merchant.addDefaultInstance();
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
   });
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
diff --git a/packages/taler-harness/src/integrationtests/test-clause-schnorr.ts 
b/packages/taler-harness/src/integrationtests/test-clause-schnorr.ts
index bf42dc4c6..9a839b677 100644
--- a/packages/taler-harness/src/integrationtests/test-clause-schnorr.ts
+++ b/packages/taler-harness/src/integrationtests/test-clause-schnorr.ts
@@ -17,12 +17,13 @@
 /**
  * Imports.
  */
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
 import { GlobalTestState } from "../harness/harness.js";
 import {
-  createSimpleTestkudosEnvironment,
-  withdrawViaBank,
-  makeTestPayment,
+  createSimpleTestkudosEnvironmentV2,
+  makeTestPaymentV2,
+  withdrawViaBankV2,
 } from "../harness/helpers.js";
 
 /**
@@ -53,12 +54,18 @@ export async function runClauseSchnorrTest(t: 
GlobalTestState) {
     name: "rsa_dummy",
   });
 
-  const { wallet, bank, exchange, merchant } =
-    await createSimpleTestkudosEnvironment(t, coinConfig);
+  const { walletClient, bank, exchange, merchant } =
+    await createSimpleTestkudosEnvironmentV2(t, coinConfig);
 
   // 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 = {
     summary: "Buy me!",
@@ -66,8 +73,8 @@ export async function runClauseSchnorrTest(t: 
GlobalTestState) {
     fulfillment_url: "taler://fulfillment-success/thx",
   };
 
-  await makeTestPayment(t, { wallet, merchant, order });
-  await wallet.runUntilDone();
+  await makeTestPaymentV2(t, { walletClient, merchant, order });
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
 
   // Test JSON normalization of contract terms: Does the wallet
   // agree with the merchant?
@@ -77,8 +84,8 @@ export async function runClauseSchnorrTest(t: 
GlobalTestState) {
     fulfillment_url: "taler://fulfillment-success/thx",
   };
 
-  await makeTestPayment(t, { wallet, merchant, order: order2 });
-  await wallet.runUntilDone();
+  await makeTestPaymentV2(t, { walletClient, merchant, order: order2 });
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
 
   // Test JSON normalization of contract terms: Does the wallet
   // agree with the merchant?
@@ -88,9 +95,8 @@ export async function runClauseSchnorrTest(t: 
GlobalTestState) {
     fulfillment_url: "taler://fulfillment-success/thx",
   };
 
-  await makeTestPayment(t, { wallet, merchant, order: order3 });
-
-  await wallet.runUntilDone();
+  await makeTestPaymentV2(t, { walletClient, merchant, order: order3 });
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
 }
 
 runClauseSchnorrTest.suites = ["experimental-wallet"];
diff --git 
a/packages/taler-harness/src/integrationtests/test-exchange-management.ts 
b/packages/taler-harness/src/integrationtests/test-exchange-management.ts
index c67f861e1..718cee0d7 100644
--- a/packages/taler-harness/src/integrationtests/test-exchange-management.ts
+++ b/packages/taler-harness/src/integrationtests/test-exchange-management.ts
@@ -105,13 +105,13 @@ export async function runExchangeManagementTest(
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
   });
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
diff --git 
a/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts 
b/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts
index 5ae97c3da..401cc4ff2 100644
--- a/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts
+++ b/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts
@@ -41,7 +41,11 @@ import {
   setupDb,
   WalletCli,
 } from "../harness/harness.js";
-import { withdrawViaBank } from "../harness/helpers.js";
+import {
+  applyTimeTravelV2,
+  createWalletDaemonWithClient,
+  withdrawViaBankV2,
+} from "../harness/helpers.js";
 
 const logger = new Logger("test-exchange-timetravel.ts");
 
@@ -89,34 +93,6 @@ function getDenomInfoFromKeys(ek: ExchangeKeysJson): 
DenomInfo[] {
   return denomInfos;
 }
 
-async function applyTimeTravel(
-  timetravelDuration: Duration,
-  s: {
-    exchange?: ExchangeService;
-    merchant?: MerchantService;
-    wallet?: WalletCli;
-  },
-): Promise<void> {
-  if (s.exchange) {
-    await s.exchange.stop();
-    s.exchange.setTimetravel(timetravelDuration);
-    await s.exchange.start();
-    await s.exchange.pingUntilAvailable();
-  }
-
-  if (s.merchant) {
-    await s.merchant.stop();
-    s.merchant.setTimetravel(timetravelDuration);
-    await s.merchant.start();
-    await s.merchant.pingUntilAvailable();
-  }
-
-  if (s.wallet) {
-    console.log("setting wallet time travel to", timetravelDuration);
-    s.wallet.setTimetravel(timetravelDuration);
-  }
-}
-
 const http = createPlatformHttpLib({
   allowHttp: true,
   enableThrottling: false,
@@ -173,13 +149,13 @@ export async function runExchangeTimetravelTest(t: 
GlobalTestState) {
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
   });
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
@@ -187,11 +163,19 @@ export async function runExchangeTimetravelTest(t: 
GlobalTestState) {
 
   console.log("setup done!");
 
-  const wallet = new WalletCli(t);
+  const { walletClient } = await createWalletDaemonWithClient(t, {
+    name: "default",
+  });
 
   // Withdraw digital cash into the wallet.
 
-  await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:15" });
+  const wres = await withdrawViaBankV2(t, {
+    walletClient,
+    bank,
+    exchange,
+    amount: "TESTKUDOS:15",
+  });
+  await wres.withdrawalFinishedCond;
 
   const keysResp1 = await http.fetch(exchange.baseUrl + "keys");
   const keys1 = await readSuccessResponseJsonOrThrow(
@@ -206,11 +190,14 @@ export async function runExchangeTimetravelTest(t: 
GlobalTestState) {
   // Travel into the future, the deposit expiration is two years
   // into the future.
   console.log("applying first time travel");
-  await applyTimeTravel(durationFromSpec({ days: 400 }), {
-    wallet,
-    exchange,
-    merchant,
-  });
+  await applyTimeTravelV2(
+    Duration.toMilliseconds(durationFromSpec({ days: 400 })),
+    {
+      walletClient,
+      exchange,
+      merchant,
+    },
+  );
 
   const keysResp2 = await http.fetch(exchange.baseUrl + "keys");
   const keys2 = await readSuccessResponseJsonOrThrow(
diff --git a/packages/taler-harness/src/integrationtests/test-fee-regression.ts 
b/packages/taler-harness/src/integrationtests/test-fee-regression.ts
index e0dc4bc3b..2d84b3a7c 100644
--- a/packages/taler-harness/src/integrationtests/test-fee-regression.ts
+++ b/packages/taler-harness/src/integrationtests/test-fee-regression.ts
@@ -139,7 +139,7 @@ export async function createMyTestkudosEnvironment(
   await merchant.pingUntilAvailable();
 
   await merchant.addDefaultInstance();
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
diff --git a/packages/taler-harness/src/integrationtests/test-kyc.ts 
b/packages/taler-harness/src/integrationtests/test-kyc.ts
index 0fe24d708..34ad46e03 100644
--- a/packages/taler-harness/src/integrationtests/test-kyc.ts
+++ b/packages/taler-harness/src/integrationtests/test-kyc.ts
@@ -162,7 +162,7 @@ export async function createKycTestkudosEnvironment(
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
@@ -171,7 +171,7 @@ export async function createKycTestkudosEnvironment(
     ),
   });
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
diff --git a/packages/taler-harness/src/integrationtests/test-libeufin-basic.ts 
b/packages/taler-harness/src/integrationtests/test-libeufin-basic.ts
index f03b63f50..5d5beb06e 100644
--- a/packages/taler-harness/src/integrationtests/test-libeufin-basic.ts
+++ b/packages/taler-harness/src/integrationtests/test-libeufin-basic.ts
@@ -34,14 +34,18 @@ import {
   MerchantService,
   setupDb,
   WalletCli,
+  WalletClient,
 } from "../harness/harness.js";
-import { makeTestPayment } from "../harness/helpers.js";
 import {
   LibeufinNexusApi,
   LibeufinNexusService,
   LibeufinSandboxApi,
   LibeufinSandboxService,
 } from "../harness/libeufin.js";
+import {
+  createWalletDaemonWithClient,
+  makeTestPaymentV2,
+} from "../harness/helpers.js";
 
 const exchangeIban = "DE71500105179674997361";
 const customerIban = "DE84500105176881385584";
@@ -53,7 +57,7 @@ export interface LibeufinTestEnvironment {
   exchange: ExchangeService;
   exchangeBankAccount: HarnessExchangeBankAccount;
   merchant: MerchantService;
-  wallet: WalletCli;
+  walletClient: WalletClient;
   libeufinSandbox: LibeufinSandboxService;
   libeufinNexus: LibeufinNexusService;
 }
@@ -202,7 +206,7 @@ export async function createLibeufinTestEnvironment(
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [`payto://iban/${merchantIban}?receiver-name=Merchant`],
@@ -213,13 +217,15 @@ export async function createLibeufinTestEnvironment(
 
   console.log("setup done!");
 
-  const wallet = new WalletCli(t);
+  const { walletClient } = await createWalletDaemonWithClient(t, {
+    name: "default ",
+  });
 
   return {
     commonDb: db,
     exchange,
     merchant,
-    wallet,
+    walletClient,
     exchangeBankAccount,
     libeufinNexus,
     libeufinSandbox,
@@ -232,14 +238,14 @@ export async function createLibeufinTestEnvironment(
 export async function runLibeufinBasicTest(t: GlobalTestState) {
   // Set up test environment
 
-  const { wallet, exchange, merchant, libeufinSandbox, libeufinNexus } =
+  const { walletClient, exchange, merchant, libeufinSandbox, libeufinNexus } =
     await createLibeufinTestEnvironment(t);
 
-  await wallet.client.call(WalletApiOperation.AddExchange, {
+  await walletClient.call(WalletApiOperation.AddExchange, {
     exchangeBaseUrl: exchange.baseUrl,
   });
 
-  const wr = await wallet.client.call(
+  const wr = await walletClient.call(
     WalletApiOperation.AcceptManualWithdrawal,
     {
       exchangeBaseUrl: exchange.baseUrl,
@@ -265,9 +271,9 @@ export async function runLibeufinBasicTest(t: 
GlobalTestState) {
 
   await exchange.runWirewatchOnce();
 
-  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("balances", JSON.stringify(bal, undefined, 2));
   t.assertAmountEquals(bal.balances[0].available, "EUR:14.7");
 
@@ -275,10 +281,12 @@ export async function runLibeufinBasicTest(t: 
GlobalTestState) {
     summary: "Buy me!",
     amount: "EUR:5",
     fulfillment_url: "taler://fulfillment-success/thx",
-    wire_transfer_deadline: 
AbsoluteTime.toProtocolTimestamp(AbsoluteTime.now()),
+    wire_transfer_deadline: AbsoluteTime.toProtocolTimestamp(
+      AbsoluteTime.now(),
+    ),
   };
 
-  await makeTestPayment(t, { wallet, merchant, order });
+  await makeTestPaymentV2(t, { walletClient, merchant, order });
 
   await exchange.runAggregatorOnce();
   await exchange.runTransferOnce();
diff --git 
a/packages/taler-harness/src/integrationtests/test-merchant-exchange-confusion.ts
 
b/packages/taler-harness/src/integrationtests/test-merchant-exchange-confusion.ts
index e18cd7a0f..2a8ae39d8 100644
--- 
a/packages/taler-harness/src/integrationtests/test-merchant-exchange-confusion.ts
+++ 
b/packages/taler-harness/src/integrationtests/test-merchant-exchange-confusion.ts
@@ -41,10 +41,10 @@ import {
   WalletCli,
 } from "../harness/harness.js";
 import {
+  createWalletDaemonWithClient,
   FaultyMerchantTestEnvironment,
-  withdrawViaBank,
+  withdrawViaBankV2,
 } from "../harness/helpers.js";
-import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
 
 /**
  * Run a test case with a simple TESTKUDOS Taler environment, consisting
@@ -110,13 +110,13 @@ export async function 
createConfusedMerchantTestkudosEnvironment(
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
   });
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
@@ -124,13 +124,15 @@ export async function 
createConfusedMerchantTestkudosEnvironment(
 
   console.log("setup done!");
 
-  const wallet = new WalletCli(t);
+  const { walletClient } = await createWalletDaemonWithClient(t, {
+    name: "default",
+  });
 
   return {
     commonDb: db,
     exchange,
     merchant,
-    wallet,
+    walletClient,
     bank,
     exchangeBankAccount,
     faultyMerchant,
@@ -145,13 +147,13 @@ export async function 
createConfusedMerchantTestkudosEnvironment(
 export async function runMerchantExchangeConfusionTest(t: GlobalTestState) {
   // Set up test environment
 
-  const { wallet, bank, faultyExchange, faultyMerchant } =
+  const { walletClient, bank, faultyExchange, faultyMerchant } =
     await createConfusedMerchantTestkudosEnvironment(t);
 
   // Withdraw digital cash into the wallet.
 
-  await withdrawViaBank(t, {
-    wallet,
+  await withdrawViaBankV2(t, {
+    walletClient,
     bank,
     exchange: faultyExchange,
     amount: "TESTKUDOS:20",
@@ -200,7 +202,7 @@ export async function runMerchantExchangeConfusionTest(t: 
GlobalTestState) {
 
   console.log(pubUnpaidStatus);
 
-  let preparePayResp = await wallet.client.call(
+  let preparePayResp = await walletClient.call(
     WalletApiOperation.PreparePayForUri,
     {
       talerPayUri: pubUnpaidStatus.taler_pay_uri,
@@ -231,7 +233,7 @@ export async function runMerchantExchangeConfusionTest(t: 
GlobalTestState) {
     await publicOrderStatusResp.json(),
   );
 
-  const confirmPayRes = await wallet.client.call(
+  const confirmPayRes = await walletClient.call(
     WalletApiOperation.ConfirmPay,
     {
       proposalId: proposalId,
diff --git 
a/packages/taler-harness/src/integrationtests/test-merchant-instances-delete.ts 
b/packages/taler-harness/src/integrationtests/test-merchant-instances-delete.ts
index e6e5bff76..1c99dda76 100644
--- 
a/packages/taler-harness/src/integrationtests/test-merchant-instances-delete.ts
+++ 
b/packages/taler-harness/src/integrationtests/test-merchant-instances-delete.ts
@@ -75,7 +75,7 @@ export async function runMerchantInstancesDeleteTest(t: 
GlobalTestState) {
   }
 
   // Add an instance, no auth!
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
@@ -85,7 +85,7 @@ export async function runMerchantInstancesDeleteTest(t: 
GlobalTestState) {
   });
 
   // Add an instance, no auth!
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "myinst",
     name: "Second Instance",
     paytoUris: [getPayto("merchant-default")],
diff --git 
a/packages/taler-harness/src/integrationtests/test-merchant-instances.ts 
b/packages/taler-harness/src/integrationtests/test-merchant-instances.ts
index f7d89c543..167c54cb4 100644
--- a/packages/taler-harness/src/integrationtests/test-merchant-instances.ts
+++ b/packages/taler-harness/src/integrationtests/test-merchant-instances.ts
@@ -77,7 +77,7 @@ export async function runMerchantInstancesTest(t: 
GlobalTestState) {
   }
 
   // Add an instance, no auth!
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
@@ -87,7 +87,7 @@ export async function runMerchantInstancesTest(t: 
GlobalTestState) {
   });
 
   // Add an instance, no auth!
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "myinst",
     name: "Second Instance",
     paytoUris: [getPayto("merchant-default")],
diff --git 
a/packages/taler-harness/src/integrationtests/test-merchant-refund-api.ts 
b/packages/taler-harness/src/integrationtests/test-merchant-refund-api.ts
index 8efac1fc1..bc53cb533 100644
--- a/packages/taler-harness/src/integrationtests/test-merchant-refund-api.ts
+++ b/packages/taler-harness/src/integrationtests/test-merchant-refund-api.ts
@@ -25,10 +25,11 @@ import {
   WalletCli,
   ExchangeServiceInterface,
   harnessHttpLib,
+  WalletClient,
 } from "../harness/harness.js";
 import {
-  createSimpleTestkudosEnvironment,
-  withdrawViaBank,
+  createSimpleTestkudosEnvironmentV2,
+  withdrawViaBankV2,
 } from "../harness/helpers.js";
 import {
   URL,
@@ -46,11 +47,11 @@ async function testRefundApiWithFulfillmentUrl(
   env: {
     merchant: MerchantServiceInterface;
     bank: BankServiceHandle;
-    wallet: WalletCli;
+    walletClient: WalletClient;
     exchange: ExchangeServiceInterface;
   },
 ): Promise<void> {
-  const { wallet, bank, exchange, merchant } = env;
+  const { walletClient, bank, exchange, merchant } = env;
 
   // Set up order.
   const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
@@ -75,7 +76,7 @@ async function testRefundApiWithFulfillmentUrl(
 
   // Make wallet pay for the order
 
-  let preparePayResult = await wallet.client.call(
+  let preparePayResult = await walletClient.call(
     WalletApiOperation.PreparePayForUri,
     {
       talerPayUri,
@@ -86,7 +87,7 @@ async function testRefundApiWithFulfillmentUrl(
     preparePayResult.status === PreparePayResultType.PaymentPossible,
   );
 
-  await wallet.client.call(WalletApiOperation.ConfirmPay, {
+  await walletClient.call(WalletApiOperation.ConfirmPay, {
     proposalId: preparePayResult.proposalId,
   });
 
@@ -98,7 +99,7 @@ async function testRefundApiWithFulfillmentUrl(
 
   t.assertTrue(orderStatus.order_status === "paid");
 
-  preparePayResult = await wallet.client.call(
+  preparePayResult = await walletClient.call(
     WalletApiOperation.PreparePayForUri,
     {
       talerPayUri,
@@ -136,7 +137,9 @@ async function testRefundApiWithFulfillmentUrl(
     preparePayResult.contractTermsHash,
   );
 
-  let publicOrderStatusResp = await 
harnessHttpLib.fetch(publicOrderStatusUrl.href);
+  let publicOrderStatusResp = await harnessHttpLib.fetch(
+    publicOrderStatusUrl.href,
+  );
   const respData = await publicOrderStatusResp.json();
   t.assertTrue(publicOrderStatusResp.status === 200);
   t.assertAmountEquals(respData.refund_amount, "TESTKUDOS:5");
@@ -158,11 +161,11 @@ async function testRefundApiWithFulfillmentMessage(
   env: {
     merchant: MerchantServiceInterface;
     bank: BankServiceHandle;
-    wallet: WalletCli;
+    walletClient: WalletClient;
     exchange: ExchangeServiceInterface;
   },
 ): Promise<void> {
-  const { wallet, bank, exchange, merchant } = env;
+  const { walletClient, bank, exchange, merchant } = env;
 
   // Set up order.
   const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
@@ -187,7 +190,7 @@ async function testRefundApiWithFulfillmentMessage(
 
   // Make wallet pay for the order
 
-  let preparePayResult = await wallet.client.call(
+  let preparePayResult = await walletClient.call(
     WalletApiOperation.PreparePayForUri,
     {
       talerPayUri,
@@ -198,7 +201,7 @@ async function testRefundApiWithFulfillmentMessage(
     preparePayResult.status === PreparePayResultType.PaymentPossible,
   );
 
-  await wallet.client.call(WalletApiOperation.ConfirmPay, {
+  await walletClient.call(WalletApiOperation.ConfirmPay, {
     proposalId: preparePayResult.proposalId,
   });
 
@@ -210,7 +213,7 @@ async function testRefundApiWithFulfillmentMessage(
 
   t.assertTrue(orderStatus.order_status === "paid");
 
-  preparePayResult = await wallet.client.call(
+  preparePayResult = await walletClient.call(
     WalletApiOperation.PreparePayForUri,
     {
       talerPayUri,
@@ -248,7 +251,9 @@ async function testRefundApiWithFulfillmentMessage(
     preparePayResult.contractTermsHash,
   );
 
-  let publicOrderStatusResp = await 
harnessHttpLib.fetch(publicOrderStatusUrl.href);
+  let publicOrderStatusResp = await harnessHttpLib.fetch(
+    publicOrderStatusUrl.href,
+  );
   let respData = await publicOrderStatusResp.json();
   console.log(respData);
   t.assertTrue(publicOrderStatusResp.status === 200);
@@ -272,22 +277,28 @@ async function testRefundApiWithFulfillmentMessage(
 export async function runMerchantRefundApiTest(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;
 
   await testRefundApiWithFulfillmentUrl(t, {
-    wallet,
+    walletClient,
     bank,
     exchange,
     merchant,
   });
 
   await testRefundApiWithFulfillmentMessage(t, {
-    wallet,
+    walletClient,
     bank,
     exchange,
     merchant,
diff --git 
a/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts
 
b/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts
index e959e813b..08c9d4bb2 100644
--- 
a/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts
+++ 
b/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts
@@ -35,8 +35,9 @@ import {
   harnessHttpLib,
 } from "../harness/harness.js";
 import {
-  createSimpleTestkudosEnvironment,
-  withdrawViaBank,
+  createSimpleTestkudosEnvironmentV2,
+  createWalletDaemonWithClient,
+  withdrawViaBankV2,
 } from "../harness/helpers.js";
 
 interface Context {
@@ -52,10 +53,18 @@ async function testWithClaimToken(
   t: GlobalTestState,
   c: Context,
 ): Promise<void> {
-  const wallet = new WalletCli(t, "withclaimtoken");
+  const { walletClient } = await createWalletDaemonWithClient(t, {
+    name: "wct",
+  });
   const { bank, exchange } = c;
   const { merchant, merchantBaseUrl } = c;
-  await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+  const wres = await withdrawViaBankV2(t, {
+    walletClient,
+    bank,
+    exchange,
+    amount: "TESTKUDOS:20",
+  });
+  await wres.withdrawalFinishedCond;
   const sessionId = "mysession";
   const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
     order: {
@@ -104,7 +113,7 @@ async function testWithClaimToken(
     console.log(r);
   }
 
-  const preparePayResp = await wallet.client.call(
+  const preparePayResp = await walletClient.call(
     WalletApiOperation.PreparePayForUri,
     {
       talerPayUri,
@@ -166,12 +175,9 @@ async function testWithClaimToken(
     t.assertDeepEqual(httpResp.status, 202);
   }
 
-  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);
 
@@ -238,7 +244,7 @@ async function testWithClaimToken(
     t.assertDeepEqual(httpResp.status, 200);
   }
 
-  const confirmPayRes2 = await wallet.client.call(
+  const confirmPayRes2 = await walletClient.call(
     WalletApiOperation.ConfirmPay,
     {
       proposalId: proposalId,
@@ -307,11 +313,19 @@ async function testWithoutClaimToken(
   t: GlobalTestState,
   c: Context,
 ): Promise<void> {
-  const wallet = new WalletCli(t, "withoutct");
+  const { walletClient } = await createWalletDaemonWithClient(t, {
+    name: "wnoct",
+  });
   const sessionId = "mysession2";
   const { bank, exchange } = c;
   const { merchant, merchantBaseUrl } = c;
-  await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+  const wres = await withdrawViaBankV2(t, {
+    walletClient,
+    bank,
+    exchange,
+    amount: "TESTKUDOS:20",
+  });
+  await wres.withdrawalFinishedCond;
   const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
     order: {
       summary: "Buy me!",
@@ -356,7 +370,7 @@ async function testWithoutClaimToken(
     console.log(r);
   }
 
-  const preparePayResp = await wallet.client.call(
+  const preparePayResp = await walletClient.call(
     WalletApiOperation.PreparePayForUri,
     {
       talerPayUri,
@@ -422,12 +436,9 @@ async function testWithoutClaimToken(
     t.assertDeepEqual(httpResp.status, 402);
   }
 
-  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);
 
@@ -492,7 +503,7 @@ async function testWithoutClaimToken(
     t.assertDeepEqual(httpResp.status, 200);
   }
 
-  const confirmPayRes2 = await wallet.client.call(
+  const confirmPayRes2 = await walletClient.call(
     WalletApiOperation.ConfirmPay,
     {
       proposalId: proposalId,
@@ -564,7 +575,7 @@ async function testWithoutClaimToken(
  * specification of the endpoint.
  */
 export async function runMerchantSpecPublicOrdersTest(t: GlobalTestState) {
-  const { bank, exchange, merchant } = await createSimpleTestkudosEnvironment(
+  const { bank, exchange, merchant } = await 
createSimpleTestkudosEnvironmentV2(
     t,
   );
 
@@ -572,7 +583,9 @@ export async function runMerchantSpecPublicOrdersTest(t: 
GlobalTestState) {
   const merchantBaseUrl = merchant.makeInstanceBaseUrl();
 
   {
-    const httpResp = await httpLib.fetch(new URL("config", 
merchantBaseUrl).href);
+    const httpResp = await httpLib.fetch(
+      new URL("config", merchantBaseUrl).href,
+    );
     const r = await httpResp.json();
     console.log(r);
     t.assertDeepEqual(r.currency, "TESTKUDOS");
diff --git a/packages/taler-harness/src/integrationtests/test-pay-paid.ts 
b/packages/taler-harness/src/integrationtests/test-pay-paid.ts
index a377b7237..8d39ad4f6 100644
--- a/packages/taler-harness/src/integrationtests/test-pay-paid.ts
+++ b/packages/taler-harness/src/integrationtests/test-pay-paid.ts
@@ -17,10 +17,14 @@
 /**
  * Imports.
  */
-import { GlobalTestState, MerchantPrivateApi, harnessHttpLib } from 
"../harness/harness.js";
 import {
-  withdrawViaBank,
+  GlobalTestState,
+  MerchantPrivateApi,
+  harnessHttpLib,
+} from "../harness/harness.js";
+import {
   createFaultInjectedMerchantTestkudosEnvironment,
+  withdrawViaBankV2,
 } from "../harness/helpers.js";
 import {
   PreparePayResultType,
@@ -42,18 +46,20 @@ import { WalletApiOperation } from 
"@gnu-taler/taler-wallet-core";
 export async function runPayPaidTest(t: GlobalTestState) {
   // Set up test environment
 
-  const { wallet, bank, faultyExchange, faultyMerchant } =
+  const { walletClient, bank, faultyExchange, faultyMerchant } =
     await createFaultInjectedMerchantTestkudosEnvironment(t);
 
   // Withdraw digital cash into the wallet.
 
-  await withdrawViaBank(t, {
-    wallet,
+  const wres = await withdrawViaBankV2(t, {
+    walletClient,
     bank,
     exchange: faultyExchange,
     amount: "TESTKUDOS:20",
   });
 
+  await wres.withdrawalFinishedCond;
+
   /**
    * =========================================================================
    * Create an order and let the wallet pay under a session ID
@@ -98,7 +104,7 @@ export async function runPayPaidTest(t: GlobalTestState) {
 
   console.log(pubUnpaidStatus);
 
-  let preparePayResp = await wallet.client.call(
+  let preparePayResp = await walletClient.call(
     WalletApiOperation.PreparePayForUri,
     {
       talerPayUri: pubUnpaidStatus.taler_pay_uri,
@@ -121,7 +127,7 @@ export async function runPayPaidTest(t: GlobalTestState) {
     publicOrderStatusResp.json(),
   );
 
-  const confirmPayRes = await wallet.client.call(
+  const confirmPayRes = await walletClient.call(
     WalletApiOperation.ConfirmPay,
     {
       proposalId: proposalId,
@@ -196,7 +202,7 @@ export async function runPayPaidTest(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: orderStatusTwo.taler_pay_uri,
diff --git a/packages/taler-harness/src/integrationtests/test-payment-abort.ts 
b/packages/taler-harness/src/integrationtests/test-payment-abort.ts
index 05ca7a543..99140b2ee 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-abort.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-abort.ts
@@ -17,10 +17,14 @@
 /**
  * Imports.
  */
-import { GlobalTestState, MerchantPrivateApi, harnessHttpLib } from 
"../harness/harness.js";
 import {
-  withdrawViaBank,
+  GlobalTestState,
+  MerchantPrivateApi,
+  harnessHttpLib,
+} from "../harness/harness.js";
+import {
   createFaultInjectedMerchantTestkudosEnvironment,
+  withdrawViaBankV2,
 } from "../harness/helpers.js";
 import { FaultInjectionRequestContext } from "../harness/faultInjection.js";
 import {
@@ -37,13 +41,13 @@ import { WalletApiOperation } from 
"@gnu-taler/taler-wallet-core";
 export async function runPaymentAbortTest(t: GlobalTestState) {
   // Set up test environment
 
-  const { wallet, bank, exchange, faultyMerchant, faultyExchange } =
+  const { walletClient, bank, exchange, faultyMerchant, faultyExchange } =
     await createFaultInjectedMerchantTestkudosEnvironment(t);
 
   // Withdraw digital cash into the wallet.
 
-  await withdrawViaBank(t, {
-    wallet,
+  await withdrawViaBankV2(t, {
+    walletClient,
     bank,
     exchange: faultyExchange,
     amount: "TESTKUDOS:20",
@@ -84,7 +88,7 @@ export async function runPaymentAbortTest(t: GlobalTestState) 
{
 
   console.log(pubUnpaidStatus);
 
-  let preparePayResp = await wallet.client.call(
+  let preparePayResp = await walletClient.call(
     WalletApiOperation.PreparePayForUri,
     {
       talerPayUri: pubUnpaidStatus.taler_pay_uri,
@@ -124,7 +128,7 @@ export async function runPaymentAbortTest(t: 
GlobalTestState) {
     },
   });
 
-  const confirmPayResp = await wallet.client.call(
+  const confirmPayResp = await walletClient.call(
     WalletApiOperation.ConfirmPay,
     {
       proposalId,
@@ -134,19 +138,16 @@ export async function runPaymentAbortTest(t: 
GlobalTestState) {
   // Can't have succeeded yet, but network error results in "pending" state.
   t.assertDeepEqual(confirmPayResp.type, ConfirmPayResultType.Pending);
 
-  const txns = await wallet.client.call(WalletApiOperation.GetTransactions, 
{});
+  const txns = await walletClient.call(WalletApiOperation.GetTransactions, {});
   console.log(j2s(txns));
 
-  await wallet.client.call(WalletApiOperation.AbortTransaction, {
+  await walletClient.call(WalletApiOperation.AbortTransaction, {
     transactionId: txns.transactions[1].transactionId,
   });
 
-  await wallet.runUntilDone();
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
 
-  const txns2 = await wallet.client.call(
-    WalletApiOperation.GetTransactions,
-    {},
-  );
+  const txns2 = await walletClient.call(WalletApiOperation.GetTransactions, 
{});
   console.log(j2s(txns2));
 
   const txTypes = txns2.transactions.map((x) => x.type);
diff --git a/packages/taler-harness/src/integrationtests/test-payment-fault.ts 
b/packages/taler-harness/src/integrationtests/test-payment-fault.ts
index c1438a419..0cc369a6e 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-fault.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-fault.ts
@@ -114,7 +114,7 @@ export async function runPaymentFaultTest(t: 
GlobalTestState) {
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
diff --git 
a/packages/taler-harness/src/integrationtests/test-payment-multiple.ts 
b/packages/taler-harness/src/integrationtests/test-payment-multiple.ts
index 25e19ae8e..29047e102 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-multiple.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-multiple.ts
@@ -27,9 +27,12 @@ import {
   MerchantPrivateApi,
   getPayto,
 } from "../harness/harness.js";
-import { withdrawViaBank } from "../harness/helpers.js";
 import { coin_ct10, coin_u1 } from "../harness/denomStructures.js";
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import {
+  createWalletDaemonWithClient,
+  withdrawViaBankV2,
+} from "../harness/helpers.js";
 
 async function setupTest(t: GlobalTestState): Promise<{
   merchant: MerchantService;
@@ -82,13 +85,13 @@ async function setupTest(t: GlobalTestState): Promise<{
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
   });
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
@@ -113,11 +116,18 @@ export async function runPaymentMultipleTest(t: 
GlobalTestState) {
 
   const { merchant, bank, exchange } = await setupTest(t);
 
-  const wallet = new WalletCli(t);
+  const { walletClient } = await createWalletDaemonWithClient(t, {
+    name: "default",
+  });
 
   // Withdraw digital cash into the wallet.
 
-  await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:100" 
});
+  await withdrawViaBankV2(t, {
+    walletClient,
+    bank,
+    exchange,
+    amount: "TESTKUDOS:100",
+  });
 
   // Set up order.
 
@@ -137,13 +147,12 @@ export async function runPaymentMultipleTest(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.
diff --git 
a/packages/taler-harness/src/integrationtests/test-payment-transient.ts 
b/packages/taler-harness/src/integrationtests/test-payment-transient.ts
index c2a8e37c5..2cc0af309 100644
--- a/packages/taler-harness/src/integrationtests/test-payment-transient.ts
+++ b/packages/taler-harness/src/integrationtests/test-payment-transient.ts
@@ -29,8 +29,7 @@ import { WalletApiOperation } from 
"@gnu-taler/taler-wallet-core";
 import { FaultInjectionResponseContext } from "../harness/faultInjection.js";
 import { GlobalTestState, MerchantPrivateApi, harnessHttpLib } from 
"../harness/harness.js";
 import {
-  createFaultInjectedMerchantTestkudosEnvironment,
-  withdrawViaBank,
+  createFaultInjectedMerchantTestkudosEnvironment, withdrawViaBankV2,
 } from "../harness/helpers.js";
 
 
@@ -41,13 +40,13 @@ import {
 export async function runPaymentTransientTest(t: GlobalTestState) {
   // Set up test environment
 
-  const { wallet, bank, exchange, faultyMerchant, faultyExchange } =
+  const { walletClient, bank, exchange, faultyMerchant, faultyExchange } =
     await createFaultInjectedMerchantTestkudosEnvironment(t);
 
   // Withdraw digital cash into the wallet.
 
-  await withdrawViaBank(t, {
-    wallet,
+  await withdrawViaBankV2(t, {
+    walletClient,
     bank,
     exchange: faultyExchange,
     amount: "TESTKUDOS:20",
@@ -88,7 +87,7 @@ export async function runPaymentTransientTest(t: 
GlobalTestState) {
 
   console.log(pubUnpaidStatus);
 
-  let preparePayResp = await wallet.client.call(
+  let preparePayResp = await walletClient.call(
     WalletApiOperation.PreparePayForUri,
     {
       talerPayUri: pubUnpaidStatus.taler_pay_uri,
@@ -136,7 +135,7 @@ export async function runPaymentTransientTest(t: 
GlobalTestState) {
     },
   });
 
-  const confirmPayResp = await wallet.client.call(
+  const confirmPayResp = await walletClient.call(
     WalletApiOperation.ConfirmPay,
     {
       proposalId,
@@ -148,7 +147,7 @@ export async function runPaymentTransientTest(t: 
GlobalTestState) {
   t.assertTrue(confirmPayResp.type === ConfirmPayResultType.Pending);
   t.assertTrue(faultInjected);
 
-  const confirmPayRespTwo = await wallet.client.call(
+  const confirmPayRespTwo = await walletClient.call(
     WalletApiOperation.ConfirmPay,
     {
       proposalId,
diff --git a/packages/taler-harness/src/integrationtests/test-refund-gone.ts 
b/packages/taler-harness/src/integrationtests/test-refund-gone.ts
index 5f226c7dd..8e402f3fc 100644
--- a/packages/taler-harness/src/integrationtests/test-refund-gone.ts
+++ b/packages/taler-harness/src/integrationtests/test-refund-gone.ts
@@ -19,9 +19,9 @@
  */
 import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
 import {
-  createSimpleTestkudosEnvironment,
-  withdrawViaBank,
-  applyTimeTravel,
+  applyTimeTravelV2,
+  createSimpleTestkudosEnvironmentV2,
+  withdrawViaBankV2,
 } from "../harness/helpers.js";
 import {
   AbsoluteTime,
@@ -36,12 +36,17 @@ import { WalletApiOperation } from 
"@gnu-taler/taler-wallet-core";
 export async function runRefundGoneTest(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.
 
@@ -72,11 +77,11 @@ export async function runRefundGoneTest(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,
   });
 
-  const r2 = await wallet.client.call(WalletApiOperation.ConfirmPay, {
+  const r2 = await walletClient.call(WalletApiOperation.ConfirmPay, {
     proposalId: r1.proposalId,
   });
 
@@ -90,7 +95,10 @@ export async function runRefundGoneTest(t: GlobalTestState) {
 
   console.log(orderStatus);
 
-  await applyTimeTravel(durationFromSpec({ hours: 1 }), { exchange, wallet });
+  await applyTimeTravelV2(
+    Duration.toMilliseconds(Duration.fromSpec({ hours: 1 })),
+    { exchange, walletClient: walletClient },
+  );
 
   await exchange.runAggregatorOnce();
 
@@ -103,16 +111,16 @@ export async function runRefundGoneTest(t: 
GlobalTestState) {
 
   console.log(ref);
 
-  await wallet.client.call(WalletApiOperation.StartRefundQuery, {
+  await walletClient.call(WalletApiOperation.StartRefundQuery, {
     transactionId: r1.transactionId,
   });
 
-  await wallet.runUntilDone();
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
 
-  let r = await wallet.client.call(WalletApiOperation.GetBalances, {});
+  let r = await walletClient.call(WalletApiOperation.GetBalances, {});
   console.log(JSON.stringify(r, undefined, 2));
 
-  const r3 = await wallet.client.call(WalletApiOperation.GetTransactions, {});
+  const r3 = await walletClient.call(WalletApiOperation.GetTransactions, {});
   console.log(JSON.stringify(r3, undefined, 2));
 
   await t.shutdown();
diff --git a/packages/taler-harness/src/integrationtests/test-revocation.ts 
b/packages/taler-harness/src/integrationtests/test-revocation.ts
index 04707e51a..233780674 100644
--- a/packages/taler-harness/src/integrationtests/test-revocation.ts
+++ b/packages/taler-harness/src/integrationtests/test-revocation.ts
@@ -28,20 +28,22 @@ import {
   BankService,
   delayMs,
   getPayto,
+  WalletClient,
 } from "../harness/harness.js";
 import {
-  withdrawViaBank,
-  makeTestPayment,
-  SimpleTestEnvironment,
+  SimpleTestEnvironmentNg,
+  createWalletDaemonWithClient,
+  makeTestPaymentV2,
+  withdrawViaBankV2,
 } from "../harness/helpers.js";
 
 async function revokeAllWalletCoins(req: {
-  wallet: WalletCli;
+  walletClient: WalletClient;
   exchange: ExchangeService;
   merchant: MerchantService;
 }): Promise<void> {
-  const { wallet, exchange, merchant } = req;
-  const coinDump = await wallet.client.call(WalletApiOperation.DumpCoins, {});
+  const { walletClient, exchange, merchant } = req;
+  const coinDump = await walletClient.call(WalletApiOperation.DumpCoins, {});
   console.log(coinDump);
   const usedDenomHashes = new Set<string>();
   for (const coin of coinDump.coins) {
@@ -60,7 +62,7 @@ async function revokeAllWalletCoins(req: {
 
 async function createTestEnvironment(
   t: GlobalTestState,
-): Promise<SimpleTestEnvironment> {
+): Promise<SimpleTestEnvironmentNg> {
   const db = await setupDb(t);
 
   const bank = await BankService.create(t, {
@@ -120,13 +122,13 @@ async function createTestEnvironment(
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
   });
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
@@ -136,11 +138,19 @@ async function createTestEnvironment(
 
   const wallet = new WalletCli(t);
 
+  const { walletService, walletClient } = await createWalletDaemonWithClient(
+    t,
+    {
+      name: "default",
+    },
+  );
+
   return {
     commonDb: db,
     exchange,
     merchant,
-    wallet,
+    walletClient,
+    walletService,
     bank,
     exchangeBankAccount,
   };
@@ -152,24 +162,30 @@ async function createTestEnvironment(
 export async function runRevocationTest(t: GlobalTestState) {
   // Set up test environment
 
-  const { wallet, bank, exchange, merchant } = await createTestEnvironment(t);
+  const { walletClient, bank, exchange, merchant } =
+    await createTestEnvironment(t);
 
   // Withdraw digital cash into the wallet.
 
-  await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:15" });
+  const wres = await withdrawViaBankV2(t, {
+    walletClient,
+    bank,
+    exchange,
+    amount: "TESTKUDOS:15",
+  });
+  await wres.withdrawalFinishedCond;
 
   console.log("revoking first time");
-  await revokeAllWalletCoins({ wallet, exchange, merchant });
+  await revokeAllWalletCoins({ walletClient, exchange, merchant });
 
   // FIXME: this shouldn't be necessary once https://bugs.taler.net/n/6565
   // is implemented.
-  await wallet.client.call(WalletApiOperation.AddExchange, {
+  await walletClient.call(WalletApiOperation.AddExchange, {
     exchangeBaseUrl: exchange.baseUrl,
     forceUpdate: true,
   });
-  await wallet.runUntilDone();
-  await wallet.runUntilDone();
-  const bal = await wallet.client.call(WalletApiOperation.GetBalances, {});
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
+  const bal = await walletClient.call(WalletApiOperation.GetBalances, {});
   console.log("wallet balance", bal);
 
   const order = {
@@ -178,39 +194,43 @@ export async function runRevocationTest(t: 
GlobalTestState) {
     fulfillment_url: "taler://fulfillment-success/thx",
   };
 
-  await makeTestPayment(t, { wallet, merchant, order });
+  await makeTestPaymentV2(t, { walletClient, merchant, order });
 
-  wallet.deleteDatabase();
+  await walletClient.call(WalletApiOperation.ClearDb, {});
 
-  await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:15" });
+  await withdrawViaBankV2(t, {
+    walletClient,
+    bank,
+    exchange,
+    amount: "TESTKUDOS:15",
+  });
 
-  const coinDump = await wallet.client.call(WalletApiOperation.DumpCoins, {});
+  const coinDump = await walletClient.call(WalletApiOperation.DumpCoins, {});
   console.log(coinDump);
   const coinPubList = coinDump.coins.map((x) => x.coin_pub);
-  await wallet.client.call(WalletApiOperation.ForceRefresh, {
+  await walletClient.call(WalletApiOperation.ForceRefresh, {
     coinPubList,
   });
-  await wallet.runUntilDone();
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
 
   console.log("revoking second time");
-  await revokeAllWalletCoins({ wallet, exchange, merchant });
+  await revokeAllWalletCoins({ walletClient, exchange, merchant });
 
   // FIXME: this shouldn't be necessary once https://bugs.taler.net/n/6565
   // is implemented.
-  await wallet.client.call(WalletApiOperation.AddExchange, {
+  await walletClient.call(WalletApiOperation.AddExchange, {
     exchangeBaseUrl: exchange.baseUrl,
     forceUpdate: true,
   });
-  await wallet.runUntilDone();
-  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("wallet balance", bal);
   }
 
-  await makeTestPayment(t, { wallet, merchant, order });
+  await makeTestPaymentV2(t, { walletClient, merchant, order });
 }
 
 runRevocationTest.timeoutMs = 120000;
 runRevocationTest.suites = ["wallet"];
-runRevocationTest.excludeByDefault = true;
\ No newline at end of file
+runRevocationTest.excludeByDefault = true;
diff --git 
a/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts 
b/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts
index 50f9cbcd3..602b6629a 100644
--- a/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts
+++ b/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts
@@ -38,35 +38,8 @@ import {
   WalletCli,
   getPayto,
 } from "../harness/harness.js";
-import { startWithdrawViaBank, withdrawViaBank } from "../harness/helpers.js";
-
-async function applyTimeTravel(
-  timetravelDuration: Duration,
-  s: {
-    exchange?: ExchangeService;
-    merchant?: MerchantService;
-    wallet?: WalletCli;
-  },
-): Promise<void> {
-  if (s.exchange) {
-    await s.exchange.stop();
-    s.exchange.setTimetravel(timetravelDuration);
-    await s.exchange.start();
-    await s.exchange.pingUntilAvailable();
-  }
-
-  if (s.merchant) {
-    await s.merchant.stop();
-    s.merchant.setTimetravel(timetravelDuration);
-    await s.merchant.start();
-    await s.merchant.pingUntilAvailable();
-  }
-
-  if (s.wallet) {
-    console.log("setting wallet time travel to", timetravelDuration);
-    s.wallet.setTimetravel(timetravelDuration);
-  }
-}
+import { applyTimeTravelV2, createWalletDaemonWithClient, withdrawViaBankV2 } 
from "../harness/helpers.js";
+
 
 /**
  * Basic time travel test.
@@ -119,13 +92,13 @@ export async function runTimetravelAutorefreshTest(t: 
GlobalTestState) {
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
   });
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "minst1",
     name: "minst1",
     paytoUris: [getPayto("minst1")],
@@ -133,43 +106,46 @@ export async function runTimetravelAutorefreshTest(t: 
GlobalTestState) {
 
   console.log("setup done!");
 
-  const wallet = new WalletCli(t);
+  const { walletClient } = await createWalletDaemonWithClient(t, {
+    name: "w1",
+  });
 
   // Withdraw digital cash into the wallet.
 
-  await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:15" });
+  const wres = await withdrawViaBankV2(t, { walletClient, bank, exchange, 
amount: "TESTKUDOS:15" });
+  await wres.withdrawalFinishedCond;
 
   // Travel into the future, the deposit expiration is two years
   // into the future.
   console.log("applying first time travel");
-  await applyTimeTravel(durationFromSpec({ days: 400 }), {
-    wallet,
+  await applyTimeTravelV2(Duration.toMilliseconds(durationFromSpec({ days: 400 
})), {
+    walletClient,
     exchange,
     merchant,
   });
 
-  await wallet.runUntilDone();
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
 
   let p: PendingOperationsResponse;
-  p = await wallet.client.call(WalletApiOperation.GetPendingOperations, {});
+  p = await walletClient.call(WalletApiOperation.GetPendingOperations, {});
 
   console.log("pending operations after first time travel");
   console.log(JSON.stringify(p, undefined, 2));
 
-  await startWithdrawViaBank(t, {
-    wallet,
+  await withdrawViaBankV2(t, {
+    walletClient,
     bank,
     exchange,
     amount: "TESTKUDOS:20",
   });
 
-  await wallet.runUntilDone();
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
 
   // Travel into the future, the deposit expiration is two years
   // into the future.
   console.log("applying second time travel");
-  await applyTimeTravel(durationFromSpec({ years: 2, months: 6 }), {
-    wallet,
+  await applyTimeTravelV2(Duration.toMilliseconds(durationFromSpec({ years: 2, 
months: 6 })), {
+    walletClient,
     exchange,
     merchant,
   });
@@ -178,7 +154,7 @@ export async function runTimetravelAutorefreshTest(t: 
GlobalTestState) {
   // It would be too late to refresh them now, as we're past
   // the two year deposit expiration.
 
-  await wallet.runUntilDone();
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
 
   const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
     order: {
@@ -198,7 +174,7 @@ export async function runTimetravelAutorefreshTest(t: 
GlobalTestState) {
 
   t.assertTrue(orderStatus.order_status === "unpaid");
 
-  const r = await wallet.client.call(WalletApiOperation.PreparePayForUri, {
+  const r = await walletClient.call(WalletApiOperation.PreparePayForUri, {
     talerPayUri: orderStatus.taler_pay_uri,
   });
 
@@ -206,7 +182,7 @@ export async function runTimetravelAutorefreshTest(t: 
GlobalTestState) {
 
   t.assertTrue(r.status === PreparePayResultType.PaymentPossible);
 
-  const cpr = await wallet.client.call(WalletApiOperation.ConfirmPay, {
+  const cpr = await walletClient.call(WalletApiOperation.ConfirmPay, {
     proposalId: r.proposalId,
   });
 
diff --git 
a/packages/taler-harness/src/integrationtests/test-timetravel-withdraw.ts 
b/packages/taler-harness/src/integrationtests/test-timetravel-withdraw.ts
index ca3e67647..e594d2d72 100644
--- a/packages/taler-harness/src/integrationtests/test-timetravel-withdraw.ts
+++ b/packages/taler-harness/src/integrationtests/test-timetravel-withdraw.ts
@@ -17,13 +17,16 @@
 /**
  * Imports.
  */
-import { Duration, TransactionMajorState, TransactionType } from 
"@gnu-taler/taler-util";
+import {
+  Duration,
+  TransactionMajorState,
+  TransactionType,
+} from "@gnu-taler/taler-util";
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { GlobalTestState } from "../harness/harness.js";
 import {
-  createSimpleTestkudosEnvironment,
-  startWithdrawViaBank,
-  withdrawViaBank,
+  createSimpleTestkudosEnvironmentV2,
+  withdrawViaBankV2,
 } from "../harness/helpers.js";
 
 /**
@@ -32,12 +35,18 @@ import {
 export async function runTimetravelWithdrawTest(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:15" });
+  const wres1 = await withdrawViaBankV2(t, {
+    walletClient,
+    bank,
+    exchange,
+    amount: "TESTKUDOS:15",
+  });
+  await wres1.withdrawalFinishedCond;
 
   // Travel 400 days into the future,
   // as the deposit expiration is two years
@@ -47,21 +56,21 @@ export async function runTimetravelWithdrawTest(t: 
GlobalTestState) {
   };
 
   await exchange.stop();
-  exchange.setTimetravel(timetravelDuration);
+  exchange.setTimetravel(Duration.toMilliseconds(timetravelDuration));
   await exchange.start();
   await exchange.pingUntilAvailable();
   await exchange.keyup();
 
   await merchant.stop();
-  merchant.setTimetravel(timetravelDuration);
+  merchant.setTimetravel(Duration.toMilliseconds(timetravelDuration));
   await merchant.start();
   await merchant.pingUntilAvailable();
 
   console.log("starting withdrawal via bank");
 
   // This should fail, as the wallet didn't time travel yet.
-  await startWithdrawViaBank(t, {
-    wallet,
+  await withdrawViaBankV2(t, {
+    walletClient,
     bank,
     exchange,
     amount: "TESTKUDOS:20",
@@ -71,10 +80,7 @@ export async function runTimetravelWithdrawTest(t: 
GlobalTestState) {
 
   // Check that transactions are correct for the failed withdrawal
   {
-    console.log("running until done (should run into maxRetries limit)");
-    await wallet.runUntilDone({ maxRetries: 5 });
-    console.log("wallet done running");
-    const transactions = await wallet.client.call(
+    const transactions = await walletClient.call(
       WalletApiOperation.GetTransactions,
       {},
     );
@@ -88,7 +94,9 @@ export async function runTimetravelWithdrawTest(t: 
GlobalTestState) {
 
   // Now we also let the wallet time travel
 
-  wallet.setTimetravel(timetravelDuration);
+  walletClient.call(WalletApiOperation.TestingSetTimetravel, {
+    offsetMs: Duration.toMilliseconds(timetravelDuration),
+  });
 
   // This doesn't work yet, see https://bugs.taler.net/n/6585
 
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 5321cf5c7..21ac662c2 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-backup-basic.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-backup-basic.ts
@@ -21,9 +21,8 @@ import { j2s } from "@gnu-taler/taler-util";
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { GlobalTestState, WalletCli } from "../harness/harness.js";
 import {
-  createSimpleTestkudosEnvironment,
   createSimpleTestkudosEnvironmentV2,
-  withdrawViaBank,
+  createWalletDaemonWithClient,
   withdrawViaBankV2,
 } from "../harness/helpers.js";
 import { SyncService } from "../harness/sync.js";
@@ -112,40 +111,42 @@ export async function runWalletBackupBasicTest(t: 
GlobalTestState) {
   const txs = await walletClient.call(WalletApiOperation.GetTransactions, {});
   console.log(`backed up transactions ${j2s(txs)}`);
 
-  const wallet2 = new WalletCli(t, "wallet2");
+  const { walletClient: walletClient2 } = await 
createWalletDaemonWithClient(t, {
+    name: "w2"
+  });
 
   // Check that the second wallet is a fresh wallet.
   {
-    const bal = await wallet2.client.call(WalletApiOperation.GetBalances, {});
+    const bal = await walletClient2.call(WalletApiOperation.GetBalances, {});
     t.assertTrue(bal.balances.length === 0);
   }
 
-  await wallet2.client.call(WalletApiOperation.ImportBackupRecovery, {
+  await walletClient2.call(WalletApiOperation.ImportBackupRecovery, {
     recovery: backupRecovery,
   });
 
-  await wallet2.client.call(WalletApiOperation.RunBackupCycle, {});
+  await walletClient2.call(WalletApiOperation.RunBackupCycle, {});
 
   // Check that now the old balance is available!
   {
-    const bal = await wallet2.client.call(WalletApiOperation.GetBalances, {});
+    const bal = await walletClient2.call(WalletApiOperation.GetBalances, {});
     t.assertTrue(bal.balances.length === 1);
     console.log(bal);
   }
 
   // Now do some basic checks that the restored wallet is still functional
   {
-    const txs = await wallet2.client.call(
+    const txs = await walletClient2.call(
       WalletApiOperation.GetTransactions,
       {},
     );
     console.log(`restored transactions ${j2s(txs)}`);
-    const bal1 = await wallet2.client.call(WalletApiOperation.GetBalances, {});
+    const bal1 = await walletClient2.call(WalletApiOperation.GetBalances, {});
 
     t.assertAmountEquals(bal1.balances[0].available, "TESTKUDOS:14.1");
 
-    await withdrawViaBank(t, {
-      wallet: wallet2,
+    await withdrawViaBankV2(t, {
+      walletClient: walletClient2,
       bank,
       exchange,
       amount: "TESTKUDOS:10",
@@ -153,15 +154,15 @@ export async function runWalletBackupBasicTest(t: 
GlobalTestState) {
 
     await exchange.runWirewatchOnce();
 
-    await wallet2.runUntilDone();
+    await walletClient2.call(WalletApiOperation.TestingWaitTransactionsFinal, 
{});
 
-    const txs2 = await wallet2.client.call(
+    const txs2 = await walletClient2.call(
       WalletApiOperation.GetTransactions,
       {},
     );
     console.log(`tx after withdraw after restore ${j2s(txs2)}`);
 
-    const bal2 = await wallet2.client.call(WalletApiOperation.GetBalances, {});
+    const bal2 = await walletClient2.call(WalletApiOperation.GetBalances, {});
 
     t.assertAmountEquals(bal2.balances[0].available, "TESTKUDOS:23.82");
   }
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 e3e18d5a4..99adc1754 100644
--- 
a/packages/taler-harness/src/integrationtests/test-wallet-backup-doublespend.ts
+++ 
b/packages/taler-harness/src/integrationtests/test-wallet-backup-doublespend.ts
@@ -19,16 +19,12 @@
  */
 import { PreparePayResultType } from "@gnu-taler/taler-util";
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import {
-  GlobalTestState,
-  MerchantPrivateApi,
-  WalletCli,
-} from "../harness/harness.js";
+import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
 import {
   createSimpleTestkudosEnvironmentV2,
+  createWalletDaemonWithClient,
   makeTestPaymentV2,
-  withdrawViaBank,
-  withdrawViaBankV2
+  withdrawViaBankV2,
 } from "../harness/helpers.js";
 import { SyncService } from "../harness/sync.js";
 
@@ -58,7 +54,12 @@ export async function runWalletBackupDoublespendTest(t: 
GlobalTestState) {
     name: sync.baseUrl,
   });
 
-  await withdrawViaBankV2(t, { walletClient, bank, exchange, amount: 
"TESTKUDOS:10" });
+  await withdrawViaBankV2(t, {
+    walletClient,
+    bank,
+    exchange,
+    amount: "TESTKUDOS:10",
+  });
 
   await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
 
@@ -71,13 +72,16 @@ export async function runWalletBackupDoublespendTest(t: 
GlobalTestState) {
     {},
   );
 
-  const wallet2 = new WalletCli(t, "wallet2");
+  const { walletClient: walletClientTwo } = await createWalletDaemonWithClient(
+    t,
+    { name: "default" },
+  );
 
-  await wallet2.client.call(WalletApiOperation.ImportBackupRecovery, {
+  await walletClientTwo.call(WalletApiOperation.ImportBackupRecovery, {
     recovery: backupRecovery,
   });
 
-  await wallet2.client.call(WalletApiOperation.RunBackupCycle, {});
+  await walletClientTwo.call(WalletApiOperation.RunBackupCycle, {});
 
   console.log(
     "wallet1 balance before spend:",
@@ -103,7 +107,7 @@ export async function runWalletBackupDoublespendTest(t: 
GlobalTestState) {
   {
     console.log(
       "wallet2 balance:",
-      await wallet2.client.call(WalletApiOperation.GetBalances, {}),
+      await walletClientTwo.call(WalletApiOperation.GetBalances, {}),
     );
   }
 
@@ -134,11 +138,11 @@ export async function runWalletBackupDoublespendTest(t: 
GlobalTestState) {
     {
       console.log(
         "wallet2 balance before preparePay:",
-        await wallet2.client.call(WalletApiOperation.GetBalances, {}),
+        await walletClientTwo.call(WalletApiOperation.GetBalances, {}),
       );
     }
 
-    const preparePayResult = await wallet2.client.call(
+    const preparePayResult = await walletClientTwo.call(
       WalletApiOperation.PreparePayForUri,
       {
         talerPayUri: orderStatus.taler_pay_uri,
@@ -150,25 +154,28 @@ export async function runWalletBackupDoublespendTest(t: 
GlobalTestState) {
       PreparePayResultType.PaymentPossible,
     );
 
-    const res = await wallet2.client.call(WalletApiOperation.ConfirmPay, {
-      proposalId: preparePayResult.proposalId,
+    const res = await walletClientTwo.call(WalletApiOperation.ConfirmPay, {
+      transactionId: preparePayResult.transactionId,
     });
 
     console.log(res);
 
     // FIXME: wait for a notification that indicates insufficient funds!
 
-    await withdrawViaBank(t, {
-      wallet: wallet2,
+    await withdrawViaBankV2(t, {
+      walletClient: walletClientTwo,
       bank,
       exchange,
       amount: "TESTKUDOS:50",
     });
 
-    const bal = await wallet2.client.call(WalletApiOperation.GetBalances, {});
+    const bal = await walletClientTwo.call(WalletApiOperation.GetBalances, {});
     console.log("bal", bal);
 
-    await wallet2.runUntilDone();
+    await walletClientTwo.call(
+      WalletApiOperation.TestingWaitTransactionsFinal,
+      {},
+    );
   }
 }
 
diff --git 
a/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts 
b/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts
index c70fd51d4..3315a71d4 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-notifications.ts
@@ -92,7 +92,7 @@ export async function runWalletNotificationsTest(t: 
GlobalTestState) {
 
   // Fakebank uses x-taler-bank, but merchant is configured to only accept 
sepa!
   const label = "mymerchant";
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [
diff --git a/packages/taler-harness/src/integrationtests/test-wallettesting.ts 
b/packages/taler-harness/src/integrationtests/test-wallettesting.ts
index a856df79f..4fa870f1c 100644
--- a/packages/taler-harness/src/integrationtests/test-wallettesting.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallettesting.ts
@@ -91,7 +91,7 @@ export async function createMyEnvironment(
   await merchant.start();
   await merchant.pingUntilAvailable();
 
-  await merchant.addInstance({
+  await merchant.addInstanceWithWireAccount({
     id: "default",
     name: "Default Instance",
     paytoUris: [getPayto("merchant-default")],
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 c3069c317..1ba180fc1 100644
--- a/packages/taler-harness/src/integrationtests/test-withdrawal-abort-bank.ts
+++ b/packages/taler-harness/src/integrationtests/test-withdrawal-abort-bank.ts
@@ -23,7 +23,7 @@ import {
   BankAccessApiClient,
 } 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.
@@ -31,7 +31,8 @@ import { createSimpleTestkudosEnvironment } from 
"../harness/helpers.js";
 export async function runWithdrawalAbortBankTest(t: GlobalTestState) {
   // Set up test environment
 
-  const { wallet, bank, exchange } = await createSimpleTestkudosEnvironment(t);
+  const { walletClient, bank, exchange } =
+    await createSimpleTestkudosEnvironmentV2(t);
 
   // Create a withdrawal operation
 
@@ -48,11 +49,11 @@ export async function runWithdrawalAbortBankTest(t: 
GlobalTestState) {
 
   // Hand it to the wallet
 
-  await wallet.client.call(WalletApiOperation.GetWithdrawalDetailsForUri, {
+  await walletClient.call(WalletApiOperation.GetWithdrawalDetailsForUri, {
     talerWithdrawUri: wop.taler_withdraw_uri,
   });
 
-  await wallet.runPending();
+  await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
 
   // Abort it
 
@@ -67,13 +68,10 @@ export async function runWithdrawalAbortBankTest(t: 
GlobalTestState) {
   // WHY ?!
   //
   const e = await t.assertThrowsTalerErrorAsync(async () => {
-    await wallet.client.call(
-      WalletApiOperation.AcceptBankIntegratedWithdrawal,
-      {
-        exchangeBaseUrl: exchange.baseUrl,
-        talerWithdrawUri: wop.taler_withdraw_uri,
-      },
-    );
+    await walletClient.call(WalletApiOperation.AcceptBankIntegratedWithdrawal, 
{
+      exchangeBaseUrl: exchange.baseUrl,
+      talerWithdrawUri: wop.taler_withdraw_uri,
+    });
   });
   t.assertDeepEqual(
     e.errorDetail.code,
diff --git 
a/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts 
b/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts
index 06355b964..34dfb8fc9 100644
--- a/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts
+++ b/packages/taler-harness/src/integrationtests/test-withdrawal-fees.ts
@@ -17,22 +17,19 @@
 /**
  * Imports.
  */
+import { j2s } from "@gnu-taler/taler-util";
 import {
-  GlobalTestState,
-  WalletCli,
-  setupDb,
-  ExchangeService,
-  BankService,
-} from "../harness/harness.js";
-import {
-  BankAccessApi,
   BankAccessApiClient,
-  BankApi,
   WalletApiOperation,
 } from "@gnu-taler/taler-wallet-core";
 import { CoinConfig } from "../harness/denomStructures.js";
-import { j2s, URL } from "@gnu-taler/taler-util";
-import { withdrawViaBank } from "../harness/helpers.js";
+import {
+  BankService,
+  ExchangeService,
+  GlobalTestState,
+  WalletCli,
+  setupDb,
+} from "../harness/harness.js";
 
 const coinRsaCommon = {
   cipher: "RSA" as const,
@@ -119,7 +116,10 @@ export async function runWithdrawalFeesTest(t: 
GlobalTestState) {
   });
   const user = await bankAccessApiClient.createRandomBankUser();
   bankAccessApiClient.setAuth(user);
-  const wop = await 
bankAccessApiClient.createWithdrawalOperation(user.username, amount);
+  const wop = await bankAccessApiClient.createWithdrawalOperation(
+    user.username,
+    amount,
+  );
 
   // Hand it to the wallet
 
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts 
b/packages/taler-harness/src/integrationtests/testrunner.ts
index 7afd9bc83..3a49cf73c 100644
--- a/packages/taler-harness/src/integrationtests/testrunner.ts
+++ b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -115,6 +115,7 @@ import { runTermOfServiceFormatTest } from 
"./test-tos-format.js";
 import { runExchangePurseTest } from "./test-exchange-purse.js";
 import { getSharedTestDir } from "../harness/helpers.js";
 import { runStoredBackupsTest } from "./test-stored-backups.js";
+import { runPaymentExpiredTest } from "./test-payment-expired.js";
 
 /**
  * Test runner.
@@ -214,6 +215,7 @@ const allTests: TestMainFunction[] = [
   runWithdrawalHugeTest,
   runTermOfServiceFormatTest,
   runStoredBackupsTest,
+  runPaymentExpiredTest,
 ];
 
 export interface TestRunSpec {
diff --git a/packages/taler-util/src/merchant-api-types.ts 
b/packages/taler-util/src/merchant-api-types.ts
index 9f00173f2..ce30aa054 100644
--- a/packages/taler-util/src/merchant-api-types.ts
+++ b/packages/taler-util/src/merchant-api-types.ts
@@ -47,6 +47,7 @@ import {
   WireAccount,
   codecForWireAccount,
   codecForList,
+  HashCodeString,
 } from "@gnu-taler/taler-util";
 
 export interface MerchantPostOrderRequest {
@@ -384,3 +385,37 @@ export const codecForMerchantReserveCreateConfirmation =
       .property("accounts", codecForList(codecForWireAccount()))
       .property("reserve_pub", codecForString())
       .build("MerchantReserveCreateConfirmation");
+
+export interface AccountAddDetails {
+  // payto:// URI of the account.
+  payto_uri: string;
+
+  // URL from where the merchant can download information
+  // about incoming wire transfers to this account.
+  credit_facade_url?: string;
+
+  // Credentials to use when accessing the credit facade.
+  // Never returned on a GET (as this may be somewhat
+  // sensitive data). Can be set in POST
+  // or PATCH requests to update (or delete) credentials.
+  // To really delete credentials, set them to the type: "none".
+  credit_facade_credentials?: FacadeCredentials;
+}
+
+export type FacadeCredentials =
+  | NoFacadeCredentials
+  | BasicAuthFacadeCredentials;
+
+export interface NoFacadeCredentials {
+  type: "none";
+}
+
+export interface BasicAuthFacadeCredentials {
+  type: "basic";
+
+  // Username to use to authenticate
+  username: string;
+
+  // Password to use to authenticate
+  password: string;
+}
diff --git a/packages/taler-util/src/time.ts b/packages/taler-util/src/time.ts
index 55cda08a5..46ed37637 100644
--- a/packages/taler-util/src/time.ts
+++ b/packages/taler-util/src/time.ts
@@ -154,13 +154,27 @@ export interface TalerProtocolDuration {
   readonly d_us: number | "forever";
 }
 
+/**
+ * Timeshift in milliseconds.
+ */
 let timeshift = 0;
 
+/**
+ * Set timetravel offset in milliseconds.
+ *
+ * Use carefully and only for testing.
+ */
 export function setDangerousTimetravel(dt: number): void {
   timeshift = dt;
 }
 
 export namespace Duration {
+  export function toMilliseconds(d: Duration): number {
+    if (d.d_ms === "forever") {
+      return Number.MAX_VALUE;
+    }
+    return d.d_ms;
+  }
   export function getRemaining(
     deadline: AbsoluteTime,
     now = AbsoluteTime.now(),
diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index d49182e26..0070b18e4 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -2685,3 +2685,13 @@ export const codecForRecoverStoredBackupRequest =
     buildCodecForObject<RecoverStoredBackupRequest>()
       .property("name", codecForString())
       .build("RecoverStoredBackupRequest");
+
+export interface TestingSetTimetravelRequest {
+  offsetMs: number;
+}
+
+export const codecForTestingSetTimetravelRequest =
+  (): Codec<TestingSetTimetravelRequest> =>
+    buildCodecForObject<TestingSetTimetravelRequest>()
+      .property("offsetMs", codecForNumber())
+      .build("TestingSetTimetravelRequest");
diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts 
b/packages/taler-wallet-core/src/wallet-api-types.ts
index 4d9d40c43..72cd37b10 100644
--- a/packages/taler-wallet-core/src/wallet-api-types.ts
+++ b/packages/taler-wallet-core/src/wallet-api-types.ts
@@ -119,6 +119,7 @@ import {
   CreateStoredBackupResponse,
   RecoverStoredBackupRequest,
   DeleteStoredBackupRequest,
+  TestingSetTimetravelRequest,
 } from "@gnu-taler/taler-util";
 import { AuditorTrustRecord, WalletContractData } from "./db.js";
 import {
@@ -215,6 +216,7 @@ export enum WalletApiOperation {
   ValidateIban = "validateIban",
   TestingWaitTransactionsFinal = "testingWaitTransactionsFinal",
   TestingWaitRefreshesFinal = "testingWaitRefreshesFinal",
+  TestingSetTimetravel = "testingSetTimetravel",
   GetScopedCurrencyInfo = "getScopedCurrencyInfo",
   ListStoredBackups = "listStoredBackups",
   CreateStoredBackup = "createStoredBackup",
@@ -989,6 +991,15 @@ export type DumpCoinsOp = {
   response: CoinDumpJson;
 };
 
+/**
+ * Add an offset to the wallet's internal time.
+ */
+export type TestingSetTimetravelOp = {
+  op: WalletApiOperation.TestingSetTimetravel;
+  request: TestingSetTimetravelRequest;
+  response: EmptyObject;
+};
+
 /**
  * Wait until all transactions are in a final state.
  */
@@ -1111,6 +1122,7 @@ export type WalletOperations = {
   [WalletApiOperation.ValidateIban]: ValidateIbanOp;
   [WalletApiOperation.TestingWaitTransactionsFinal]: 
TestingWaitTransactionsFinal;
   [WalletApiOperation.TestingWaitRefreshesFinal]: TestingWaitRefreshesFinal;
+  [WalletApiOperation.TestingSetTimetravel]: TestingSetTimetravelOp;
   [WalletApiOperation.GetScopedCurrencyInfo]: GetScopedCurrencyInfoOp;
   [WalletApiOperation.CreateStoredBackup]: CreateStoredBackupsOp;
   [WalletApiOperation.ListStoredBackups]: ListStoredBackupsOp;
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index 5666d67e0..4194ab9eb 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -126,6 +126,8 @@ import {
   DeleteStoredBackupRequest,
   RecoverStoredBackupRequest,
   codecForRecoverStoredBackupRequest,
+  codecForTestingSetTimetravelRequest,
+  setDangerousTimetravel,
 } from "@gnu-taler/taler-util";
 import {
   HttpRequestLibrary,
@@ -1674,6 +1676,11 @@ async function dispatchRequestInternal<Op extends 
WalletApiOperation>(
       return await waitUntilDone(ws);
     case WalletApiOperation.TestingWaitRefreshesFinal:
       return await waitUntilRefreshesDone(ws);
+    case WalletApiOperation.TestingSetTimetravel: {
+      const req = codecForTestingSetTimetravelRequest().decode(payload);
+      setDangerousTimetravel(req.offsetMs);
+      ws.workAvailable.trigger();
+    }
     // default:
     //  assertUnreachable(operation);
   }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]