gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: using new wallet api (typed i


From: gnunet
Subject: [taler-wallet-core] branch master updated: using new wallet api (typed interface)
Date: Tue, 25 Oct 2022 17:24:01 +0200

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

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

The following commit(s) were added to refs/heads/master by this push:
     new 3f2db7707 using new wallet api (typed interface)
3f2db7707 is described below

commit 3f2db7707fdf4eb4c1dfdb527d5726dd1694e126
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Tue Oct 25 12:23:08 2022 -0300

    using new wallet api (typed interface)
---
 packages/taler-util/src/wallet-types.ts            |  38 +-
 packages/taler-wallet-core/src/wallet-api-types.ts |   5 +-
 packages/taler-wallet-core/src/wallet.ts           |  14 +-
 packages/taler-wallet-webextension/package.json    |   2 +-
 .../src/components/PendingTransactions.tsx         |  13 +-
 .../src/components/ShowFullContractTermPopup.tsx   |  13 +-
 .../src/components/TermsOfService/index.ts         |   4 +-
 .../src/components/TermsOfService/state.ts         |  18 +-
 .../src/cta/Deposit/index.ts                       |   2 +-
 .../src/cta/Deposit/state.ts                       |  19 +-
 .../src/cta/Deposit/test.ts                        |  89 ++--
 .../src/cta/InvoiceCreate/index.ts                 |   2 +-
 .../src/cta/InvoiceCreate/state.ts                 |   8 +-
 .../src/cta/InvoicePay/index.ts                    |   4 +-
 .../src/cta/InvoicePay/state.ts                    |  32 +-
 .../src/cta/Payment/index.ts                       |  13 +-
 .../src/cta/Payment/state.ts                       |  32 +-
 .../src/cta/Payment/test.ts                        | 577 ++++++++++-----------
 .../src/cta/Recovery/index.ts                      |   3 +-
 .../src/cta/Recovery/state.ts                      |   5 +-
 .../src/cta/Refund/index.ts                        |   4 +-
 .../src/cta/Refund/state.ts                        |  18 +-
 .../src/cta/Refund/test.ts                         | 389 ++++++++------
 .../taler-wallet-webextension/src/cta/Tip/index.ts |   4 +-
 .../taler-wallet-webextension/src/cta/Tip/state.ts |  17 +-
 .../taler-wallet-webextension/src/cta/Tip/test.ts  | 163 +++---
 .../src/cta/TransferCreate/index.ts                |   2 +-
 .../src/cta/TransferCreate/state.ts                |   6 +-
 .../src/cta/TransferPickup/index.ts                |   4 +-
 .../src/cta/TransferPickup/state.ts                |  11 +-
 .../src/cta/Withdraw/index.ts                      |   6 +-
 .../src/cta/Withdraw/state.ts                      |  41 +-
 .../src/cta/Withdraw/test.ts                       | 258 +++++----
 .../src/hooks/useAsyncAsHook.ts                    |   3 +-
 .../src/hooks/useAutoOpenPermissions.ts            |  14 +-
 .../src/hooks/useBackupDeviceName.ts               |   7 +-
 .../src/hooks/useClipboardPermissions.ts           |  12 +-
 .../src/hooks/useDiagnostics.ts                    |   4 +-
 .../src/hooks/useProviderStatus.ts                 |  14 +-
 .../src/hooks/useTalerActionURL.test.ts            |  12 +-
 .../src/hooks/useWalletDevMode.ts                  |   6 +-
 .../src/popup/BalancePage.tsx                      |  19 +-
 .../taler-wallet-webextension/src/test-utils.ts    | 164 ++++--
 .../src/wallet/AddAccount/index.ts                 |  10 +-
 .../src/wallet/AddAccount/state.ts                 |  21 +-
 .../src/wallet/BackupPage.tsx                      |  26 +-
 .../src/wallet/CreateManualWithdraw.test.ts        |  66 +--
 .../src/wallet/DepositPage/index.ts                |  21 +-
 .../src/wallet/DepositPage/state.ts                |  40 +-
 .../src/wallet/DepositPage/test.ts                 | 498 ++++++------------
 .../src/wallet/DestinationSelection.tsx            |   7 +-
 .../src/wallet/DeveloperPage.tsx                   |  34 +-
 .../src/wallet/EmptyComponentExample/index.ts      |   4 +-
 .../src/wallet/EmptyComponentExample/state.ts      |   2 +-
 .../src/wallet/ExchangeAddPage.tsx                 |   9 +-
 .../src/wallet/ExchangeSelection/index.ts          |   7 +-
 .../src/wallet/ExchangeSelection/state.ts          |  12 +-
 .../src/wallet/History.tsx                         |  13 +-
 .../src/wallet/ManualWithdrawPage.tsx              |  23 +-
 .../src/wallet/ProviderAddPage.tsx                 |   5 +-
 .../src/wallet/ProviderDetailPage.tsx              |  24 +-
 .../src/wallet/Settings.tsx                        |   6 +-
 .../src/wallet/Transaction.tsx                     |  59 ++-
 packages/taler-wallet-webextension/src/wxApi.ts    | 499 ++----------------
 64 files changed, 1545 insertions(+), 1912 deletions(-)

diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index 13fcb94ff..8737bc3f0 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -32,26 +32,24 @@ import {
   codecForAmountJson,
   codecForAmountString,
 } from "./amounts.js";
-import {
-  AbsoluteTime,
-  codecForAbsoluteTime,
-  codecForTimestamp,
-  TalerProtocolDuration,
-  TalerProtocolTimestamp,
-} from "./time.js";
+import { BackupRecovery } from "./backup-types.js";
 import {
   buildCodecForObject,
-  codecForString,
-  codecOptional,
+  buildCodecForUnion,
   Codec,
-  codecForList,
+  codecForAny,
   codecForBoolean,
   codecForConstString,
-  codecForAny,
-  buildCodecForUnion,
-  codecForNumber,
+  codecForList,
   codecForMap,
+  codecForNumber,
+  codecForString,
+  codecOptional,
 } from "./codec.js";
+import { VersionMatchResult } from "./libtool-version.js";
+import { PaytoUri } from "./payto.js";
+import { AgeCommitmentProof } from "./taler-crypto.js";
+import { TalerErrorCode } from "./taler-error-codes.js";
 import {
   AmountString,
   AuditorDenomSig,
@@ -64,14 +62,16 @@ import {
   UnblindedSignature,
 } from "./taler-types.js";
 import {
-  OrderShortInfo,
+  AbsoluteTime,
+  codecForAbsoluteTime,
+  codecForTimestamp,
+  TalerProtocolDuration,
+  TalerProtocolTimestamp,
+} from "./time.js";
+import {
   codecForOrderShortInfo,
+  OrderShortInfo,
 } from "./transactions-types.js";
-import { BackupRecovery } from "./backup-types.js";
-import { PaytoUri } from "./payto.js";
-import { TalerErrorCode } from "./taler-error-codes.js";
-import { AgeCommitmentProof } from "./taler-crypto.js";
-import { VersionMatchResult } from "./libtool-version.js";
 
 /**
  * Identifier for a transaction in the wallet.
diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts 
b/packages/taler-wallet-core/src/wallet-api-types.ts
index 302b0e2e1..e36e630f4 100644
--- a/packages/taler-wallet-core/src/wallet-api-types.ts
+++ b/packages/taler-wallet-core/src/wallet-api-types.ts
@@ -35,6 +35,7 @@ import {
   AcceptWithdrawalResponse,
   AddExchangeRequest,
   AddKnownBankAccountsRequest,
+  ApplyDevExperimentRequest,
   ApplyRefundFromPurchaseIdRequest,
   ApplyRefundRequest,
   ApplyRefundResponse,
@@ -98,12 +99,12 @@ import {
   WithdrawTestBalanceRequest,
   WithdrawUriInfoResponse,
 } from "@gnu-taler/taler-util";
-import { ApplyDevExperimentRequest } from "@gnu-taler/taler-util";
 import { WalletContractData } from "./db.js";
 import {
   AddBackupProviderRequest,
   BackupInfo,
   RemoveBackupProviderRequest,
+  RunBackupCycleRequest,
 } from "./operations/backup/index.js";
 import { PendingOperationsResponse as PendingTasksResponse } from 
"./pending-types.js";
 
@@ -496,7 +497,7 @@ export type ImportBackupRecoveryOp = {
  */
 export type RunBackupCycleOp = {
   op: WalletApiOperation.RunBackupCycle;
-  request: EmptyObject;
+  request: RunBackupCycleRequest;
   response: EmptyObject;
 };
 
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index de7f6f42c..04645a4e8 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -78,7 +78,7 @@ import {
   Duration,
   durationFromSpec,
   durationMin,
-  ExchangeFullDetails,
+  ExchangeDetailedResponse,
   ExchangeListItem,
   ExchangesListResponse,
   ExchangeTosStatusDetails,
@@ -664,7 +664,7 @@ async function getExchanges(
 async function getExchangeDetailedInfo(
   ws: InternalWalletState,
   exchangeBaseurl: string,
-): Promise<ExchangeFullDetails> {
+): Promise<ExchangeDetailedResponse> {
   //TODO: should we use the forceUpdate parameter?
   const exchange = await ws.db
     .mktx((x) => [
@@ -819,10 +819,12 @@ async function getExchangeDetailedInfo(
   );
 
   return {
-    ...exchange.info,
-    denomFees,
-    transferFees,
-    globalFees,
+    exchange: {
+      ...exchange.info,
+      denomFees,
+      transferFees,
+      globalFees,
+    },
   };
 }
 
diff --git a/packages/taler-wallet-webextension/package.json 
b/packages/taler-wallet-webextension/package.json
index 75c96a17b..f0863df84 100644
--- a/packages/taler-wallet-webextension/package.json
+++ b/packages/taler-wallet-webextension/package.json
@@ -9,7 +9,7 @@
   "private": false,
   "scripts": {
     "clean": "rimraf dist lib tsconfig.tsbuildinfo",
-    "test": "pnpm compile && mocha --enable-source-maps 'dist/**/*.test.js' 
'dist/**/test.js'",
+    "test": "pnpm compile && mocha 'dist/**/*.test.js' 'dist/**/test.js'",
     "test:coverage": "nyc pnpm test",
     "compile": "tsc && ./build-fast-with-linaria.mjs",
     "prepare": "pnpm compile",
diff --git 
a/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx 
b/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
index e9688da21..5d5dae092 100644
--- a/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
+++ b/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
@@ -19,13 +19,14 @@ import {
   NotificationType,
   Transaction,
 } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { Fragment, h, JSX, VNode } from "preact";
 import { useEffect } from "preact/hooks";
 import { useTranslationContext } from "../context/translation.js";
 import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
 import { Avatar } from "../mui/Avatar.js";
 import { Typography } from "../mui/Typography.js";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 import Banner from "./Banner.js";
 import { Time } from "./Time.js";
 
@@ -34,14 +35,14 @@ interface Props extends JSX.HTMLAttributes {
 }
 
 export function PendingTransactions({ goToTransaction }: Props): VNode {
-  const state = useAsyncAsHook(wxApi.getTransactions);
+  const state = useAsyncAsHook(() =>
+    wxApi.wallet.call(WalletApiOperation.GetTransactions, {}),
+  );
 
   useEffect(() => {
-    return wxApi.onUpdateNotification(
+    return wxApi.listener.onUpdateNotification(
       [NotificationType.WithdrawGroupFinished],
-      () => {
-        state?.retry();
-      },
+      state?.retry,
     );
   });
 
diff --git 
a/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx
 
b/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx
index 7c1d2c6fc..6461f76e3 100644
--- 
a/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx
+++ 
b/packages/taler-wallet-webextension/src/components/ShowFullContractTermPopup.tsx
@@ -14,7 +14,10 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 import { AbsoluteTime, Duration, Location } from "@gnu-taler/taler-util";
-import { WalletContractData } from "@gnu-taler/taler-wallet-core";
+import {
+  WalletApiOperation,
+  WalletContractData,
+} from "@gnu-taler/taler-wallet-core";
 import { styled } from "@linaria/react";
 import { Fragment, h, VNode } from "preact";
 import { useState } from "preact/hooks";
@@ -26,9 +29,9 @@ import { useTranslationContext } from 
"../context/translation.js";
 import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
 import { ButtonHandler } from "../mui/handlers.js";
 import { compose, StateViewMap } from "../utils/index.js";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 import { Amount } from "./Amount.js";
-import { Link, LinkPrimary } from "./styled/index.js";
+import { Link } from "./styled/index.js";
 
 const ContractTermsTable = styled.table`
   width: 100%;
@@ -99,7 +102,9 @@ function useComponentState({ proposalId }: Props, api: 
typeof wxApi): State {
   const [show, setShow] = useState(false);
   const hook = useAsyncAsHook(async () => {
     if (!show) return undefined;
-    return await api.getContractTermsDetails(proposalId);
+    return await api.wallet.call(WalletApiOperation.GetContractTermsDetails, {
+      proposalId,
+    });
   }, [show]);
 
   const hideHandler = {
diff --git 
a/packages/taler-wallet-webextension/src/components/TermsOfService/index.ts 
b/packages/taler-wallet-webextension/src/components/TermsOfService/index.ts
index 2c77e5d3c..79778a595 100644
--- a/packages/taler-wallet-webextension/src/components/TermsOfService/index.ts
+++ b/packages/taler-wallet-webextension/src/components/TermsOfService/index.ts
@@ -18,7 +18,7 @@ import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { ToggleHandler } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
 import { TermsState } from "./utils.js";
 import {
@@ -26,7 +26,7 @@ import {
   LoadingUriView,
   ShowButtonsAcceptedTosView,
   ShowButtonsNonAcceptedTosView,
-  ShowTosContentView,
+  ShowTosContentView
 } from "./views.js";
 
 export interface Props {
diff --git 
a/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts 
b/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts
index 30322e139..3cad967ae 100644
--- a/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts
+++ b/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts
@@ -14,9 +14,10 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useState } from "preact/hooks";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 import { buildTermsOfServiceState } from "./utils.js";
 
@@ -34,7 +35,10 @@ export function useComponentState(
    * For the exchange selected, bring the status of the terms of service
    */
   const terms = useAsyncAsHook(async () => {
-    const exchangeTos = await api.getExchangeTos(exchangeUrl, ["text/xml"]);
+    const exchangeTos = await 
api.wallet.call(WalletApiOperation.GetExchangeTos, {
+      exchangeBaseUrl: exchangeUrl,
+      acceptedFormat: ["text/xml"]
+    })
 
     const state = buildTermsOfServiceState(exchangeTos);
 
@@ -72,10 +76,16 @@ export function useComponentState(
 
     try {
       if (accepted) {
-        await api.setExchangeTosAccepted(exchangeUrl, state.version);
+        api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, {
+          exchangeBaseUrl: exchangeUrl,
+          etag: state.version
+        })
       } else {
         // mark as not accepted
-        await api.setExchangeTosAccepted(exchangeUrl, undefined);
+        api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, {
+          exchangeBaseUrl: exchangeUrl,
+          etag: undefined
+        })
       }
       // setAccepted(accepted);
       if (!readOnly) onChange(accepted); //external update
diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/index.ts 
b/packages/taler-wallet-webextension/src/cta/Deposit/index.ts
index 0246b6f7c..539709821 100644
--- a/packages/taler-wallet-webextension/src/cta/Deposit/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Deposit/index.ts
@@ -19,7 +19,7 @@ import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { ButtonHandler } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
 import { LoadingUriView, ReadyView } from "./views.js";
 
diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/state.ts 
b/packages/taler-wallet-webextension/src/cta/Deposit/state.ts
index 5662a24c8..ba7bd147b 100644
--- a/packages/taler-wallet-webextension/src/cta/Deposit/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Deposit/state.ts
@@ -14,10 +14,10 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { Amounts, CreateDepositGroupResponse } from "@gnu-taler/taler-util";
-import { useState } from "preact/hooks";
+import { Amounts } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState(
@@ -29,10 +29,10 @@ export function useComponentState(
     if (!amountStr) throw Error("ERROR_NO-AMOUNT-FOR-DEPOSIT");
     const amount = Amounts.parse(amountStr);
     if (!amount) throw Error("ERROR_INVALID-AMOUNT-FOR-DEPOSIT");
-    const deposit = await api.prepareDeposit(
-      talerDepositUri,
-      Amounts.stringify(amount),
-    );
+    const deposit = await api.wallet.call(WalletApiOperation.PrepareDeposit, {
+      amount: Amounts.stringify(amount),
+      depositPaytoUri: talerDepositUri,
+    });
     return { deposit, uri: talerDepositUri, amount };
   });
 
@@ -46,7 +46,10 @@ export function useComponentState(
 
   const { deposit, uri, amount } = info.response;
   async function doDeposit(): Promise<void> {
-    const resp = await api.createDepositGroup(uri, Amounts.stringify(amount));
+    const resp = await api.wallet.call(WalletApiOperation.CreateDepositGroup, {
+      amount: Amounts.stringify(amount),
+      depositPaytoUri: uri,
+    });
     onSuccess(resp.transactionId);
   }
 
diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/test.ts 
b/packages/taler-wallet-webextension/src/cta/Deposit/test.ts
index b6e63a796..f628b3287 100644
--- a/packages/taler-wallet-webextension/src/cta/Deposit/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Deposit/test.ts
@@ -19,43 +19,40 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { Amounts, PrepareDepositResponse } from "@gnu-taler/taler-util";
+import { Amounts } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { expect } from "chai";
 import { mountHook } from "../../test-utils.js";
+import { createWalletApiMock } from "../../test-utils.js";
 import { useComponentState } from "./state.js";
 
 describe("Deposit CTA states", () => {
   it("should tell the user that the URI is missing", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerDepositUri: undefined,
+      amountStr: undefined,
+      cancel: async () => {
+        null;
+      },
+      onSuccess: async () => {
+        null;
+      },
+    }
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
-        useComponentState(
-          {
-            talerDepositUri: undefined,
-            amountStr: undefined,
-            cancel: async () => {
-              null;
-            },
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            prepareRefund: async () => ({}),
-            applyRefund: async () => ({}),
-            onUpdateNotification: async () => ({}),
-          } as any,
-        ),
+        useComponentState(props, mock),
       );
 
     {
-      const { status } = getLastResultOrThrow();
+      const { status } = pullLastResultOrThrow();
       expect(status).equals("loading");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
 
       expect(status).equals("loading-uri");
 
@@ -64,44 +61,41 @@ describe("Deposit CTA states", () => {
       if (error.operational) expect.fail();
       expect(error.message).eq("ERROR_NO-URI-FOR-DEPOSIT");
     }
-
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should be ready after loading", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    handler.addWalletCallResponse(WalletApiOperation.PrepareDeposit, 
undefined, {
+      effectiveDepositAmount: Amounts.parseOrThrow("EUR:1"),
+      totalDepositCost: Amounts.parseOrThrow("EUR:1.2"),
+    });
+    const props = {
+      talerDepositUri: "payto://refund/asdasdas",
+      amountStr: "EUR:1",
+      cancel: async () => {
+        null;
+      },
+      onSuccess: async () => {
+        null;
+      },
+    }
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
-        useComponentState(
-          {
-            talerDepositUri: "payto://refund/asdasdas",
-            amountStr: "EUR:1",
-            cancel: async () => {
-              null;
-            },
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            prepareDeposit: async () =>
-              ({
-                effectiveDepositAmount: Amounts.parseOrThrow("EUR:1"),
-                totalDepositCost: Amounts.parseOrThrow("EUR:1.2"),
-              } as PrepareDepositResponse as any),
-            createDepositGroup: async () => ({}),
-          } as any,
-        ),
+        useComponentState(props, mock),
       );
 
     {
-      const { status } = getLastResultOrThrow();
+      const { status } = pullLastResultOrThrow();
       expect(status).equals("loading");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
 
       if (state.status !== "ready") expect.fail();
       if (state.error) expect.fail();
@@ -112,5 +106,6 @@ describe("Deposit CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty");
   });
 });
diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts 
b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts
index ff04a8247..0389a17fb 100644
--- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts
@@ -22,7 +22,7 @@ import { ButtonHandler, TextFieldHandler } from 
"../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
 import { ExchangeSelectionPage } from 
"../../wallet/ExchangeSelection/index.js";
 import { NoExchangesView } from "../../wallet/ExchangeSelection/views.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
 import { LoadingUriView, ReadyView } from "./views.js";
 
diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts 
b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts
index 205a664e0..d845e121a 100644
--- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts
@@ -16,11 +16,11 @@
 
 /* eslint-disable react-hooks/rules-of-hooks */
 import { Amounts, TalerErrorDetail } from "@gnu-taler/taler-util";
-import { TalerError } from "@gnu-taler/taler-wallet-core";
+import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useState } from "preact/hooks";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
 import { useSelectedExchange } from "../../hooks/useSelectedExchange.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 type RecursiveState<S extends object> = S | (() => RecursiveState<S>);
@@ -31,7 +31,7 @@ export function useComponentState(
 ): RecursiveState<State> {
   const amount = Amounts.parseOrThrow(amountStr);
 
-  const hook = useAsyncAsHook(api.listExchanges);
+  const hook = useAsyncAsHook(() => 
api.wallet.call(WalletApiOperation.ListExchanges, {}));
 
   if (!hook) {
     return {
@@ -69,7 +69,7 @@ export function useComponentState(
 
     async function accept(): Promise<void> {
       try {
-        const resp = await api.initiatePeerPullPayment({
+        const resp = await 
api.wallet.call(WalletApiOperation.InitiatePeerPullPayment, {
           amount: Amounts.stringify(amount),
           exchangeBaseUrl: exchange.exchangeBaseUrl,
           partialContractTerms: {
diff --git a/packages/taler-wallet-webextension/src/cta/InvoicePay/index.ts 
b/packages/taler-wallet-webextension/src/cta/InvoicePay/index.ts
index 7c6f13286..693803587 100644
--- a/packages/taler-wallet-webextension/src/cta/InvoicePay/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/InvoicePay/index.ts
@@ -18,13 +18,13 @@ import {
   AbsoluteTime,
   AmountJson,
   PreparePayResult,
-  TalerErrorDetail,
+  TalerErrorDetail
 } from "@gnu-taler/taler-util";
 import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { ButtonHandler } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
 import { LoadingUriView, ReadyView } from "./views.js";
 
diff --git a/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts 
b/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts
index c88e80602..457827127 100644
--- a/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/InvoicePay/state.ts
@@ -21,12 +21,12 @@ import {
   PreparePayResult,
   PreparePayResultType,
   TalerErrorDetail,
-  TalerProtocolTimestamp,
+  TalerProtocolTimestamp
 } from "@gnu-taler/taler-util";
-import { TalerError } from "@gnu-taler/taler-wallet-core";
+import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useEffect, useState } from "preact/hooks";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState(
@@ -34,18 +34,17 @@ export function useComponentState(
   api: typeof wxApi,
 ): State {
   const hook = useAsyncAsHook(async () => {
-    const p2p = await api.checkPeerPullPayment({
+    const p2p = await api.wallet.call(WalletApiOperation.CheckPeerPullPayment, 
{
       talerUri: talerPayPullUri,
     });
-    const balance = await api.getBalance();
+    const balance = await api.wallet.call(WalletApiOperation.GetBalances, {});
     return { p2p, balance };
   });
 
-  useEffect(() => {
-    api.onUpdateNotification([NotificationType.CoinWithdrawn], () => {
-      hook?.retry();
-    });
-  });
+  useEffect(() => api.listener.onUpdateNotification(
+    [NotificationType.CoinWithdrawn],
+    hook?.retry
+  ));
 
   const [operationError, setOperationError] = useState<
     TalerErrorDetail | undefined
@@ -64,10 +63,7 @@ export function useComponentState(
     };
   }
 
-  // const { payStatus } = hook.response.p2p;
-
   const {
-    amount: purseAmount,
     contractTerms,
     peerPullPaymentIncomingId,
   } = hook.response.p2p;
@@ -136,17 +132,9 @@ export function useComponentState(
     };
   }
 
-  // if (payStatus.status === PreparePayResultType.AlreadyConfirmed) {
-  //   return {
-  //     status: "confirmed",
-  //     balance: foundAmount,
-  //     ...baseResult,
-  //   };
-  // }
-
   async function accept(): Promise<void> {
     try {
-      const resp = await api.acceptPeerPullPayment({
+      const resp = await 
api.wallet.call(WalletApiOperation.AcceptPeerPullPayment, {
         peerPullPaymentIncomingId,
       });
       onSuccess(resp.transactionId);
diff --git a/packages/taler-wallet-webextension/src/cta/Payment/index.ts 
b/packages/taler-wallet-webextension/src/cta/Payment/index.ts
index 8e446722e..b4e59e666 100644
--- a/packages/taler-wallet-webextension/src/cta/Payment/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Payment/index.ts
@@ -15,21 +15,16 @@
  */
 
 import {
-  AmountJson,
-  ConfirmPayResult,
-  PreparePayResult,
-  PreparePayResultAlreadyConfirmed,
-  PreparePayResultInsufficientBalance,
-  PreparePayResultPaymentPossible,
+  AmountJson, PreparePayResult,
+  PreparePayResultAlreadyConfirmed, PreparePayResultPaymentPossible
 } from "@gnu-taler/taler-util";
-import { TalerError } from "@gnu-taler/taler-wallet-core";
 import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { ButtonHandler } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
-import { LoadingUriView, BaseView } from "./views.js";
+import { BaseView, LoadingUriView } from "./views.js";
 
 export interface Props {
   talerPayUri?: string;
diff --git a/packages/taler-wallet-webextension/src/cta/Payment/state.ts 
b/packages/taler-wallet-webextension/src/cta/Payment/state.ts
index 8d388aa60..414bc2000 100644
--- a/packages/taler-wallet-webextension/src/cta/Payment/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Payment/state.ts
@@ -15,19 +15,16 @@
  */
 
 import {
-  AmountJson,
-  Amounts,
-  ConfirmPayResult,
-  ConfirmPayResultType,
+  Amounts, ConfirmPayResultType,
   NotificationType,
   PreparePayResultType,
-  TalerErrorCode,
+  TalerErrorCode
 } from "@gnu-taler/taler-util";
-import { TalerError } from "@gnu-taler/taler-wallet-core";
+import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useEffect, useState } from "preact/hooks";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
 import { ButtonHandler } from "../../mui/handlers.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState(
@@ -38,16 +35,17 @@ export function useComponentState(
 
   const hook = useAsyncAsHook(async () => {
     if (!talerPayUri) throw Error("ERROR_NO-URI-FOR-PAYMENT");
-    const payStatus = await api.preparePay(talerPayUri);
-    const balance = await api.getBalance();
+    const payStatus = await 
api.wallet.call(WalletApiOperation.PreparePayForUri, {
+      talerPayUri: talerPayUri
+    });
+    const balance = await api.wallet.call(WalletApiOperation.GetBalances, {});
     return { payStatus, balance, uri: talerPayUri };
-  });
+  }, []);
 
-  useEffect(() => {
-    api.onUpdateNotification([NotificationType.CoinWithdrawn], () => {
-      hook?.retry();
-    });
-  });
+  useEffect(() => api.listener.onUpdateNotification(
+    [NotificationType.CoinWithdrawn],
+    hook?.retry
+  ), [hook]);
 
   const hookResponse = !hook || hook.hasError ? undefined : hook.response;
 
@@ -127,7 +125,9 @@ export function useComponentState(
           hint: `payment is not possible: ${payStatus.status}`,
         });
       }
-      const res = await api.confirmPay(payStatus.proposalId, undefined);
+      const res = await api.wallet.call(WalletApiOperation.ConfirmPay, {
+        proposalId: payStatus.proposalId,
+      });
       // handle confirm pay
       if (res.type !== ConfirmPayResultType.Done) {
         throw TalerError.fromUncheckedDetail({
diff --git a/packages/taler-wallet-webextension/src/cta/Payment/test.ts 
b/packages/taler-wallet-webextension/src/cta/Payment/test.ts
index f4ce5afb3..8aa099fdc 100644
--- a/packages/taler-wallet-webextension/src/cta/Payment/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Payment/test.ts
@@ -20,81 +20,44 @@
  */
 
 import {
-  AmountJson,
-  Amounts,
-  BalancesResponse,
-  ConfirmPayResult,
+  Amounts, ConfirmPayResult,
   ConfirmPayResultType,
-  NotificationType,
-  PreparePayResult,
-  PreparePayResultType,
+  NotificationType, PreparePayResultInsufficientBalance,
+  PreparePayResultPaymentPossible,
+  PreparePayResultType
 } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { expect } from "chai";
-import { mountHook } from "../../test-utils.js";
+import { mountHook, nullFunction } from "../../test-utils.js";
+import { createWalletApiMock } from "../../test-utils.js";
 import { useComponentState } from "./state.js";
-import * as wxApi from "../../wxApi.js";
-
-const nullFunction: any = () => null;
-type VoidFunction = () => void;
-
-type Subs = {
-  [key in NotificationType]?: VoidFunction;
-};
-
-export class SubsHandler {
-  private subs: Subs = {};
-
-  constructor() {
-    this.saveSubscription = this.saveSubscription.bind(this);
-  }
-
-  saveSubscription(
-    messageTypes: NotificationType[],
-    callback: VoidFunction,
-  ): VoidFunction {
-    messageTypes.forEach((m) => {
-      this.subs[m] = callback;
-    });
-    return nullFunction;
-  }
-
-  notifyEvent(event: NotificationType): void {
-    const cb = this.subs[event];
-    if (cb === undefined)
-      expect.fail(`Expected to have a subscription for ${event}`);
-    cb();
-  }
-}
 
 describe("Payment CTA states", () => {
   it("should tell the user that the URI is missing", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerPayUri: undefined,
+      cancel: nullFunction,
+      goToWalletManualWithdraw: nullFunction,
+      onSuccess: async () => {
+        null;
+      },
+    }
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
-        useComponentState(
-          {
-            talerPayUri: undefined,
-            cancel: nullFunction,
-            goToWalletManualWithdraw: nullFunction,
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            onUpdateNotification: nullFunction,
-          } as Partial<typeof wxApi> as any,
-        ),
+        useComponentState(props, mock),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
 
       expect(status).equals("loading-uri");
       if (error === undefined) expect.fail();
@@ -103,324 +66,312 @@ describe("Payment CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should response with no balance", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerPayUri: "taller://pay",
+      cancel: nullFunction,
+      goToWalletManualWithdraw: nullFunction,
+      onSuccess: async () => {
+        null;
+      },
+    }
+
+    handler.addWalletCallResponse(WalletApiOperation.PreparePayForUri, 
undefined, {
+      status: PreparePayResultType.InsufficientBalance,
+      amountRaw: "USD:10",
+    } as PreparePayResultInsufficientBalance)
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, {}, { 
balances: [] })
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
-        useComponentState(
-          {
-            talerPayUri: "taller://pay",
-            cancel: nullFunction,
-            goToWalletManualWithdraw: nullFunction,
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            onUpdateNotification: nullFunction,
-            preparePay: async () =>
-              ({
-                amountRaw: "USD:10",
-                status: PreparePayResultType.InsufficientBalance,
-              } as Partial<PreparePayResult>),
-            getBalance: async () =>
-              ({
-                balances: [],
-              } as Partial<BalancesResponse>),
-          } as Partial<typeof wxApi> as any,
-        ),
+        useComponentState(props, mock),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
-      if (r.status !== "no-balance-for-currency") expect.fail();
+      const r = pullLastResultOrThrow();
+      if (r.status !== "no-balance-for-currency") {
+        expect(r).eq({})
+        return;
+      }
       expect(r.balance).undefined;
       expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should not be able to pay if there is no enough balance", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerPayUri: "taller://pay",
+      cancel: nullFunction,
+      goToWalletManualWithdraw: nullFunction,
+      onSuccess: async () => {
+        null;
+      },
+    }
+    handler.addWalletCallResponse(WalletApiOperation.PreparePayForUri, 
undefined, {
+      status: PreparePayResultType.InsufficientBalance,
+      amountRaw: "USD:10",
+    } as PreparePayResultInsufficientBalance)
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, {}, {
+      balances: [{
+        available: "USD:5",
+        hasPendingTransactions: false,
+        pendingIncoming: "USD:0",
+        pendingOutgoing: "USD:0",
+        requiresUserInput: false,
+      }]
+    })
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
-        useComponentState(
-          {
-            talerPayUri: "taller://pay",
-            cancel: nullFunction,
-            goToWalletManualWithdraw: nullFunction,
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            onUpdateNotification: nullFunction,
-            preparePay: async () =>
-              ({
-                amountRaw: "USD:10",
-                status: PreparePayResultType.InsufficientBalance,
-              } as Partial<PreparePayResult>),
-            getBalance: async () =>
-              ({
-                balances: [
-                  {
-                    available: "USD:5",
-                  },
-                ],
-              } as Partial<BalancesResponse>),
-          } as Partial<typeof wxApi> as any,
-        ),
+        useComponentState(props, mock),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "no-enough-balance") expect.fail();
       expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:5"));
       expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should be able to pay (without fee)", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerPayUri: "taller://pay",
+      cancel: nullFunction,
+      goToWalletManualWithdraw: nullFunction,
+      onSuccess: async () => {
+        null;
+      },
+    }
+    handler.addWalletCallResponse(WalletApiOperation.PreparePayForUri, 
undefined, {
+      status: PreparePayResultType.PaymentPossible,
+      amountRaw: "USD:10",
+      amountEffective: "USD:10",
+    } as PreparePayResultPaymentPossible)
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, {}, {
+      balances: [{
+        available: "USD:15",
+        hasPendingTransactions: false,
+        pendingIncoming: "USD:0",
+        pendingOutgoing: "USD:0",
+        requiresUserInput: false,
+      }]
+    })
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
-        useComponentState(
-          {
-            talerPayUri: "taller://pay",
-            cancel: nullFunction,
-            goToWalletManualWithdraw: nullFunction,
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            onUpdateNotification: nullFunction,
-            preparePay: async () =>
-              ({
-                amountRaw: "USD:10",
-                amountEffective: "USD:10",
-                status: PreparePayResultType.PaymentPossible,
-              } as Partial<PreparePayResult>),
-            getBalance: async () =>
-              ({
-                balances: [
-                  {
-                    available: "USD:15",
-                  },
-                ],
-              } as Partial<BalancesResponse>),
-          } as Partial<typeof wxApi> as any,
-        ),
+        useComponentState(props, mock),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
+      const r = pullLastResultOrThrow();
+      if (r.status !== "ready") {
+        expect(r).eq({})
+        return
+      }
       expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
       expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:10"));
-      // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:0"));
       expect(r.payHandler.onClick).not.undefined;
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should be able to pay (with fee)", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerPayUri: "taller://pay",
+      cancel: nullFunction,
+      goToWalletManualWithdraw: nullFunction,
+      onSuccess: async () => {
+        null;
+      },
+    }
+    handler.addWalletCallResponse(WalletApiOperation.PreparePayForUri, 
undefined, {
+      status: PreparePayResultType.PaymentPossible,
+      amountRaw: "USD:9",
+      amountEffective: "USD:10",
+    } as PreparePayResultPaymentPossible)
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, {}, {
+      balances: [{
+        available: "USD:15",
+        hasPendingTransactions: false,
+        pendingIncoming: "USD:0",
+        pendingOutgoing: "USD:0",
+        requiresUserInput: false,
+      }]
+    })
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
-          {
-            talerPayUri: "taller://pay",
-            cancel: nullFunction,
-            goToWalletManualWithdraw: nullFunction,
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            onUpdateNotification: nullFunction,
-            preparePay: async () =>
-              ({
-                amountRaw: "USD:9",
-                amountEffective: "USD:10",
-                status: PreparePayResultType.PaymentPossible,
-              } as Partial<PreparePayResult>),
-            getBalance: async () =>
-              ({
-                balances: [
-                  {
-                    available: "USD:15",
-                  },
-                ],
-              } as Partial<BalancesResponse>),
-          } as Partial<typeof wxApi> as any,
+          props,
+          mock
+
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "ready") expect.fail();
       expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
       expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
-      // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
       expect(r.payHandler.onClick).not.undefined;
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should get confirmation done after pay successfully", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerPayUri: "taller://pay",
+      cancel: nullFunction,
+      goToWalletManualWithdraw: nullFunction,
+      onSuccess: async () => {
+        null;
+      },
+    }
+    handler.addWalletCallResponse(WalletApiOperation.PreparePayForUri, 
undefined, {
+      status: PreparePayResultType.PaymentPossible,
+      amountRaw: "USD:9",
+      amountEffective: "USD:10",
+    } as PreparePayResultPaymentPossible)
+
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, {}, {
+      balances: [{
+        available: "USD:15",
+        hasPendingTransactions: false,
+        pendingIncoming: "USD:0",
+        pendingOutgoing: "USD:0",
+        requiresUserInput: false,
+      }]
+    })
+    handler.addWalletCallResponse(WalletApiOperation.ConfirmPay, undefined, {
+      type: ConfirmPayResultType.Done,
+      contractTerms: {},
+    } as ConfirmPayResult)
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
-          {
-            talerPayUri: "taller://pay",
-            cancel: nullFunction,
-            goToWalletManualWithdraw: nullFunction,
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            onUpdateNotification: nullFunction,
-            preparePay: async () =>
-              ({
-                amountRaw: "USD:9",
-                amountEffective: "USD:10",
-                status: PreparePayResultType.PaymentPossible,
-              } as Partial<PreparePayResult>),
-            getBalance: async () =>
-              ({
-                balances: [
-                  {
-                    available: "USD:15",
-                  },
-                ],
-              } as Partial<BalancesResponse>),
-            confirmPay: async () =>
-              ({
-                type: ConfirmPayResultType.Done,
-                contractTerms: {},
-              } as Partial<ConfirmPayResult>),
-          } as Partial<typeof wxApi> as any,
+          props, mock
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
+      const r = pullLastResultOrThrow();
+      if (r.status !== "ready") {
+        expect(r).eq({})
+        return;
+      }
       expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
       expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
-      // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
       if (r.payHandler.onClick === undefined) expect.fail();
       r.payHandler.onClick();
     }
 
-    // await waitNextUpdate();
-
-    // {
-    //   const r = getLastResultOrThrow();
-    //   if (r.status !== "completed") expect.fail();
-    //   expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
-    //   expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
-    //   // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
-    //   // if (r.payResult.type !== ConfirmPayResultType.Done) expect.fail();
-    //   // expect(r.payResult.contractTerms).not.undefined;
-    //   // expect(r.payHandler.onClick).undefined;
-    // }
-
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should not stay in ready state after pay with error", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerPayUri: "taller://pay",
+      cancel: nullFunction,
+      goToWalletManualWithdraw: nullFunction,
+      onSuccess: nullFunction,
+    };
+    handler.addWalletCallResponse(WalletApiOperation.PreparePayForUri, 
undefined, {
+      status: PreparePayResultType.PaymentPossible,
+      amountRaw: "USD:9",
+      amountEffective: "USD:10",
+    } as PreparePayResultPaymentPossible)
+
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, {}, {
+      balances: [{
+        available: "USD:15",
+        hasPendingTransactions: false,
+        pendingIncoming: "USD:0",
+        pendingOutgoing: "USD:0",
+        requiresUserInput: false,
+      }]
+    })
+    handler.addWalletCallResponse(WalletApiOperation.ConfirmPay, undefined, {
+      type: ConfirmPayResultType.Pending,
+      lastError: { code: 1 },
+    } as ConfirmPayResult)
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
-          {
-            talerPayUri: "taller://pay",
-            cancel: nullFunction,
-            goToWalletManualWithdraw: nullFunction,
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            onUpdateNotification: nullFunction,
-            preparePay: async () =>
-              ({
-                amountRaw: "USD:9",
-                amountEffective: "USD:10",
-                status: PreparePayResultType.PaymentPossible,
-              } as Partial<PreparePayResult>),
-            getBalance: async () =>
-              ({
-                balances: [
-                  {
-                    available: "USD:15",
-                  },
-                ],
-              } as Partial<BalancesResponse>),
-            confirmPay: async () =>
-              ({
-                type: ConfirmPayResultType.Pending,
-                lastError: { code: 1 },
-              } as Partial<ConfirmPayResult>),
-          } as Partial<typeof wxApi> as any,
+          props, mock
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "ready") expect.fail();
       expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
       expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
@@ -429,10 +380,10 @@ describe("Payment CTA states", () => {
       r.payHandler.onClick();
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "ready") expect.fail();
       expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
       expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
@@ -450,72 +401,91 @@ describe("Payment CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should update balance if a coins is withdraw", async () => {
-    const subscriptions = new SubsHandler();
-    let availableBalance = Amounts.parseOrThrow("USD:10");
-
-    function notifyCoinWithdrawn(newAmount: AmountJson): void {
-      availableBalance = Amounts.add(availableBalance, newAmount).amount;
-      subscriptions.notifyEvent(NotificationType.CoinWithdrawn);
+    const { handler, mock } = createWalletApiMock();
+
+    const props = {
+      talerPayUri: "taller://pay",
+      cancel: nullFunction,
+      goToWalletManualWithdraw: nullFunction,
+      onSuccess: async () => {
+        null;
+      },
     }
 
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    handler.addWalletCallResponse(WalletApiOperation.PreparePayForUri, 
undefined, {
+      status: PreparePayResultType.PaymentPossible,
+      amountRaw: "USD:9",
+      amountEffective: "USD:10",
+    } as PreparePayResultPaymentPossible)
+
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, {}, {
+      balances: [{
+        available: "USD:10",
+        hasPendingTransactions: false,
+        pendingIncoming: "USD:0",
+        pendingOutgoing: "USD:0",
+        requiresUserInput: false,
+      }]
+    })
+
+    handler.addWalletCallResponse(WalletApiOperation.PreparePayForUri, 
undefined, {
+      status: PreparePayResultType.PaymentPossible,
+      amountRaw: "USD:9",
+      amountEffective: "USD:10",
+    } as PreparePayResultPaymentPossible)
+
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, {}, {
+      balances: [{
+        available: "USD:15",
+        hasPendingTransactions: false,
+        pendingIncoming: "USD:0",
+        pendingOutgoing: "USD:0",
+        requiresUserInput: false,
+      }]
+    })
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
-          {
-            talerPayUri: "taller://pay",
-            cancel: nullFunction,
-            goToWalletManualWithdraw: nullFunction,
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            onUpdateNotification: subscriptions.saveSubscription,
-            preparePay: async () =>
-              ({
-                amountRaw: "USD:9",
-                amountEffective: "USD:10",
-                status: PreparePayResultType.PaymentPossible,
-              } as Partial<PreparePayResult>),
-            getBalance: async () =>
-              ({
-                balances: [
-                  {
-                    available: Amounts.stringify(availableBalance),
-                  },
-                ],
-              } as Partial<BalancesResponse>),
-          } as Partial<typeof wxApi> as any,
+          props, mock
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
+      const r = pullLastResultOrThrow();
+      if (r.status !== "ready") {
+        expect(r).eq({})
+        return
+      }
       expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:10"));
       expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
       // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
       expect(r.payHandler.onClick).not.undefined;
 
-      notifyCoinWithdrawn(Amounts.parseOrThrow("USD:5"));
+      handler.notifyEventFromWallet(NotificationType.CoinWithdrawn);
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
+      const r = pullLastResultOrThrow();
+      if (r.status !== "ready") {
+        expect(r).eq({})
+        return
+      }
       expect(r.balance).deep.equal(Amounts.parseOrThrow("USD:15"));
       expect(r.amount).deep.equal(Amounts.parseOrThrow("USD:9"));
       // expect(r.totalFees).deep.equal(Amounts.parseOrThrow("USD:1"));
@@ -523,5 +493,6 @@ describe("Payment CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 });
diff --git a/packages/taler-wallet-webextension/src/cta/Recovery/index.ts 
b/packages/taler-wallet-webextension/src/cta/Recovery/index.ts
index 013e9c041..4a65c571b 100644
--- a/packages/taler-wallet-webextension/src/cta/Recovery/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Recovery/index.ts
@@ -14,12 +14,11 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { AmountJson } from "@gnu-taler/taler-util";
 import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { ButtonHandler } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
 import { LoadingUriView, ReadyView } from "./views.js";
 
diff --git a/packages/taler-wallet-webextension/src/cta/Recovery/state.ts 
b/packages/taler-wallet-webextension/src/cta/Recovery/state.ts
index 965a64e69..750fd22f7 100644
--- a/packages/taler-wallet-webextension/src/cta/Recovery/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Recovery/state.ts
@@ -16,8 +16,7 @@
 
 import { parseRecoveryUri } from "@gnu-taler/taler-util";
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import * as wxApi from "../../wxApi.js";
-import { wxClient } from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState(
@@ -49,7 +48,7 @@ export function useComponentState(
   const recovery = info;
 
   async function recoverBackup(): Promise<void> {
-    await wxClient.call(WalletApiOperation.ImportBackupRecovery, { recovery });
+    await wxApi.wallet.call(WalletApiOperation.ImportBackupRecovery, { 
recovery });
     onSuccess();
   }
 
diff --git a/packages/taler-wallet-webextension/src/cta/Refund/index.ts 
b/packages/taler-wallet-webextension/src/cta/Refund/index.ts
index be9e3499b..6bd976aab 100644
--- a/packages/taler-wallet-webextension/src/cta/Refund/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Refund/index.ts
@@ -19,13 +19,13 @@ import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { ButtonHandler } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
 import {
   IgnoredView,
   InProgressView,
   LoadingUriView,
-  ReadyView,
+  ReadyView
 } from "./views.js";
 
 export interface Props {
diff --git a/packages/taler-wallet-webextension/src/cta/Refund/state.ts 
b/packages/taler-wallet-webextension/src/cta/Refund/state.ts
index 16dbbf70d..65a895fc3 100644
--- a/packages/taler-wallet-webextension/src/cta/Refund/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Refund/state.ts
@@ -15,9 +15,10 @@
  */
 
 import { Amounts, NotificationType } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useEffect, useState } from "preact/hooks";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState(
@@ -28,15 +29,14 @@ export function useComponentState(
 
   const info = useAsyncAsHook(async () => {
     if (!talerRefundUri) throw Error("ERROR_NO-URI-FOR-REFUND");
-    const refund = await api.prepareRefund({ talerRefundUri });
+    const refund = await api.wallet.call(WalletApiOperation.PrepareRefund, { 
talerRefundUri });
     return { refund, uri: talerRefundUri };
   });
 
-  useEffect(() => {
-    api.onUpdateNotification([NotificationType.RefreshMelted], () => {
-      info?.retry();
-    });
-  });
+  useEffect(() => api.listener.onUpdateNotification(
+    [NotificationType.RefreshMelted],
+    info?.retry)
+  );
 
   if (!info) {
     return { status: "loading", error: undefined };
@@ -51,7 +51,9 @@ export function useComponentState(
   const { refund, uri } = info.response;
 
   const doAccept = async (): Promise<void> => {
-    const res = await api.applyRefund(uri);
+    const res = await api.wallet.call(WalletApiOperation.ApplyRefund, {
+      talerRefundUri: uri
+    });
 
     onSuccess(res.transactionId);
   };
diff --git a/packages/taler-wallet-webextension/src/cta/Refund/test.ts 
b/packages/taler-wallet-webextension/src/cta/Refund/test.ts
index 3111a85c6..41996c133 100644
--- a/packages/taler-wallet-webextension/src/cta/Refund/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Refund/test.ts
@@ -21,18 +21,19 @@
 
 import {
   AmountJson,
-  Amounts,
-  NotificationType,
-  PrepareRefundResult,
+  Amounts, NotificationType, OrderShortInfo, PrepareRefundResult
 } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { expect } from "chai";
 import { mountHook } from "../../test-utils.js";
-import { SubsHandler } from "../Payment/test.js";
+import { createWalletApiMock } from "../../test-utils.js";
 import { useComponentState } from "./state.js";
 
 describe("Refund CTA states", () => {
   it("should tell the user that the URI is missing", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
           {
@@ -44,24 +45,25 @@ describe("Refund CTA states", () => {
               null;
             },
           },
-          {
-            prepareRefund: async () => ({}),
-            applyRefund: async () => ({}),
-            onUpdateNotification: async () => ({}),
-          } as any,
+          mock
+          // {
+          //   prepareRefund: async () => ({}),
+          //   applyRefund: async () => ({}),
+          //   onUpdateNotification: async () => ({}),
+          // } as any,
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
 
       expect(status).equals("loading-uri");
       if (!error) expect.fail();
@@ -71,55 +73,76 @@ describe("Refund CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should be ready after loading", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerRefundUri: "taler://refund/asdasdas",
+      cancel: async () => {
+        null;
+      },
+      onSuccess: async () => {
+        null;
+      },
+    }
+
+    handler.addWalletCallResponse(WalletApiOperation.PrepareRefund, undefined, 
{
+      awaiting: "EUR:2",
+      effectivePaid: "EUR:2",
+      gone: "EUR:0",
+      granted: "EUR:0",
+      pending: false,
+      proposalId: "1",
+      info: {
+        contractTermsHash: "123",
+        merchant: {
+          name: "the merchant name",
+        },
+        orderId: "orderId1",
+        summary: "the summary",
+      } as OrderShortInfo,
+    })
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
-          {
-            talerRefundUri: "taler://refund/asdasdas",
-            cancel: async () => {
-              null;
-            },
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            prepareRefund: async () =>
-              ({
-                effectivePaid: "EUR:2",
-                awaiting: "EUR:2",
-                gone: "EUR:0",
-                granted: "EUR:0",
-                pending: false,
-                proposalId: "1",
-                info: {
-                  contractTermsHash: "123",
-                  merchant: {
-                    name: "the merchant name",
-                  },
-                  orderId: "orderId1",
-                  summary: "the summary",
-                },
-              } as PrepareRefundResult as any),
-            applyRefund: async () => ({}),
-            onUpdateNotification: async () => ({}),
-          } as any,
+          props, mock
+          //   {
+          //     prepareRefund: async () =>
+          //     ({
+          //       effectivePaid: "EUR:2",
+          //       awaiting: "EUR:2",
+          //       gone: "EUR:0",
+          //       granted: "EUR:0",
+          //       pending: false,
+          //       proposalId: "1",
+          //       info: {
+          //         contractTermsHash: "123",
+          //         merchant: {
+          //           name: "the merchant name",
+          //         },
+          //         orderId: "orderId1",
+          //         summary: "the summary",
+          //       },
+          //     } as PrepareRefundResult as any),
+          //     applyRefund: async () => ({}),
+          //     onUpdateNotification: async () => ({}),
+          //   } as any,
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
 
       if (state.status !== "ready") expect.fail();
       if (state.error) expect.fail();
@@ -131,58 +154,101 @@ describe("Refund CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should be ignored after clicking the ignore button", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerRefundUri: "taler://refund/asdasdas",
+      cancel: async () => {
+        null;
+      },
+      onSuccess: async () => {
+        null;
+      },
+    }
+
+    handler.addWalletCallResponse(WalletApiOperation.PrepareRefund, undefined, 
{
+      awaiting: "EUR:2",
+      effectivePaid: "EUR:2",
+      gone: "EUR:0",
+      granted: "EUR:0",
+      pending: false,
+      proposalId: "1",
+      info: {
+        contractTermsHash: "123",
+        merchant: {
+          name: "the merchant name",
+        },
+        orderId: "orderId1",
+        summary: "the summary",
+      } as OrderShortInfo,
+    })
+    // handler.addWalletCall(WalletApiOperation.ApplyRefund)
+    // handler.addWalletCall(WalletApiOperation.PrepareRefund, undefined, {
+    //   awaiting: "EUR:1",
+    //   effectivePaid: "EUR:2",
+    //   gone: "EUR:0",
+    //   granted: "EUR:1",
+    //   pending: true,
+    //   proposalId: "1",
+    //   info: {
+    //     contractTermsHash: "123",
+    //     merchant: {
+    //       name: "the merchant name",
+    //     },
+    //     orderId: "orderId1",
+    //     summary: "the summary",
+    //   } as OrderShortInfo,
+    // })
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
-          {
-            talerRefundUri: "taler://refund/asdasdas",
-            cancel: async () => {
-              null;
-            },
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            prepareRefund: async () =>
-              ({
-                effectivePaid: "EUR:2",
-                awaiting: "EUR:2",
-                gone: "EUR:0",
-                granted: "EUR:0",
-                pending: false,
-                proposalId: "1",
-                info: {
-                  contractTermsHash: "123",
-                  merchant: {
-                    name: "the merchant name",
-                  },
-                  orderId: "orderId1",
-                  summary: "the summary",
-                },
-              } as PrepareRefundResult as any),
-            applyRefund: async () => ({}),
-            onUpdateNotification: async () => ({}),
-          } as any,
+          props, mock
+          // {
+          //   prepareRefund: async () =>
+          //   ({
+          //     effectivePaid: "EUR:2",
+          //     awaiting: "EUR:2",
+          //     gone: "EUR:0",
+          //     granted: "EUR:0",
+          //     pending: false,
+          //     proposalId: "1",
+          //     info: {
+          //       contractTermsHash: "123",
+          //       merchant: {
+          //         name: "the merchant name",
+          //       },
+          //       orderId: "orderId1",
+          //       summary: "the summary",
+          //     },
+          //   } as PrepareRefundResult as any),
+          //   applyRefund: async () => ({}),
+          //   onUpdateNotification: async () => ({}),
+          // } as any,
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
-
-      if (state.status !== "ready") expect.fail();
-      if (state.error) expect.fail();
+      const state = pullLastResultOrThrow();
+
+      if (state.status !== "ready") {
+        expect(state).eq({})
+        return;
+      }
+      if (state.error) {
+        expect(state).eq({})
+        return;
+      }
       expect(state.accept.onClick).not.undefined;
       expect(state.merchantName).eq("the merchant name");
       expect(state.orderId).eq("orderId1");
@@ -192,113 +258,145 @@ describe("Refund CTA states", () => {
       state.ignore.onClick();
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
-
-      if (state.status !== "ignored") expect.fail();
-      if (state.error) expect.fail();
+      const state = pullLastResultOrThrow();
+
+      if (state.status !== "ignored") {
+        expect(state).eq({})
+        return;
+      }
+      if (state.error) {
+        expect(state).eq({})
+        return;
+      }
       expect(state.merchantName).eq("the merchant name");
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should be in progress when doing refresh", async () => {
-    let granted = Amounts.getZero("EUR");
-    const unit: AmountJson = { currency: "EUR", value: 1, fraction: 0 };
-    const refunded: AmountJson = { currency: "EUR", value: 2, fraction: 0 };
-    let awaiting: AmountJson = refunded;
-    let pending = true;
-
-    const subscriptions = new SubsHandler();
-
-    function notifyMelt(): void {
-      granted = Amounts.add(granted, unit).amount;
-      pending = granted.value < refunded.value;
-      awaiting = Amounts.sub(refunded, granted).amount;
-      subscriptions.notifyEvent(NotificationType.RefreshMelted);
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerRefundUri: "taler://refund/asdasdas",
+      cancel: async () => {
+        null;
+      },
+      onSuccess: async () => {
+        null;
+      },
     }
 
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    handler.addWalletCallResponse(WalletApiOperation.PrepareRefund, undefined, 
{
+      awaiting: "EUR:2",
+      effectivePaid: "EUR:2",
+      gone: "EUR:0",
+      granted: "EUR:0",
+      pending: true,
+      proposalId: "1",
+      info: {
+        contractTermsHash: "123",
+        merchant: {
+          name: "the merchant name",
+        },
+        orderId: "orderId1",
+        summary: "the summary",
+      } as OrderShortInfo,
+    })
+    handler.addWalletCallResponse(WalletApiOperation.PrepareRefund, undefined, 
{
+      awaiting: "EUR:1",
+      effectivePaid: "EUR:2",
+      gone: "EUR:0",
+      granted: "EUR:1",
+      pending: true,
+      proposalId: "1",
+      info: {
+        contractTermsHash: "123",
+        merchant: {
+          name: "the merchant name",
+        },
+        orderId: "orderId1",
+        summary: "the summary",
+      } as OrderShortInfo,
+    })
+    handler.addWalletCallResponse(WalletApiOperation.PrepareRefund, undefined, 
{
+      awaiting: "EUR:0",
+      effectivePaid: "EUR:2",
+      gone: "EUR:0",
+      granted: "EUR:2",
+      pending: false,
+      proposalId: "1",
+      info: {
+        contractTermsHash: "123",
+        merchant: {
+          name: "the merchant name",
+        },
+        orderId: "orderId1",
+        summary: "the summary",
+      } as OrderShortInfo,
+    })
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
-          {
-            talerRefundUri: "taler://refund/asdasdas",
-            cancel: async () => {
-              null;
-            },
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            prepareRefund: async () =>
-              ({
-                awaiting: Amounts.stringify(awaiting),
-                effectivePaid: "EUR:2",
-                gone: "EUR:0",
-                granted: Amounts.stringify(granted),
-                pending,
-                proposalId: "1",
-                info: {
-                  contractTermsHash: "123",
-                  merchant: {
-                    name: "the merchant name",
-                  },
-                  orderId: "orderId1",
-                  summary: "the summary",
-                },
-              } as PrepareRefundResult as any),
-            applyRefund: async () => ({}),
-            onUpdateNotification: subscriptions.saveSubscription,
-          } as any,
+          props, mock
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
 
-      if (state.status !== "in-progress") expect.fail("1");
+      if (state.status !== "in-progress") {
+        expect(state).eq({})
+        return;
+      }
       if (state.error) expect.fail();
       expect(state.merchantName).eq("the merchant name");
       expect(state.products).undefined;
       expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
       // expect(state.progress).closeTo(1 / 3, 0.01)
 
-      notifyMelt();
+      handler.notifyEventFromWallet(NotificationType.RefreshMelted)
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
 
-      if (state.status !== "in-progress") expect.fail("2");
+      if (state.status !== "in-progress") {
+        expect(state).eq({})
+        return;
+      }
       if (state.error) expect.fail();
       expect(state.merchantName).eq("the merchant name");
       expect(state.products).undefined;
       expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:2"));
       // expect(state.progress).closeTo(2 / 3, 0.01)
 
-      notifyMelt();
+      handler.notifyEventFromWallet(NotificationType.RefreshMelted)
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
 
-      if (state.status !== "ready") expect.fail("3");
+      if (state.status !== "ready") {
+        expect(state).eq({})
+        return;
+      }
       if (state.error) expect.fail();
       expect(state.merchantName).eq("the merchant name");
       expect(state.products).undefined;
@@ -306,5 +404,6 @@ describe("Refund CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 });
diff --git a/packages/taler-wallet-webextension/src/cta/Tip/index.ts 
b/packages/taler-wallet-webextension/src/cta/Tip/index.ts
index 03cbd2196..520d854f2 100644
--- a/packages/taler-wallet-webextension/src/cta/Tip/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Tip/index.ts
@@ -19,13 +19,13 @@ import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { ButtonHandler } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
 import {
   AcceptedView,
   IgnoredView,
   LoadingUriView,
-  ReadyView,
+  ReadyView
 } from "./views.js";
 
 export interface Props {
diff --git a/packages/taler-wallet-webextension/src/cta/Tip/state.ts 
b/packages/taler-wallet-webextension/src/cta/Tip/state.ts
index f6721d504..00e1fddad 100644
--- a/packages/taler-wallet-webextension/src/cta/Tip/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Tip/state.ts
@@ -15,20 +15,18 @@
  */
 
 import { Amounts } from "@gnu-taler/taler-util";
-import { useState } from "preact/hooks";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState(
   { talerTipUri, onCancel, onSuccess }: Props,
   api: typeof wxApi,
 ): State {
-  const [tipIgnored, setTipIgnored] = useState(false);
-
   const tipInfo = useAsyncAsHook(async () => {
     if (!talerTipUri) throw Error("ERROR_NO-URI-FOR-TIP");
-    const tip = await api.prepareTip({ talerTipUri });
+    const tip = await api.wallet.call(WalletApiOperation.PrepareTip, { 
talerTipUri });
     return { tip };
   });
 
@@ -48,7 +46,7 @@ export function useComponentState(
   const { tip } = tipInfo.response;
 
   const doAccept = async (): Promise<void> => {
-    const res = await api.acceptTip({ walletTipId: tip.walletTipId });
+    const res = await api.wallet.call(WalletApiOperation.AcceptTip, { 
walletTipId: tip.walletTipId });
 
     //FIX: this may not be seen since we are moving to the success also
     tipInfo.retry();
@@ -65,13 +63,6 @@ export function useComponentState(
     },
   };
 
-  if (tipIgnored) {
-    return {
-      status: "ignored",
-      ...baseInfo,
-    };
-  }
-
   if (tip.accepted) {
     return {
       status: "accepted",
diff --git a/packages/taler-wallet-webextension/src/cta/Tip/test.ts 
b/packages/taler-wallet-webextension/src/cta/Tip/test.ts
index 47d9aa8db..69badbede 100644
--- a/packages/taler-wallet-webextension/src/cta/Tip/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Tip/test.ts
@@ -19,14 +19,18 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { Amounts, PrepareTipResult } from "@gnu-taler/taler-util";
+import { Amounts } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { expect } from "chai";
 import { mountHook } from "../../test-utils.js";
+import { createWalletApiMock } from "../../test-utils.js";
 import { useComponentState } from "./state.js";
 
 describe("Tip CTA states", () => {
   it("should tell the user that the URI is missing", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
           {
@@ -38,23 +42,20 @@ describe("Tip CTA states", () => {
               null;
             },
           },
-          {
-            prepareTip: async () => ({}),
-            acceptTip: async () => ({}),
-          } as any,
+          mock,
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
 
       expect(status).equals("loading-uri");
       if (!error) expect.fail();
@@ -64,12 +65,26 @@ describe("Tip CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should be ready for accepting the tip", async () => {
-    let tipAccepted = false;
 
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+
+    handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
+      accepted: false,
+      exchangeBaseUrl: "exchange url",
+      merchantBaseUrl: "merchant url",
+      tipAmountEffective: "EUR:1",
+      walletTipId: "tip_id",
+      expirationTimestamp: {
+        t_s: 1
+      },
+      tipAmountRaw: ""
+    });
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
           {
@@ -81,58 +96,79 @@ describe("Tip CTA states", () => {
               null;
             },
           },
-          {
-            prepareTip: async () =>
-              ({
-                accepted: tipAccepted,
-                exchangeBaseUrl: "exchange url",
-                merchantBaseUrl: "merchant url",
-                tipAmountEffective: "EUR:1",
-                walletTipId: "tip_id",
-              } as PrepareTipResult as any),
-            acceptTip: async () => {
-              tipAccepted = true;
-            },
-          } as any,
+          mock,
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
 
-      if (state.status !== "ready") expect.fail();
+      if (state.status !== "ready") {
+        expect(state).eq({ status: "ready" })
+        return;
+      }
       if (state.error) expect.fail();
       expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
       expect(state.merchantBaseUrl).eq("merchant url");
       expect(state.exchangeBaseUrl).eq("exchange url");
       if (state.accept.onClick === undefined) expect.fail();
 
+      handler.addWalletCallResponse(WalletApiOperation.AcceptTip);
       state.accept.onClick();
     }
 
-    await waitNextUpdate();
+    handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
+      accepted: true,
+      exchangeBaseUrl: "exchange url",
+      merchantBaseUrl: "merchant url",
+      tipAmountEffective: "EUR:1",
+      walletTipId: "tip_id",
+      expirationTimestamp: {
+        t_s: 1
+      },
+      tipAmountRaw: ""
+    });
+    expect(await waitForStateUpdate()).true;
+
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
 
-      if (state.status !== "accepted") expect.fail();
+      if (state.status !== "accepted") {
+        expect(state).eq({ status: "accepted" })
+        return;
+      }
       if (state.error) expect.fail();
       expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
       expect(state.merchantBaseUrl).eq("merchant url");
       expect(state.exchangeBaseUrl).eq("exchange url");
     }
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should be ignored after clicking the ignore button", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
+      exchangeBaseUrl: "exchange url",
+      merchantBaseUrl: "merchant url",
+      tipAmountEffective: "EUR:1",
+      walletTipId: "tip_id",
+      accepted: false,
+      expirationTimestamp: {
+        t_s: 1,
+      },
+      tipAmountRaw: ""
+    });
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
           {
@@ -144,52 +180,48 @@ describe("Tip CTA states", () => {
               null;
             },
           },
-          {
-            prepareTip: async () =>
-              ({
-                exchangeBaseUrl: "exchange url",
-                merchantBaseUrl: "merchant url",
-                tipAmountEffective: "EUR:1",
-                walletTipId: "tip_id",
-              } as PrepareTipResult as any),
-            acceptTip: async () => ({}),
-          } as any,
+          mock,
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
 
       if (state.status !== "ready") expect.fail();
       if (state.error) expect.fail();
       expect(state.amount).deep.eq(Amounts.parseOrThrow("EUR:1"));
       expect(state.merchantBaseUrl).eq("merchant url");
       expect(state.exchangeBaseUrl).eq("exchange url");
-      // if (state.ignore.onClick === undefined) expect.fail();
-
-      // state.ignore.onClick();
     }
 
-    // await waitNextUpdate();
-    // {
-    //   const state = getLastResultOrThrow();
-
-    //   if (state.status !== "ignored") expect.fail();
-    //   if (state.error) expect.fail();
-    // }
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should render accepted if the tip has been used previously", async () => 
{
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+
+    handler.addWalletCallResponse(WalletApiOperation.PrepareTip, undefined, {
+      accepted: true,
+      exchangeBaseUrl: "exchange url",
+      merchantBaseUrl: "merchant url",
+      tipAmountEffective: "EUR:1",
+      walletTipId: "tip_id",
+      expirationTimestamp: {
+        t_s: 1,
+      },
+      tipAmountRaw: "",
+    });
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
           {
@@ -201,30 +233,20 @@ describe("Tip CTA states", () => {
               null;
             },
           },
-          {
-            prepareTip: async () =>
-              ({
-                accepted: true,
-                exchangeBaseUrl: "exchange url",
-                merchantBaseUrl: "merchant url",
-                tipAmountEffective: "EUR:1",
-                walletTipId: "tip_id",
-              } as PrepareTipResult as any),
-            acceptTip: async () => ({}),
-          } as any,
+          mock,
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
 
       if (state.status !== "accepted") expect.fail();
       if (state.error) expect.fail();
@@ -233,5 +255,6 @@ describe("Tip CTA states", () => {
       expect(state.exchangeBaseUrl).eq("exchange url");
     }
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 });
diff --git a/packages/taler-wallet-webextension/src/cta/TransferCreate/index.ts 
b/packages/taler-wallet-webextension/src/cta/TransferCreate/index.ts
index 820bffdea..83293438f 100644
--- a/packages/taler-wallet-webextension/src/cta/TransferCreate/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/TransferCreate/index.ts
@@ -19,7 +19,7 @@ import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { ButtonHandler, TextFieldHandler } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
 import { LoadingUriView, ReadyView } from "./views.js";
 
diff --git a/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts 
b/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts
index d4ba18c12..b229924b2 100644
--- a/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts
@@ -15,9 +15,9 @@
  */
 
 import { Amounts, TalerErrorDetail } from "@gnu-taler/taler-util";
-import { TalerError } from "@gnu-taler/taler-wallet-core";
+import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useState } from "preact/hooks";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState(
@@ -33,7 +33,7 @@ export function useComponentState(
 
   async function accept(): Promise<void> {
     try {
-      const resp = await api.initiatePeerPushPayment({
+      const resp = await 
api.wallet.call(WalletApiOperation.InitiatePeerPushPayment, {
         amount: Amounts.stringify(amount),
         partialContractTerms: {
           summary: subject,
diff --git a/packages/taler-wallet-webextension/src/cta/TransferPickup/index.ts 
b/packages/taler-wallet-webextension/src/cta/TransferPickup/index.ts
index 0ffdb1b95..954243fe8 100644
--- a/packages/taler-wallet-webextension/src/cta/TransferPickup/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/TransferPickup/index.ts
@@ -17,13 +17,13 @@
 import {
   AbsoluteTime,
   AmountJson,
-  TalerErrorDetail,
+  TalerErrorDetail
 } from "@gnu-taler/taler-util";
 import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { ButtonHandler } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
 import { LoadingUriView, ReadyView } from "./views.js";
 
diff --git a/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts 
b/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts
index 0095910b5..4b860559e 100644
--- a/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/TransferPickup/state.ts
@@ -18,12 +18,12 @@ import {
   AbsoluteTime,
   Amounts,
   TalerErrorDetail,
-  TalerProtocolTimestamp,
+  TalerProtocolTimestamp
 } from "@gnu-taler/taler-util";
-import { TalerError } from "@gnu-taler/taler-wallet-core";
+import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useState } from "preact/hooks";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState(
@@ -31,7 +31,7 @@ export function useComponentState(
   api: typeof wxApi,
 ): State {
   const hook = useAsyncAsHook(async () => {
-    return await api.checkPeerPushPayment({
+    return await api.wallet.call(WalletApiOperation.CheckPeerPushPayment, {
       talerUri: talerPayPushUri,
     });
   }, []);
@@ -53,7 +53,6 @@ export function useComponentState(
   }
 
   const {
-    amount: purseAmount,
     contractTerms,
     peerPushPaymentIncomingId,
   } = hook.response;
@@ -65,7 +64,7 @@ export function useComponentState(
 
   async function accept(): Promise<void> {
     try {
-      const resp = await api.acceptPeerPushPayment({
+      const resp = await 
api.wallet.call(WalletApiOperation.AcceptPeerPushPayment, {
         peerPushPaymentIncomingId,
       });
       onSuccess(resp.transactionId);
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts 
b/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts
index a3b3df8b3..9a7acf9f1 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts
@@ -20,15 +20,15 @@ import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { State as SelectExchangeState } from 
"../../hooks/useSelectedExchange.js";
 import { ButtonHandler, SelectFieldHandler } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import {
   useComponentStateFromParams,
-  useComponentStateFromURI,
+  useComponentStateFromURI
 } from "./state.js";
 
 import { ExchangeSelectionPage } from 
"../../wallet/ExchangeSelection/index.js";
-import { LoadingInfoView, LoadingUriView, SuccessView } from "./views.js";
 import { NoExchangesView } from "../../wallet/ExchangeSelection/views.js";
+import { LoadingInfoView, LoadingUriView, SuccessView } from "./views.js";
 
 export interface PropsFromURI {
   talerWithdrawUri: string | undefined;
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts 
b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
index c542d8aae..704ef1ac3 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
@@ -19,13 +19,13 @@ import {
   AmountJson,
   Amounts,
   ExchangeListItem,
-  ExchangeTosStatus,
+  ExchangeTosStatus
 } from "@gnu-taler/taler-util";
-import { TalerError } from "@gnu-taler/taler-wallet-core";
+import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useState } from "preact/hooks";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
 import { useSelectedExchange } from "../../hooks/useSelectedExchange.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { PropsFromParams, PropsFromURI, State } from "./index.js";
 
 type RecursiveState<S extends object> = S | (() => RecursiveState<S>);
@@ -35,7 +35,7 @@ export function useComponentStateFromParams(
   api: typeof wxApi,
 ): RecursiveState<State> {
   const uriInfoHook = useAsyncAsHook(async () => {
-    const exchanges = await api.listExchanges();
+    const exchanges = await api.wallet.call(WalletApiOperation.ListExchanges, 
{});
     return { amount: Amounts.parseOrThrow(amount), exchanges };
   });
 
@@ -58,11 +58,11 @@ export function useComponentStateFromParams(
     transactionId: string;
     confirmTransferUrl: string | undefined;
   }> {
-    const res = await api.acceptManualWithdrawal(
-      exchange,
-      Amounts.stringify(chosenAmount),
-      ageRestricted,
-    );
+    const res = await 
api.wallet.call(WalletApiOperation.AcceptManualWithdrawal, {
+      exchangeBaseUrl: exchange,
+      amount: Amounts.stringify(chosenAmount),
+      restrictAge: ageRestricted,
+    });
     return {
       confirmTransferUrl: undefined,
       transactionId: res.transactionId,
@@ -93,16 +93,15 @@ export function useComponentStateFromURI(
   const uriInfoHook = useAsyncAsHook(async () => {
     if (!talerWithdrawUri) throw Error("ERROR_NO-URI-FOR-WITHDRAWAL");
 
-    const uriInfo = await api.getWithdrawalDetailsForUri({
+    const uriInfo = await 
api.wallet.call(WalletApiOperation.GetWithdrawalDetailsForUri, {
       talerWithdrawUri,
     });
-    const exchanges = await api.listExchanges();
     const { amount, defaultExchangeBaseUrl } = uriInfo;
     return {
       talerWithdrawUri,
       amount: Amounts.parseOrThrow(amount),
       thisExchange: defaultExchangeBaseUrl,
-      exchanges,
+      exchanges: uriInfo.possibleExchanges,
     };
   });
 
@@ -118,7 +117,7 @@ export function useComponentStateFromURI(
   const uri = uriInfoHook.response.talerWithdrawUri;
   const chosenAmount = uriInfoHook.response.amount;
   const defaultExchange = uriInfoHook.response.thisExchange;
-  const exchangeList = uriInfoHook.response.exchanges.exchanges;
+  const exchangeList = uriInfoHook.response.exchanges;
 
   async function doManagedWithdraw(
     exchange: string,
@@ -127,7 +126,11 @@ export function useComponentStateFromURI(
     transactionId: string;
     confirmTransferUrl: string | undefined;
   }> {
-    const res = await api.acceptWithdrawal(uri, exchange, ageRestricted);
+    const res = await 
api.wallet.call(WalletApiOperation.AcceptBankIntegratedWithdrawal, {
+      exchangeBaseUrl: exchange,
+      talerWithdrawUri: uri,
+      restrictAge: ageRestricted
+    });
     return {
       confirmTransferUrl: res.confirmTransferUrl,
       transactionId: res.transactionId,
@@ -186,7 +189,7 @@ function exchangeSelectionState(
      * about the withdrawal
      */
     const amountHook = useAsyncAsHook(async () => {
-      const info = await api.getWithdrawalDetailsForAmount({
+      const info = await 
api.wallet.call(WalletApiOperation.GetWithdrawalDetailsForAmount, {
         exchangeBaseUrl: currentExchange.exchangeBaseUrl,
         amount: Amounts.stringify(chosenAmount),
         restrictAge: ageRestricted,
@@ -261,10 +264,10 @@ function exchangeSelectionState(
     //TODO: calculate based on exchange info
     const ageRestriction = ageRestrictionEnabled
       ? {
-          list: ageRestrictionOptions,
-          value: String(ageRestricted),
-          onChange: async (v: string) => setAgeRestricted(parseInt(v, 10)),
-        }
+        list: ageRestrictionOptions,
+        value: String(ageRestricted),
+        onChange: async (v: string) => setAgeRestricted(parseInt(v, 10)),
+      }
       : undefined;
 
     return {
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts 
b/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts
index 977faa03a..b4ba32f8a 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw/test.ts
@@ -21,16 +21,12 @@
 
 import {
   Amounts,
-  ExchangeEntryStatus,
-  ExchangeFullDetails,
-  ExchangeListItem,
-  ExchangesListResponse,
-  ExchangeTosStatus,
-  GetExchangeTosResult,
-  ManualWithdrawalDetails,
+  ExchangeEntryStatus, ExchangeListItem, ExchangeTosStatus
 } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { expect } from "chai";
 import { mountHook } from "../../test-utils.js";
+import { createWalletApiMock } from "../../test-utils.js";
 import { useComponentStateFromURI } from "./state.js";
 
 const exchanges: ExchangeListItem[] = [
@@ -65,39 +61,32 @@ const exchanges: ExchangeListItem[] = [
 
 describe("Withdraw CTA states", () => {
   it("should tell the user that the URI is missing", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerWithdrawUri: undefined,
+      cancel: async () => {
+        null;
+      },
+      onSuccess: async () => {
+        null;
+      },
+    }
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentStateFromURI(
-          {
-            talerWithdrawUri: undefined,
-            cancel: async () => {
-              null;
-            },
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            listExchanges: async () => ({ exchanges }),
-            getWithdrawalDetailsForAmount: async ({
-              talerWithdrawUri,
-            }: any) => ({
-              amount: "ARS:2",
-              possibleExchanges: exchanges,
-            }),
-          } as any,
+          props, mock
         ),
       );
 
     {
-      const { status } = getLastResultOrThrow();
+      const { status } = pullLastResultOrThrow();
       expect(status).equals("loading");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
 
       if (status != "uri-error") expect.fail();
       if (!error) expect.fail();
@@ -107,40 +96,41 @@ describe("Withdraw CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should tell the user that there is not known exchange", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerWithdrawUri: "taler-withdraw://",
+      cancel: async () => {
+        null;
+      },
+      onSuccess: async () => {
+        null;
+      },
+    }
+    
handler.addWalletCallResponse(WalletApiOperation.GetWithdrawalDetailsForUri, 
undefined, {
+      amount: "EUR:2",
+      possibleExchanges: [],
+    })
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentStateFromURI(
-          {
-            talerWithdrawUri: "taler-withdraw://",
-            cancel: async () => {
-              null;
-            },
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            listExchanges: async () => ({ exchanges }),
-            getWithdrawalDetailsForUri: async ({ talerWithdrawUri }: any) => ({
-              amount: "EUR:2",
-              possibleExchanges: [],
-            }),
-          } as any,
+          props, mock
         ),
       );
 
     {
-      const { status } = getLastResultOrThrow();
+      const { status } = pullLastResultOrThrow();
       expect(status).equals("loading", "1");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
 
       expect(status).equals("no-exchange", "3");
 
@@ -148,65 +138,60 @@ describe("Withdraw CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
   it("should be able to withdraw if tos are ok", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerWithdrawUri: "taler-withdraw://",
+      cancel: async () => {
+        null;
+      },
+      onSuccess: async () => {
+        null;
+      },
+    }
+    
handler.addWalletCallResponse(WalletApiOperation.GetWithdrawalDetailsForUri, 
undefined, {
+      amount: "ARS:2",
+      possibleExchanges: exchanges,
+      defaultExchangeBaseUrl: exchanges[0].exchangeBaseUrl
+    })
+    
handler.addWalletCallResponse(WalletApiOperation.GetWithdrawalDetailsForAmount, 
undefined, {
+      amountRaw: "ARS:2",
+      amountEffective: "ARS:2",
+      paytoUris: ["payto://"],
+      tosAccepted: true,
+      ageRestrictionOptions: []
+    })
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentStateFromURI(
-          {
-            talerWithdrawUri: "taler-withdraw://",
-            cancel: async () => {
-              null;
-            },
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            listExchanges: async () => ({ exchanges }),
-            getWithdrawalDetailsForUri: async ({ talerWithdrawUri }: any) => ({
-              amount: "ARS:2",
-              possibleExchanges: exchanges,
-              defaultExchangeBaseUrl: exchanges[0].exchangeBaseUrl,
-            }),
-            getWithdrawalDetailsForAmount:
-              async (): Promise<ManualWithdrawalDetails> =>
-                ({
-                  amountRaw: "ARS:2",
-                  amountEffective: "ARS:2",
-                } as any),
-            getExchangeTos: async (): Promise<GetExchangeTosResult> => ({
-              contentType: "text",
-              content: "just accept",
-              acceptedEtag: "v1",
-              currentEtag: "v1",
-              tosStatus: ExchangeTosStatus.Accepted,
-            }),
-          } as any,
+          props, mock
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
 
       expect(status).equals("loading");
 
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
       expect(state.status).equals("success");
       if (state.status !== "success") return;
 
@@ -218,82 +203,72 @@ describe("Withdraw CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
-  it("should be accept the tos before withdraw", async () => {
-    const listExchangesResponse: ExchangesListResponse = {
-      exchanges: exchanges.map((e) => ({
-        ...e,
-        tosStatus: ExchangeTosStatus.New,
-      })),
-    };
-
-    function updateAcceptedVersionToCurrentVersion(): void {
-      listExchangesResponse.exchanges = listExchangesResponse.exchanges.map(
-        (e) => ({
-          ...e,
-          tosStatus: ExchangeTosStatus.Accepted,
-        }),
-      );
+  it("should accept the tos before withdraw", async () => {
+    const { handler, mock } = createWalletApiMock();
+    const props = {
+      talerWithdrawUri: "taler-withdraw://",
+      cancel: async () => {
+        null;
+      },
+      onSuccess: async () => {
+        null;
+      },
     }
-
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const exchangeWithNewTos = exchanges.map((e) => ({
+      ...e,
+      tosStatus: ExchangeTosStatus.New,
+    }));
+
+    
handler.addWalletCallResponse(WalletApiOperation.GetWithdrawalDetailsForUri, 
undefined, {
+      amount: "ARS:2",
+      possibleExchanges: exchangeWithNewTos,
+      defaultExchangeBaseUrl: exchangeWithNewTos[0].exchangeBaseUrl
+    })
+    
handler.addWalletCallResponse(WalletApiOperation.GetWithdrawalDetailsForAmount, 
undefined, {
+      amountRaw: "ARS:2",
+      amountEffective: "ARS:2",
+      paytoUris: ["payto://"],
+      tosAccepted: false,
+      ageRestrictionOptions: []
+    })
+
+
+    
handler.addWalletCallResponse(WalletApiOperation.GetWithdrawalDetailsForUri, 
undefined, {
+      amount: "ARS:2",
+      possibleExchanges: exchanges,
+      defaultExchangeBaseUrl: exchanges[0].exchangeBaseUrl
+    })
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentStateFromURI(
-          {
-            talerWithdrawUri: "taler-withdraw://",
-            cancel: async () => {
-              null;
-            },
-            onSuccess: async () => {
-              null;
-            },
-          },
-          {
-            listExchanges: async () => listExchangesResponse,
-            getWithdrawalDetailsForUri: async ({ talerWithdrawUri }: any) => ({
-              amount: "ARS:2",
-              possibleExchanges: exchanges,
-              defaultExchangeBaseUrl: exchanges[0].exchangeBaseUrl,
-            }),
-            getWithdrawalDetailsForAmount:
-              async (): Promise<ManualWithdrawalDetails> =>
-                ({
-                  amountRaw: "ARS:2",
-                  amountEffective: "ARS:2",
-                } as any),
-            getExchangeTos: async (): Promise<GetExchangeTosResult> => ({
-              contentType: "text",
-              content: "just accept",
-              acceptedEtag: "v1",
-              currentEtag: "v2",
-              tosStatus: ExchangeTosStatus.Changed,
-            }),
-            setExchangeTosAccepted: async () => ({}),
-          } as any,
+          props, mock
         ),
       );
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
       expect(status).equals("loading");
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { status, error } = getLastResultOrThrow();
+      const { status, error } = pullLastResultOrThrow();
 
       expect(status).equals("loading");
 
       expect(error).undefined;
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
       expect(state.status).equals("success");
       if (state.status !== "success") return;
 
@@ -303,14 +278,14 @@ describe("Withdraw CTA states", () => {
 
       expect(state.doWithdrawal.onClick).undefined;
 
-      updateAcceptedVersionToCurrentVersion();
+      // updateAcceptedVersionToCurrentVersion();
       state.onTosUpdate();
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const state = getLastResultOrThrow();
+      const state = pullLastResultOrThrow();
       expect(state.status).equals("success");
       if (state.status !== "success") return;
 
@@ -322,5 +297,6 @@ describe("Withdraw CTA states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 });
diff --git a/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts 
b/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts
index f24896bf3..1b2929317 100644
--- a/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts
@@ -13,10 +13,9 @@
  You should have received a copy of the GNU General Public License along with
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
-import { NotificationType, TalerErrorDetail } from "@gnu-taler/taler-util";
+import { TalerErrorDetail } from "@gnu-taler/taler-util";
 import { TalerError } from "@gnu-taler/taler-wallet-core";
 import { useEffect, useMemo, useState } from "preact/hooks";
-import * as wxApi from "../wxApi.js";
 
 export interface HookOk<T> {
   hasError: false;
diff --git 
a/packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts 
b/packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts
index 727d653af..5a0194db8 100644
--- a/packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts
@@ -14,11 +14,11 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { useState, useEffect } from "preact/hooks";
-import * as wxApi from "../wxApi.js";
-import { platform } from "../platform/api.js";
-import { ToggleHandler } from "../mui/handlers.js";
 import { TalerError } from "@gnu-taler/taler-wallet-core";
+import { useEffect, useState } from "preact/hooks";
+import { ToggleHandler } from "../mui/handlers.js";
+import { platform } from "../platform/api.js";
+import { wxApi } from "../wxApi.js";
 
 export function useAutoOpenPermissions(): ToggleHandler {
   const [enabled, setEnabled] = useState(false);
@@ -31,7 +31,7 @@ export function useAutoOpenPermissions(): ToggleHandler {
 
   useEffect(() => {
     async function getValue(): Promise<void> {
-      const res = await wxApi.containsHeaderListener();
+      const res = await wxApi.background.containsHeaderListener();
       setEnabled(res.newValue);
     }
     getValue();
@@ -59,11 +59,11 @@ async function handleAutoOpenPerm(
       onChange(false);
       throw lastError;
     }
-    const res = await wxApi.toggleHeaderListener(granted);
+    const res = await wxApi.background.toggleHeaderListener(granted);
     onChange(res.newValue);
   } else {
     try {
-      await wxApi.toggleHeaderListener(false).then((r) => 
onChange(r.newValue));
+      await wxApi.background.toggleHeaderListener(false).then((r) => 
onChange(r.newValue));
     } catch (e) {
       console.log(e);
     }
diff --git 
a/packages/taler-wallet-webextension/src/hooks/useBackupDeviceName.ts 
b/packages/taler-wallet-webextension/src/hooks/useBackupDeviceName.ts
index da3b05df4..7339a876a 100644
--- a/packages/taler-wallet-webextension/src/hooks/useBackupDeviceName.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useBackupDeviceName.ts
@@ -14,8 +14,9 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useEffect, useState } from "preact/hooks";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 
 export interface BackupDeviceName {
   name: string;
@@ -31,10 +32,10 @@ export function useBackupDeviceName(): BackupDeviceName {
   useEffect(() => {
     async function run(): Promise<void> {
       //create a first list of backup info by currency
-      const status = await wxApi.getBackupInfo();
+      const status = await wxApi.wallet.call(WalletApiOperation.GetBackupInfo, 
{});
 
       async function update(newName: string): Promise<void> {
-        await wxApi.setWalletDeviceId(newName);
+        await wxApi.wallet.call(WalletApiOperation.SetWalletDeviceId, { 
walletDeviceId: newName });
         setStatus((old) => ({ ...old, name: newName }));
       }
 
diff --git 
a/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts 
b/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts
index 3e9629dcb..3d284fb5a 100644
--- a/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts
@@ -14,11 +14,11 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { useState, useEffect } from "preact/hooks";
-import * as wxApi from "../wxApi.js";
-import { platform } from "../platform/api.js";
-import { ToggleHandler } from "../mui/handlers.js";
 import { TalerError } from "@gnu-taler/taler-wallet-core";
+import { useEffect, useState } from "preact/hooks";
+import { ToggleHandler } from "../mui/handlers.js";
+import { platform } from "../platform/api.js";
+import { wxApi } from "../wxApi.js";
 
 export function useClipboardPermissions(): ToggleHandler {
   const [enabled, setEnabled] = useState(false);
@@ -31,7 +31,7 @@ export function useClipboardPermissions(): ToggleHandler {
 
   useEffect(() => {
     async function getValue(): Promise<void> {
-      const res = await wxApi.containsHeaderListener();
+      const res = await wxApi.background.containsHeaderListener();
       setEnabled(res.newValue);
     }
     getValue();
@@ -66,7 +66,7 @@ async function handleClipboardPerm(
     onChange(granted);
   } else {
     try {
-      await wxApi.toggleHeaderListener(false).then((r) => 
onChange(r.newValue));
+      await wxApi.background.toggleHeaderListener(false).then((r) => 
onChange(r.newValue));
     } catch (e) {
       console.log(e);
     }
diff --git a/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts 
b/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts
index a61fe7965..a8564fddb 100644
--- a/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts
@@ -16,7 +16,7 @@
 
 import { WalletDiagnostics } from "@gnu-taler/taler-util";
 import { useEffect, useState } from "preact/hooks";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 
 export function useDiagnostics(): [WalletDiagnostics | undefined, boolean] {
   const [timedOut, setTimedOut] = useState(false);
@@ -33,7 +33,7 @@ export function useDiagnostics(): [WalletDiagnostics | 
undefined, boolean] {
       }
     }, 1000);
     const doFetch = async (): Promise<void> => {
-      const d = await wxApi.getDiagnostics();
+      const d = await wxApi.background.getDiagnostics();
       gotDiagnostics = true;
       setDiagnostics(d);
     };
diff --git a/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts 
b/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts
index 187517b41..b73c9fc16 100644
--- a/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts
@@ -14,9 +14,9 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { ProviderInfo } from "@gnu-taler/taler-wallet-core";
+import { ProviderInfo, WalletApiOperation } from 
"@gnu-taler/taler-wallet-core";
 import { useEffect, useState } from "preact/hooks";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 
 export interface ProviderStatus {
   info?: ProviderInfo;
@@ -30,7 +30,7 @@ export function useProviderStatus(url: string): 
ProviderStatus | undefined {
   useEffect(() => {
     async function run(): Promise<void> {
       //create a first list of backup info by currency
-      const status = await wxApi.getBackupInfo();
+      const status = await wxApi.wallet.call(WalletApiOperation.GetBackupInfo, 
{});
 
       const providers = status.providers.filter(
         (p) => p.syncProviderBaseUrl === url,
@@ -39,13 +39,17 @@ export function useProviderStatus(url: string): 
ProviderStatus | undefined {
 
       async function sync(): Promise<void> {
         if (info) {
-          await wxApi.syncOneProvider(info.syncProviderBaseUrl);
+          await wxApi.wallet.call(WalletApiOperation.RunBackupCycle, {
+            providers: [info.syncProviderBaseUrl]
+          });
         }
       }
 
       async function remove(): Promise<void> {
         if (info) {
-          await wxApi.removeProvider(info.syncProviderBaseUrl);
+          await wxApi.wallet.call(WalletApiOperation.RemoveBackupProvider, {
+            provider: info.syncProviderBaseUrl
+          });
         }
       }
 
diff --git 
a/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.test.ts 
b/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.test.ts
index a7ad3e81b..8aabb8adf 100644
--- a/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.test.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.test.ts
@@ -31,18 +31,18 @@ describe("useTalerActionURL hook", () => {
       });
     };
 
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(useTalerActionURL, ctx);
 
     {
-      const [url] = getLastResultOrThrow();
+      const [url] = pullLastResultOrThrow();
       expect(url).undefined;
     }
 
-    await waitNextUpdate("waiting for useEffect");
+    expect(await waitForStateUpdate()).true;
 
     {
-      const [url, setDismissed] = getLastResultOrThrow();
+      const [url, setDismissed] = pullLastResultOrThrow();
       expect(url).deep.equals({
         location: "clipboard",
         uri: "qwe",
@@ -50,10 +50,10 @@ describe("useTalerActionURL hook", () => {
       setDismissed(true);
     }
 
-    await waitNextUpdate("after dismiss");
+    expect(await waitForStateUpdate()).true;
 
     {
-      const [url] = getLastResultOrThrow();
+      const [url] = pullLastResultOrThrow();
       if (url !== undefined) throw Error("invalid");
       expect(url).undefined;
     }
diff --git a/packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts 
b/packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts
index 8021db686..8d4921392 100644
--- a/packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts
@@ -15,7 +15,7 @@
  */
 
 import { useState, useEffect } from "preact/hooks";
-import { wxClient } from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 import { ToggleHandler } from "../mui/handlers.js";
 import { TalerError, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 
@@ -30,7 +30,7 @@ export function useWalletDevMode(): ToggleHandler {
 
   useEffect(() => {
     async function getValue(): Promise<void> {
-      const res = await wxClient.call(WalletApiOperation.GetVersion, {});
+      const res = await wxApi.wallet.call(WalletApiOperation.GetVersion, {});
       setEnabled(res.devMode);
     }
     getValue();
@@ -49,7 +49,7 @@ async function handleOpen(
   onChange: (value: boolean) => void,
 ): Promise<void> {
   const nextValue = !currentValue
-  await wxClient.call(WalletApiOperation.SetDevMode, { devModeEnabled: 
nextValue });
+  await wxApi.wallet.call(WalletApiOperation.SetDevMode, { devModeEnabled: 
nextValue });
   onChange(nextValue);
   return;
 }
diff --git a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx 
b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
index 94d5d1e16..98c6d166c 100644
--- a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
@@ -15,6 +15,7 @@
  */
 
 import { Amounts, Balance, NotificationType } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { Fragment, h, VNode } from "preact";
 import { useEffect, useState } from "preact/hooks";
 import { BalanceTable } from "../components/BalanceTable.js";
@@ -27,7 +28,7 @@ import { Button } from "../mui/Button.js";
 import { ButtonHandler } from "../mui/handlers.js";
 import { compose, StateViewMap } from "../utils/index.js";
 import { AddNewActionView } from "../wallet/AddNewActionView.js";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 import { NoBalanceHelp } from "./NoBalanceHelp.js";
 
 export interface Props {
@@ -71,16 +72,16 @@ function useComponentState(
   api: typeof wxApi,
 ): State {
   const [addingAction, setAddingAction] = useState(false);
-  const state = useAsyncAsHook(api.getBalance);
+  const state = useAsyncAsHook(() =>
+    api.wallet.call(WalletApiOperation.GetBalances, {}),
+  );
 
-  useEffect(() => {
-    return api.onUpdateNotification(
+  useEffect(() =>
+    api.listener.onUpdateNotification(
       [NotificationType.WithdrawGroupFinished],
-      () => {
-        state?.retry();
-      },
-    );
-  });
+      state?.retry,
+    ),
+  );
 
   if (!state) {
     return {
diff --git a/packages/taler-wallet-webextension/src/test-utils.ts 
b/packages/taler-wallet-webextension/src/test-utils.ts
index e2339bff3..695fec201 100644
--- a/packages/taler-wallet-webextension/src/test-utils.ts
+++ b/packages/taler-wallet-webextension/src/test-utils.ts
@@ -14,6 +14,8 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
+import { NotificationType } from "@gnu-taler/taler-util";
+import { WalletCoreApiClient, WalletCoreOpKeys, WalletCoreRequestType, 
WalletCoreResponseType } from "@gnu-taler/taler-wallet-core";
 import {
   ComponentChildren,
   Fragment,
@@ -24,6 +26,7 @@ import {
   VNode,
 } from "preact";
 import { render as renderToString } from "preact-render-to-string";
+import { BackgroundApiClient, wxApi } from "./wxApi.js";
 
 // When doing tests we want the requestAnimationFrame to be as fast as 
possible.
 // without this option the RAF will timeout after 100ms making the tests slower
@@ -86,9 +89,10 @@ type RecursiveState<S> = S | (() => RecursiveState<S>);
 
 interface Mounted<T> {
   unmount: () => void;
-  getLastResultOrThrow: () => Exclude<T, VoidFunction>;
+  pullLastResultOrThrow: () => Exclude<T, VoidFunction>;
   assertNoPendingUpdate: () => void;
-  waitNextUpdate: (s?: string) => Promise<void>;
+  // waitNextUpdate: (s?: string) => Promise<void>;
+  waitForStateUpdate: () => Promise<boolean>;
 }
 
 const isNode = typeof window === "undefined";
@@ -97,9 +101,6 @@ export function mountHook<T extends object>(
   callback: () => RecursiveState<T>,
   Context?: ({ children }: { children: any }) => VNode,
 ): Mounted<T> {
-  // const result: { current: T | null } = {
-  //   current: null
-  // }
   let lastResult: Exclude<T, VoidFunction> | Error | null = null;
 
   const listener: Array<() => void> = [];
@@ -132,23 +133,6 @@ export function mountHook<T extends object>(
     ? create(Component, {})
     : create(Context, { children: [create(Component, {})] });
 
-  // waiter callback
-  async function waitNextUpdate(_label = ""): Promise<void> {
-    if (_label) _label = `. label: "${_label}"`;
-    await new Promise((res, rej) => {
-      const tid = setTimeout(() => {
-        rej(
-          Error(`waiting for an update but the hook didn't make one${_label}`),
-        );
-      }, 100);
-
-      listener.push(() => {
-        clearTimeout(tid);
-        res(undefined);
-      });
-    });
-  }
-
   const customElement = {} as Element;
   const parentElement = isNode ? customElement : document.createElement("div");
   if (!isNode) {
@@ -164,14 +148,14 @@ export function mountHook<T extends object>(
     }
   }
 
-  function getLastResult(): Exclude<T | Error | null, VoidFunction> {
+  function pullLastResult(): Exclude<T | Error | null, VoidFunction> {
     const copy: Exclude<T | Error | null, VoidFunction> = lastResult;
     lastResult = null;
     return copy;
   }
 
-  function getLastResultOrThrow(): Exclude<T, VoidFunction> {
-    const r = getLastResult();
+  function pullLastResultOrThrow(): Exclude<T, VoidFunction> {
+    const r = pullLastResult();
     if (r instanceof Error) throw r;
     if (!r) throw Error("there was no last result");
     return r;
@@ -194,15 +178,137 @@ export function mountHook<T extends object>(
       });
     });
 
-    const r = getLastResult();
+    const r = pullLastResult();
     if (r)
       throw Error(`There are still pending results.
-    This may happen because the hook did a new update but the test didn't 
consume the result using getLastResult`);
+    This may happen because the hook did a new update but the test didn't 
consume the result using pullLastResult`);
   }
+  async function waitForStateUpdate(): Promise<boolean> {
+    return await new Promise((res, rej) => {
+      const tid = setTimeout(() => {
+        res(false);
+      }, 10);
+
+      listener.push(() => {
+        clearTimeout(tid);
+        res(true);
+      });
+    });
+  }
+
   return {
     unmount,
-    getLastResultOrThrow,
-    waitNextUpdate,
+    pullLastResultOrThrow,
+    waitForStateUpdate,
     assertNoPendingUpdate,
   };
 }
+
+export const nullFunction: any = () => null;
+
+interface MockHandler {
+  addWalletCallResponse<Op extends WalletCoreOpKeys>(operation: Op,
+    payload?: Partial<WalletCoreRequestType<Op>>,
+    response?: WalletCoreResponseType<Op>,
+    callback?: () => void,
+  ): MockHandler;
+
+  getCallingQueueState(): "empty" | string;
+
+  notifyEventFromWallet(event: NotificationType): void;
+}
+
+type CallRecord = WalletCallRecord | BackgroundCallRecord;
+interface WalletCallRecord {
+  source: "wallet"
+  callback: () => void;
+  operation: WalletCoreOpKeys,
+  payload?: WalletCoreRequestType<WalletCoreOpKeys>,
+  response?: WalletCoreResponseType<WalletCoreOpKeys>,
+}
+interface BackgroundCallRecord {
+  source: "background"
+  name: string,
+  args: any,
+  response: any;
+}
+
+type Subscriptions = {
+  [key in NotificationType]?: VoidFunction;
+};
+
+export function createWalletApiMock(): { handler: MockHandler, mock: typeof 
wxApi } {
+  const calls = new Array<CallRecord>()
+  const subscriptions: Subscriptions = {};
+
+
+  const mock: typeof wxApi = {
+    wallet: new Proxy<WalletCoreApiClient>({} as any, {
+      get(target, name, receiver) {
+        const functionName = String(name)
+        if (functionName !== "call") {
+          throw Error(`the only method in wallet api should be 'call': 
${functionName}`)
+        }
+        return function (operation: WalletCoreOpKeys, payload: 
WalletCoreRequestType<WalletCoreOpKeys>) {
+          const next = calls.shift()
+
+          if (!next) {
+            throw Error(`wallet operation was called but none was expected: 
${operation} (${JSON.stringify(payload, undefined, 2)})`)
+          }
+          if (next.source !== "wallet") {
+            throw Error(`wallet operation expected`)
+          }
+          if (operation !== next.operation) {
+            //more checks, deep check payload
+            throw Error(`wallet operation doesn't match: expected 
${next.operation} actual ${operation}`)
+          }
+          next.callback()
+
+          return next.response ?? {}
+        }
+      }
+    }),
+    listener: {
+      onUpdateNotification(mTypes: NotificationType[], callback: (() => void) 
| undefined): (() => void) {
+        mTypes.forEach(m => {
+          subscriptions[m] = callback
+        })
+        return nullFunction
+      }
+    },
+    background: new Proxy<BackgroundApiClient>({} as any, {
+      get(target, name, receiver) {
+        const functionName = String(name);
+        return function (...args: any) {
+          const next = calls.shift()
+          if (!next) {
+            throw Error(`background operation was called but none was 
expected: ${functionName} (${JSON.stringify(args, undefined, 2)})`)
+          }
+          if (next.source !== "background" || functionName !== next.name) {
+            //more checks, deep check args
+            throw Error(`background operation doesn't match`)
+          }
+          return next.response
+        }
+      }
+    }),
+  }
+
+
+  const handler: MockHandler = {
+    addWalletCallResponse(operation, payload, response, cb) {
+      calls.push({ source: "wallet", operation, payload, response, callback: 
cb ? cb : () => { null } })
+      return handler
+    },
+    notifyEventFromWallet(event: NotificationType): void {
+      const callback = subscriptions[event]
+      if (!callback) throw Error(`Expected to have a subscription for 
${event}`);
+      return callback();
+    },
+    getCallingQueueState() {
+      return calls.length === 0 ? "empty" : `${calls.length} left`;
+    },
+  }
+
+  return { handler, mock }
+}
diff --git a/packages/taler-wallet-webextension/src/wallet/AddAccount/index.ts 
b/packages/taler-wallet-webextension/src/wallet/AddAccount/index.ts
index 0b50d9d85..09609a8a1 100644
--- a/packages/taler-wallet-webextension/src/wallet/AddAccount/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/AddAccount/index.ts
@@ -16,15 +16,15 @@
 
 import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
-import { compose, StateViewMap } from "../../utils/index.js";
-import { LoadingUriView, ReadyView } from "./views.js";
-import * as wxApi from "../../wxApi.js";
-import { useComponentState } from "./state.js";
 import {
   ButtonHandler,
   SelectFieldHandler,
-  TextFieldHandler,
+  TextFieldHandler
 } from "../../mui/handlers.js";
+import { compose, StateViewMap } from "../../utils/index.js";
+import { wxApi } from "../../wxApi.js";
+import { useComponentState } from "./state.js";
+import { LoadingUriView, ReadyView } from "./views.js";
 
 export interface Props {
   currency: string;
diff --git a/packages/taler-wallet-webextension/src/wallet/AddAccount/state.ts 
b/packages/taler-wallet-webextension/src/wallet/AddAccount/state.ts
index f14c4c1bb..a9e8dfb30 100644
--- a/packages/taler-wallet-webextension/src/wallet/AddAccount/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/AddAccount/state.ts
@@ -15,19 +15,17 @@
  */
 
 import { parsePaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useState } from "preact/hooks";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState(
   { currency, onAccountAdded, onCancel }: Props,
   api: typeof wxApi,
 ): State {
-  const hook = useAsyncAsHook(async () => {
-    const { accounts } = await api.listKnownBankAccounts(currency);
-    return { accounts };
-  });
+  const hook = useAsyncAsHook(() => 
api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency }));
 
   const [payto, setPayto] = useState("");
   const [alias, setAlias] = useState("");
@@ -61,7 +59,10 @@ export function useComponentState(
   async function addAccount(): Promise<void> {
     if (!uri || found) return;
 
-    await api.addKnownBankAccounts(uri, currency, alias);
+    const normalizedPayto = stringifyPaytoUri(uri);
+    await api.wallet.call(WalletApiOperation.AddKnownBankAccounts, {
+      alias, currency, payto: normalizedPayto
+    });
     onAccountAdded(payto);
   }
 
@@ -69,10 +70,10 @@ export function useComponentState(
     payto === ""
       ? undefined
       : !uri
-      ? "the uri is not ok"
-      : found
-      ? "that account is already present"
-      : undefined;
+        ? "the uri is not ok"
+        : found
+          ? "that account is already present"
+          : undefined;
 
   const unableToAdd = !type || !alias || paytoUriError;
 
diff --git a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
index bba8b5964..c9dbfb64d 100644
--- a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
@@ -14,11 +14,7 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import {
-  AbsoluteTime,
-  BackupRecovery,
-  constructRecoveryUri,
-} from "@gnu-taler/taler-util";
+import { AbsoluteTime, constructRecoveryUri } from "@gnu-taler/taler-util";
 import {
   ProviderInfo,
   ProviderPaymentPaid,
@@ -32,8 +28,10 @@ import {
   intervalToDuration,
 } from "date-fns";
 import { Fragment, h, VNode } from "preact";
+import { useEffect, useState } from "preact/hooks";
 import { Loading } from "../components/Loading.js";
 import { LoadingError } from "../components/LoadingError.js";
+import { QR } from "../components/QR.js";
 import {
   BoldLight,
   Centered,
@@ -48,10 +46,7 @@ import { useTranslationContext } from 
"../context/translation.js";
 import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
 import { Button } from "../mui/Button.js";
 import { Pages } from "../NavigationBar.js";
-import * as wxApi from "../wxApi.js";
-import { wxClient } from "../wxApi.js";
-import { useEffect, useState } from "preact/hooks";
-import { QR } from "../components/QR.js";
+import { wxApi } from "../wxApi.js";
 
 interface Props {
   onAddProvider: () => Promise<void>;
@@ -112,7 +107,9 @@ export function ShowRecoveryInfo({
 
 export function BackupPage({ onAddProvider }: Props): VNode {
   const { i18n } = useTranslationContext();
-  const status = useAsyncAsHook(wxApi.getBackupInfo);
+  const status = useAsyncAsHook(() =>
+    wxApi.wallet.call(WalletApiOperation.GetBackupInfo, {}),
+  );
   const [recoveryInfo, setRecoveryInfo] = useState<string>("");
   if (!status) {
     return <Loading />;
@@ -127,7 +124,10 @@ export function BackupPage({ onAddProvider }: Props): 
VNode {
   }
 
   async function getRecoveryInfo(): Promise<void> {
-    const r = await wxClient.call(WalletApiOperation.ExportBackupRecovery, {});
+    const r = await wxApi.wallet.call(
+      WalletApiOperation.ExportBackupRecovery,
+      {},
+    );
     const str = constructRecoveryUri(r);
     setRecoveryInfo(str);
   }
@@ -157,7 +157,9 @@ export function BackupPage({ onAddProvider }: Props): VNode 
{
     <BackupView
       providers={providers}
       onAddProvider={onAddProvider}
-      onSyncAll={wxApi.syncAllProviders}
+      onSyncAll={async () =>
+        wxApi.wallet.call(WalletApiOperation.RunBackupCycle, {}).then()
+      }
       onShowInfo={getRecoveryInfo}
     />
   );
diff --git 
a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts 
b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts
index 374d6639f..c757610fc 100644
--- a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts
+++ b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts
@@ -34,73 +34,73 @@ const exchangeListEmpty = {};
 
 describe("CreateManualWithdraw states", () => {
   it("should set noExchangeFound when exchange list is empty", () => {
-    const { getLastResultOrThrow } = mountHook(() =>
+    const { pullLastResultOrThrow } = mountHook(() =>
       useComponentState(exchangeListEmpty, undefined, undefined),
     );
 
-    const { noExchangeFound } = getLastResultOrThrow();
+    const { noExchangeFound } = pullLastResultOrThrow();
 
     expect(noExchangeFound).equal(true);
   });
 
   it("should set noExchangeFound when exchange list doesn't include selected 
currency", () => {
-    const { getLastResultOrThrow } = mountHook(() =>
+    const { pullLastResultOrThrow } = mountHook(() =>
       useComponentState(exchangeListWithARSandUSD, undefined, "COL"),
     );
 
-    const { noExchangeFound } = getLastResultOrThrow();
+    const { noExchangeFound } = pullLastResultOrThrow();
 
     expect(noExchangeFound).equal(true);
   });
 
   it("should select the first exchange from the list", () => {
-    const { getLastResultOrThrow } = mountHook(() =>
+    const { pullLastResultOrThrow } = mountHook(() =>
       useComponentState(exchangeListWithARSandUSD, undefined, undefined),
     );
 
-    const { exchange } = getLastResultOrThrow();
+    const { exchange } = pullLastResultOrThrow();
 
     expect(exchange.value).equal("url1");
   });
 
   it("should select the first exchange with the selected currency", () => {
-    const { getLastResultOrThrow } = mountHook(() =>
+    const { pullLastResultOrThrow } = mountHook(() =>
       useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
     );
 
-    const { exchange } = getLastResultOrThrow();
+    const { exchange } = pullLastResultOrThrow();
 
     expect(exchange.value).equal("url2");
   });
 
   it("should change the exchange when currency change", async () => {
-    const { getLastResultOrThrow, waitNextUpdate } = mountHook(() =>
+    const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() =>
       useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
     );
 
     {
-      const { exchange, currency } = getLastResultOrThrow();
+      const { exchange, currency } = pullLastResultOrThrow();
 
       expect(exchange.value).equal("url2");
       if (currency.onChange === undefined) expect.fail();
       currency.onChange("USD");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { exchange } = getLastResultOrThrow();
+      const { exchange } = pullLastResultOrThrow();
       expect(exchange.value).equal("url1");
     }
   });
 
   it("should change the currency when exchange change", async () => {
-    const { getLastResultOrThrow, waitNextUpdate } = mountHook(() =>
+    const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() =>
       useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
     );
 
     {
-      const { exchange, currency } = getLastResultOrThrow();
+      const { exchange, currency } = pullLastResultOrThrow();
 
       expect(exchange.value).equal("url2");
       expect(currency.value).equal("ARS");
@@ -109,10 +109,10 @@ describe("CreateManualWithdraw states", () => {
       exchange.onChange("url1");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { exchange, currency } = getLastResultOrThrow();
+      const { exchange, currency } = pullLastResultOrThrow();
 
       expect(exchange.value).equal("url1");
       expect(currency.value).equal("USD");
@@ -120,22 +120,22 @@ describe("CreateManualWithdraw states", () => {
   });
 
   it("should update parsed amount when amount change", async () => {
-    const { getLastResultOrThrow, waitNextUpdate } = mountHook(() =>
+    const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() =>
       useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
     );
 
     {
-      const { amount, parsedAmount } = getLastResultOrThrow();
+      const { amount, parsedAmount } = pullLastResultOrThrow();
 
       expect(parsedAmount).equal(undefined);
 
       amount.onInput("12");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { parsedAmount } = getLastResultOrThrow();
+      const { parsedAmount } = pullLastResultOrThrow();
 
       expect(parsedAmount).deep.equals({
         value: 12,
@@ -146,41 +146,41 @@ describe("CreateManualWithdraw states", () => {
   });
 
   it("should have an amount field", async () => {
-    const { getLastResultOrThrow, waitNextUpdate } = mountHook(() =>
+    const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() =>
       useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
     );
 
     await defaultTestForInputText(
-      waitNextUpdate,
-      () => getLastResultOrThrow().amount,
+      waitForStateUpdate,
+      () => pullLastResultOrThrow().amount,
     );
   });
 
   it("should have an exchange selector ", async () => {
-    const { getLastResultOrThrow, waitNextUpdate } = mountHook(() =>
+    const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() =>
       useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
     );
 
     await defaultTestForInputSelect(
-      waitNextUpdate,
-      () => getLastResultOrThrow().exchange,
+      waitForStateUpdate,
+      () => pullLastResultOrThrow().exchange,
     );
   });
 
   it("should have a currency selector ", async () => {
-    const { getLastResultOrThrow, waitNextUpdate } = mountHook(() =>
+    const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() =>
       useComponentState(exchangeListWithARSandUSD, undefined, "ARS"),
     );
 
     await defaultTestForInputSelect(
-      waitNextUpdate,
-      () => getLastResultOrThrow().currency,
+      waitForStateUpdate,
+      () => pullLastResultOrThrow().currency,
     );
   });
 });
 
 async function defaultTestForInputText(
-  awaiter: () => Promise<void>,
+  awaiter: () => Promise<boolean>,
   getField: () => TextFieldHandler,
 ): Promise<void> {
   let nextValue = "";
@@ -191,7 +191,7 @@ async function defaultTestForInputText(
     field.onInput(nextValue);
   }
 
-  await awaiter();
+  expect(await awaiter()).true;
 
   {
     const field = getField();
@@ -200,7 +200,7 @@ async function defaultTestForInputText(
 }
 
 async function defaultTestForInputSelect(
-  awaiter: () => Promise<void>,
+  awaiter: () => Promise<boolean>,
   getField: () => SelectFieldHandler,
 ): Promise<void> {
   let nextValue = "";
@@ -218,7 +218,7 @@ async function defaultTestForInputSelect(
     field.onChange(nextValue);
   }
 
-  await awaiter();
+  expect(await awaiter()).true;
 
   {
     const field = getField();
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts 
b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
index 81d401a70..77661fe15 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
@@ -14,26 +14,25 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
+import { AmountJson, PaytoUri } from "@gnu-taler/taler-util";
 import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
+import {
+  ButtonHandler,
+  SelectFieldHandler,
+  TextFieldHandler
+} from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
+import { wxApi } from "../../wxApi.js";
+import { AddAccountPage } from "../AddAccount/index.js";
+import { useComponentState } from "./state.js";
 import {
   AmountOrCurrencyErrorView,
   LoadingErrorView,
   NoAccountToDepositView,
   NoEnoughBalanceView,
-  ReadyView,
+  ReadyView
 } from "./views.js";
-import * as wxApi from "../../wxApi.js";
-import { useComponentState } from "./state.js";
-import { AmountJson, PaytoUri } from "@gnu-taler/taler-util";
-import {
-  ButtonHandler,
-  SelectFieldHandler,
-  TextFieldHandler,
-  ToggleHandler,
-} from "../../mui/handlers.js";
-import { AddAccountPage } from "../AddAccount/index.js";
 
 export interface Props {
   amount?: string;
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts 
b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
index 57380a632..686cfb4b4 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
@@ -21,11 +21,12 @@ import {
   KnownBankAccountsInfo,
   parsePaytoUri,
   PaytoUri,
-  stringifyPaytoUri,
+  stringifyPaytoUri
 } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { useState } from "preact/hooks";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState(
@@ -36,8 +37,10 @@ export function useComponentState(
   const currency = parsed !== undefined ? parsed.currency : currencyStr;
 
   const hook = useAsyncAsHook(async () => {
-    const { balances } = await api.getBalance();
-    const { accounts } = await api.listKnownBankAccounts(currency);
+    const { balances } = await api.wallet.call(WalletApiOperation.GetBalances, 
{});
+    const { accounts } = await 
api.wallet.call(WalletApiOperation.ListKnownBankAccounts, {
+      currency
+    });
 
     return { accounts, balances };
   });
@@ -127,25 +130,29 @@ export function useComponentState(
     // const newSelected = !accountMap[accountStr] ? undefined : 
accountMap[accountStr];
     // if (!newSelected) return;
     const uri = !accountStr ? undefined : parsePaytoUri(accountStr);
-    setSelectedAccount(uri);
     if (uri && parsedAmount) {
       try {
         const result = await getFeeForAmount(uri, parsedAmount, api);
+        setSelectedAccount(uri);
         setFee(result);
       } catch (e) {
+        console.error(e)
+        setSelectedAccount(uri);
         setFee(undefined);
       }
     }
   }
 
   async function updateAmount(numStr: string): Promise<void> {
-    setAmount(numStr);
     const parsed = Amounts.parse(`${currency}:${numStr}`);
     if (parsed && selectedAccount) {
       try {
         const result = await getFeeForAmount(selectedAccount, parsed, api);
+        setAmount(numStr);
         setFee(result);
       } catch (e) {
+        console.error(e)
+        setAmount(numStr);
         setFee(undefined);
       }
     }
@@ -165,10 +172,10 @@ export function useComponentState(
   const amountError = !isDirty
     ? undefined
     : !parsedAmount
-    ? "Invalid amount"
-    : Amounts.cmp(balance, parsedAmount) === -1
-    ? `Too much, your current balance is ${Amounts.stringifyValue(balance)}`
-    : undefined;
+      ? "Invalid amount"
+      : Amounts.cmp(balance, parsedAmount) === -1
+        ? `Too much, your current balance is 
${Amounts.stringifyValue(balance)}`
+        : undefined;
 
   const unableToDeposit =
     !parsedAmount ||
@@ -176,13 +183,16 @@ export function useComponentState(
     Amounts.isZero(totalToDeposit) ||
     fee === undefined ||
     amountError !== undefined;
+  // console.log(parsedAmount, selectedAccount, fee, totalToDeposit, 
amountError)
 
   async function doSend(): Promise<void> {
     if (!selectedAccount || !parsedAmount || !currency) return;
 
-    const account = 
`payto://${selectedAccount.targetType}/${selectedAccount.targetPath}`;
+    const depositPaytoUri = 
`payto://${selectedAccount.targetType}/${selectedAccount.targetPath}`;
     const amount = Amounts.stringify(parsedAmount);
-    await api.createDepositGroup(account, amount);
+    await api.wallet.call(WalletApiOperation.CreateDepositGroup, {
+      amount, depositPaytoUri
+    })
     onSuccess(currency);
   }
 
@@ -226,9 +236,11 @@ async function getFeeForAmount(
   a: AmountJson,
   api: typeof wxApi,
 ): Promise<DepositGroupFees> {
-  const account = `payto://${p.targetType}/${p.targetPath}`;
+  const depositPaytoUri = `payto://${p.targetType}/${p.targetPath}`;
   const amount = Amounts.stringify(a);
-  return await api.getFeeForDeposit(account, amount);
+  return await api.wallet.call(WalletApiOperation.GetFeeForDeposit, {
+    amount, depositPaytoUri
+  })
 }
 
 export function labelForAccountType(id: string) {
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts 
b/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
index 68df5e402..4d36bc740 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts
@@ -20,101 +20,108 @@
  */
 
 import {
-  Amounts,
-  Balance,
-  BalancesResponse,
-  DepositGroupFees,
+  Amounts, DepositGroupFees,
   parsePaytoUri,
-  stringifyPaytoUri,
+  stringifyPaytoUri
 } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { expect } from "chai";
-import { mountHook } from "../../test-utils.js";
+import { createWalletApiMock, mountHook, nullFunction } from 
"../../test-utils.js";
 
-import * as wxApi from "../../wxApi.js";
 import { useComponentState } from "./state.js";
 
 const currency = "EUR";
-const withoutFee = async (): Promise<DepositGroupFees> => ({
+const withoutFee = (): DepositGroupFees => ({
   coin: Amounts.parseOrThrow(`${currency}:0`),
   wire: Amounts.parseOrThrow(`${currency}:0`),
   refresh: Amounts.parseOrThrow(`${currency}:0`),
 });
 
-const withSomeFee = async (): Promise<DepositGroupFees> => ({
+const withSomeFee = (): DepositGroupFees => ({
   coin: Amounts.parseOrThrow(`${currency}:1`),
   wire: Amounts.parseOrThrow(`${currency}:1`),
   refresh: Amounts.parseOrThrow(`${currency}:1`),
 });
 
-const freeJustForIBAN = async (account: string): Promise<DepositGroupFees> =>
-  /IBAN/i.test(account) ? withSomeFee() : withoutFee();
-
-const someBalance = [
-  {
-    available: "EUR:10",
-  } as Balance,
-];
-
-const nullFunction: any = () => null;
-type VoidFunction = () => void;
-
 describe("DepositPage states", () => {
   it("should have status 'no-enough-balance' when balance is empty", async () 
=> {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = { currency, onCancel: nullFunction, onSuccess: nullFunction }
+
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, undefined, {
+      balances: [{
+        available: `${currency}:0`,
+        hasPendingTransactions: false,
+        pendingIncoming: `${currency}:0`,
+        pendingOutgoing: `${currency}:0`,
+        requiresUserInput: false,
+      }],
+    })
+    handler.addWalletCallResponse(WalletApiOperation.ListKnownBankAccounts, 
undefined, {
+      accounts: []
+    });
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
-          { currency, onCancel: nullFunction, onSuccess: nullFunction },
-          {
-            getBalance: async () =>
-              ({
-                balances: [{ available: `${currency}:0` }],
-              } as Partial<BalancesResponse>),
-            listKnownBankAccounts: async () => ({ accounts: {} }),
-          } as Partial<typeof wxApi> as any,
+          props, mock
         ),
       );
 
     {
-      const { status } = getLastResultOrThrow();
+      const { status } = pullLastResultOrThrow();
       expect(status).equal("loading");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const { status } = getLastResultOrThrow();
+      const { status } = pullLastResultOrThrow();
       expect(status).equal("no-enough-balance");
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
-  // it("should have status 'no-accounts' when balance is not empty and 
accounts is empty", async () => {
-  //   const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
-  //     mountHook(() =>
-  //       useComponentState({ currency, onCancel: nullFunction, onSuccess: 
nullFunction }, {
-  //         getBalance: async () =>
-  //         ({
-  //           balances: [{ available: `${currency}:1` }],
-  //         } as Partial<BalancesResponse>),
-  //         listKnownBankAccounts: async () => ({ accounts: {} }),
-  //       } as Partial<typeof wxApi> as any),
-  //     );
-
-  //   {
-  //     const { status } = getLastResultOrThrow();
-  //     expect(status).equal("loading");
-  //   }
-
-  //   await waitNextUpdate();
-  //   {
-  //     const r = getLastResultOrThrow();
-  //     if (r.status !== "no-accounts") expect.fail();
-  //     expect(r.cancelHandler.onClick).not.undefined;
-  //   }
-
-  //   await assertNoPendingUpdate();
-  // });
+  it("should have status 'no-accounts' when balance is not empty and accounts 
is empty", async () => {
+    const { handler, mock } = createWalletApiMock();
+    const props = { currency, onCancel: nullFunction, onSuccess: nullFunction }
+
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, undefined, {
+      balances: [{
+        available: `${currency}:1`,
+        hasPendingTransactions: false,
+        pendingIncoming: `${currency}:0`,
+        pendingOutgoing: `${currency}:0`,
+        requiresUserInput: false,
+      }],
+    })
+    handler.addWalletCallResponse(WalletApiOperation.ListKnownBankAccounts, 
undefined, {
+      accounts: []
+    });
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
+      mountHook(() =>
+        useComponentState(
+          props, mock
+        )
+      );
+
+    {
+      const { status } = pullLastResultOrThrow();
+      expect(status).equal("loading");
+    }
+
+    expect(await waitForStateUpdate()).true;
+    {
+      const r = pullLastResultOrThrow();
+      if (r.status !== "no-accounts") expect.fail();
+      // expect(r.cancelHandler.onClick).not.undefined;
+    }
+
+    await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
+  });
 
   const ibanPayto = {
     uri: parsePaytoUri("payto://iban/ES8877998399652238")!,
@@ -130,29 +137,38 @@ describe("DepositPage states", () => {
   };
 
   it("should have status 'ready' but unable to deposit ", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+    const { handler, mock } = createWalletApiMock();
+    const props = { currency, onCancel: nullFunction, onSuccess: nullFunction }
+
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, undefined, {
+      balances: [{
+        available: `${currency}:1`,
+        hasPendingTransactions: false,
+        pendingIncoming: `${currency}:0`,
+        pendingOutgoing: `${currency}:0`,
+        requiresUserInput: false,
+      }],
+    })
+    handler.addWalletCallResponse(WalletApiOperation.ListKnownBankAccounts, 
undefined, {
+      accounts: [ibanPayto]
+    });
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
-          { currency, onCancel: nullFunction, onSuccess: nullFunction },
-          {
-            getBalance: async () =>
-              ({
-                balances: [{ available: `${currency}:1` }],
-              } as Partial<BalancesResponse>),
-            listKnownBankAccounts: async () => ({ accounts: [ibanPayto] }),
-          } as Partial<typeof wxApi> as any,
+          props, mock
         ),
       );
 
     {
-      const { status } = getLastResultOrThrow();
+      const { status } = pullLastResultOrThrow();
       expect(status).equal("loading");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "ready") expect.fail();
       expect(r.cancelHandler.onClick).not.undefined;
       expect(r.currency).eq(currency);
@@ -162,33 +178,46 @@ describe("DepositPage states", () => {
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
-  it.skip("should not be able to deposit more than the balance ", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+  it("should not be able to deposit more than the balance ", async () => {
+    const { handler, mock } = createWalletApiMock();
+    const props = { currency, onCancel: nullFunction, onSuccess: nullFunction }
+
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, undefined, {
+      balances: [{
+        available: `${currency}:5`,
+        hasPendingTransactions: false,
+        pendingIncoming: `${currency}:0`,
+        pendingOutgoing: `${currency}:0`,
+        requiresUserInput: false,
+      }],
+    })
+    handler.addWalletCallResponse(WalletApiOperation.ListKnownBankAccounts, 
undefined, {
+      accounts: [ibanPayto]
+    });
+    handler.addWalletCallResponse(WalletApiOperation.GetFeeForDeposit, 
undefined, withoutFee())
+    handler.addWalletCallResponse(WalletApiOperation.GetFeeForDeposit, 
undefined, withoutFee())
+    handler.addWalletCallResponse(WalletApiOperation.GetFeeForDeposit, 
undefined, withoutFee())
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
-          { currency, onCancel: nullFunction, onSuccess: nullFunction },
-          {
-            getBalance: async () =>
-              ({
-                balances: [{ available: `${currency}:1` }],
-              } as Partial<BalancesResponse>),
-            listKnownBankAccounts: async () => ({ accounts: [ibanPayto] }),
-            getFeeForDeposit: withoutFee,
-          } as Partial<typeof wxApi> as any,
+          props, mock
         ),
       );
 
     {
-      const { status } = getLastResultOrThrow();
+      const { status } = pullLastResultOrThrow();
       expect(status).equal("loading");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
+    const accountSelected = stringifyPaytoUri(ibanPayto.uri)
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "ready") expect.fail();
       expect(r.cancelHandler.onClick).not.undefined;
       expect(r.currency).eq(currency);
@@ -196,68 +225,19 @@ describe("DepositPage states", () => {
       expect(r.amount.value).eq("0");
       expect(r.depositHandler.onClick).undefined;
       expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
+      expect(r.account.onChange).not.undefined;
 
-      r.amount.onInput("10");
-    }
-
-    await waitNextUpdate();
-
-    {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
-      expect(r.cancelHandler.onClick).not.undefined;
-      expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
-      expect(r.amount.value).eq("10");
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
-      expect(r.depositHandler.onClick).undefined;
+      r.account.onChange!(accountSelected)
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "ready") expect.fail();
       expect(r.cancelHandler.onClick).not.undefined;
       expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
-      expect(r.amount.value).eq("10");
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
-      expect(r.depositHandler.onClick).undefined;
-    }
-
-    await assertNoPendingUpdate();
-  });
-
-  it.skip("should calculate the fee upon entering amount ", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
-      mountHook(() =>
-        useComponentState(
-          { currency, onCancel: nullFunction, onSuccess: nullFunction },
-          {
-            getBalance: async () =>
-              ({
-                balances: [{ available: `${currency}:1` }],
-              } as Partial<BalancesResponse>),
-            listKnownBankAccounts: async () => ({ accounts: [ibanPayto] }),
-            getFeeForDeposit: withSomeFee,
-          } as Partial<typeof wxApi> as any,
-        ),
-      );
-
-    {
-      const { status } = getLastResultOrThrow();
-      expect(status).equal("loading");
-    }
-
-    await waitNextUpdate();
-
-    {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
-      expect(r.cancelHandler.onClick).not.undefined;
-      expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
+      expect(r.account.value).eq(accountSelected);
       expect(r.amount.value).eq("0");
       expect(r.depositHandler.onClick).undefined;
       expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
@@ -265,64 +245,74 @@ describe("DepositPage states", () => {
       r.amount.onInput("10");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "ready") expect.fail();
       expect(r.cancelHandler.onClick).not.undefined;
       expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
+      expect(r.account.value).eq(accountSelected);
       expect(r.amount.value).eq("10");
       expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:10`));
       expect(r.depositHandler.onClick).undefined;
+
+      r.amount.onInput("3");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "ready") expect.fail();
       expect(r.cancelHandler.onClick).not.undefined;
       expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
-      expect(r.amount.value).eq("10");
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:7`));
-      expect(r.depositHandler.onClick).undefined;
+      expect(r.account.value).eq(accountSelected);
+      expect(r.amount.value).eq("3");
+      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
+      expect(r.depositHandler.onClick).not.undefined;
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
 
-  it("should calculate the fee upon selecting account ", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
+  it("should calculate the fee upon entering amount ", async () => {
+    const { handler, mock } = createWalletApiMock();
+    const props = { currency, onCancel: nullFunction, onSuccess: nullFunction }
+
+    handler.addWalletCallResponse(WalletApiOperation.GetBalances, undefined, {
+      balances: [{
+        available: `${currency}:10`,
+        hasPendingTransactions: false,
+        pendingIncoming: `${currency}:0`,
+        pendingOutgoing: `${currency}:0`,
+        requiresUserInput: false,
+      }],
+    })
+    handler.addWalletCallResponse(WalletApiOperation.ListKnownBankAccounts, 
undefined, {
+      accounts: [ibanPayto]
+    });
+    handler.addWalletCallResponse(WalletApiOperation.GetFeeForDeposit, 
undefined, withSomeFee())
+    handler.addWalletCallResponse(WalletApiOperation.GetFeeForDeposit, 
undefined, withSomeFee())
+
+    const { pullLastResultOrThrow, waitForStateUpdate, assertNoPendingUpdate } 
=
       mountHook(() =>
         useComponentState(
-          { currency, onCancel: nullFunction, onSuccess: nullFunction },
-          {
-            getBalance: async () =>
-              ({
-                balances: [{ available: `${currency}:1` }],
-              } as Partial<BalancesResponse>),
-            listKnownBankAccounts: async () => ({
-              accounts: [ibanPayto, talerBankPayto],
-            }),
-            getFeeForDeposit: freeJustForIBAN,
-          } as Partial<typeof wxApi> as any,
+          props, mock
         ),
       );
 
     {
-      const { status } = getLastResultOrThrow();
+      const { status } = pullLastResultOrThrow();
       expect(status).equal("loading");
     }
 
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
+    const accountSelected = stringifyPaytoUri(ibanPayto.uri)
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "ready") expect.fail();
       expect(r.cancelHandler.onClick).not.undefined;
       expect(r.currency).eq(currency);
@@ -330,198 +320,42 @@ describe("DepositPage states", () => {
       expect(r.amount.value).eq("0");
       expect(r.depositHandler.onClick).undefined;
       expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
+      expect(r.account.onChange).not.undefined;
 
-      if (r.account.onChange === undefined) expect.fail();
-      r.account.onChange(stringifyPaytoUri(ibanPayto.uri));
+      r.account.onChange!(accountSelected)
     }
 
-    await waitNextUpdate("");
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "ready") expect.fail();
       expect(r.cancelHandler.onClick).not.undefined;
       expect(r.currency).eq(currency);
-      expect(r.account.value).eq(stringifyPaytoUri(ibanPayto.uri));
+      expect(r.account.value).eq(accountSelected);
       expect(r.amount.value).eq("0");
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
-      expect(r.depositHandler.onClick).undefined;
-    }
-
-    await waitNextUpdate("");
-
-    {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
-      expect(r.cancelHandler.onClick).not.undefined;
-      expect(r.currency).eq(currency);
-      expect(r.account.value).eq(stringifyPaytoUri(ibanPayto.uri));
-      expect(r.amount.value).eq("0");
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
-      expect(r.depositHandler.onClick).undefined;
-
-      r.amount.onInput("10");
-    }
-
-    await waitNextUpdate("");
-
-    {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
-      expect(r.cancelHandler.onClick).not.undefined;
-      expect(r.currency).eq(currency);
-      expect(r.account.value).eq(stringifyPaytoUri(ibanPayto.uri));
-      expect(r.amount.value).eq("10");
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:7`));
-      expect(r.depositHandler.onClick).undefined;
-    }
-
-    await waitNextUpdate("");
-
-    {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
-      expect(r.cancelHandler.onClick).not.undefined;
-      expect(r.currency).eq(currency);
-      expect(r.account.value).eq(stringifyPaytoUri(ibanPayto.uri));
-      expect(r.amount.value).eq("10");
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:7`));
       expect(r.depositHandler.onClick).undefined;
-
-      if (r.account.onChange === undefined) expect.fail();
-      r.account.onChange(stringifyPaytoUri(talerBankPayto.uri));
-    }
-
-    await waitNextUpdate("");
-
-    {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
-      expect(r.cancelHandler.onClick).not.undefined;
-      expect(r.currency).eq(currency);
-      expect(r.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
-      expect(r.amount.value).eq("10");
       expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:7`));
-      expect(r.depositHandler.onClick).undefined;
-    }
-
-    await waitNextUpdate("");
-
-    {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
-      expect(r.cancelHandler.onClick).not.undefined;
-      expect(r.currency).eq(currency);
-      expect(r.account.value).eq(stringifyPaytoUri(talerBankPayto.uri));
-      expect(r.amount.value).eq("10");
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:10`));
-      expect(r.depositHandler.onClick).undefined;
-    }
-
-    await assertNoPendingUpdate();
-  });
-
-  it.skip("should be able to deposit if has the enough balance ", async () => {
-    const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } =
-      mountHook(() =>
-        useComponentState(
-          { currency, onCancel: nullFunction, onSuccess: nullFunction },
-          {
-            getBalance: async () =>
-              ({
-                balances: [{ available: `${currency}:15` }],
-              } as Partial<BalancesResponse>),
-            listKnownBankAccounts: async () => ({ accounts: [ibanPayto] }),
-            getFeeForDeposit: withSomeFee,
-          } as Partial<typeof wxApi> as any,
-        ),
-      );
-
-    {
-      const { status } = getLastResultOrThrow();
-      expect(status).equal("loading");
-    }
-
-    await waitNextUpdate();
-
-    {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
-      expect(r.cancelHandler.onClick).not.undefined;
-      expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
-      expect(r.amount.value).eq("0");
-      expect(r.depositHandler.onClick).undefined;
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
 
       r.amount.onInput("10");
     }
 
-    await waitNextUpdate();
-
-    {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
-      expect(r.cancelHandler.onClick).not.undefined;
-      expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
-      expect(r.amount.value).eq("10");
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:10`));
-      expect(r.depositHandler.onClick).undefined;
-    }
-
-    await waitNextUpdate();
+    expect(await waitForStateUpdate()).true;
 
     {
-      const r = getLastResultOrThrow();
+      const r = pullLastResultOrThrow();
       if (r.status !== "ready") expect.fail();
       expect(r.cancelHandler.onClick).not.undefined;
       expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
+      expect(r.account.value).eq(accountSelected);
       expect(r.amount.value).eq("10");
       expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
       expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:7`));
       expect(r.depositHandler.onClick).not.undefined;
-
-      r.amount.onInput("13");
-    }
-
-    await waitNextUpdate();
-
-    {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
-      expect(r.cancelHandler.onClick).not.undefined;
-      expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
-      expect(r.amount.value).eq("13");
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:10`));
-      expect(r.depositHandler.onClick).not.undefined;
-    }
-
-    await waitNextUpdate();
-
-    {
-      const r = getLastResultOrThrow();
-      if (r.status !== "ready") expect.fail();
-      expect(r.cancelHandler.onClick).not.undefined;
-      expect(r.currency).eq(currency);
-      expect(r.account.value).eq("");
-      expect(r.amount.value).eq("13");
-      expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`));
-      expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:10`));
-      expect(r.depositHandler.onClick).not.undefined;
     }
 
     await assertNoPendingUpdate();
+    expect(handler.getCallingQueueState()).eq("empty")
   });
+
 });
diff --git 
a/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx 
b/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx
index 94e6ab442..1e52f11bc 100644
--- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx
@@ -15,6 +15,7 @@
  */
 
 import { Amounts } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { styled } from "@linaria/react";
 import { Fragment, h, VNode } from "preact";
 import { useState } from "preact/hooks";
@@ -36,7 +37,7 @@ import { TextField } from "../mui/TextField.js";
 import { Pages } from "../NavigationBar.js";
 import arrowIcon from "../svg/chevron-down.svg";
 import bankIcon from "../svg/ri-bank-line.svg";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 
 const Container = styled.div`
   display: flex;
@@ -171,7 +172,9 @@ export function SelectCurrency({
 }): VNode {
   const { i18n } = useTranslationContext();
 
-  const hook = useAsyncAsHook(wxApi.listExchanges);
+  const hook = useAsyncAsHook(() =>
+    wxApi.wallet.call(WalletApiOperation.ListExchanges, {}),
+  );
 
   if (!hook) {
     return <Loading />;
diff --git a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
index c0e35b17b..2333fd3c1 100644
--- a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
@@ -21,7 +21,10 @@ import {
   ExchangeListItem,
   NotificationType,
 } from "@gnu-taler/taler-util";
-import { PendingTaskInfo } from "@gnu-taler/taler-wallet-core";
+import {
+  PendingTaskInfo,
+  WalletApiOperation,
+} from "@gnu-taler/taler-wallet-core";
 import { format } from "date-fns";
 import { Fragment, h, VNode } from "preact";
 import { useEffect, useRef, useState } from "preact/hooks";
@@ -33,8 +36,7 @@ import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
 import { useDiagnostics } from "../hooks/useDiagnostics.js";
 import { Button } from "../mui/Button.js";
 import { Grid } from "../mui/Grid.js";
-import { Paper } from "../mui/Paper.js";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 
 export function DeveloperPage(): VNode {
   const [status, timedOut] = useDiagnostics();
@@ -44,9 +46,12 @@ export function DeveloperPage(): VNode {
   listenAllEvents.includes = (e) => e !== "waiting-for-retry"; // includes 
every event
 
   const response = useAsyncAsHook(async () => {
-    const op = await wxApi.getPendingOperations();
-    const c = await wxApi.dumpCoins();
-    const ex = await wxApi.listExchanges();
+    const op = await wxApi.wallet.call(
+      WalletApiOperation.GetPendingOperations,
+      {},
+    );
+    const c = await wxApi.wallet.call(WalletApiOperation.DumpCoins, {});
+    const ex = await wxApi.wallet.call(WalletApiOperation.ListExchanges, {});
     return {
       operations: op.pendingOperations,
       coins: c.coins,
@@ -55,9 +60,10 @@ export function DeveloperPage(): VNode {
   });
 
   useEffect(() => {
-    return wxApi.onUpdateNotification(listenAllEvents, () => {
-      response?.retry();
-    });
+    return wxApi.listener.onUpdateNotification(
+      listenAllEvents,
+      response?.retry,
+    );
   });
 
   const nonResponse = { operations: [], coins: [], exchanges: [] };
@@ -76,7 +82,7 @@ export function DeveloperPage(): VNode {
       coins={coins}
       exchanges={exchanges}
       onDownloadDatabase={async () => {
-        const db = await wxApi.exportDB();
+        const db = await wxApi.wallet.call(WalletApiOperation.ExportDb, {});
         return JSON.stringify(db);
       }}
     />
@@ -131,7 +137,9 @@ export function View({
   }
   const fileRef = useRef<HTMLInputElement>(null);
   async function onImportDatabase(str: string): Promise<void> {
-    return wxApi.importDB(JSON.parse(str));
+    return wxApi.wallet.call(WalletApiOperation.ImportDb, {
+      dump: JSON.parse(str),
+    });
   }
   const currencies: { [ex: string]: string } = {};
   const money_by_exchange = coins.reduce(
@@ -169,7 +177,7 @@ export function View({
             onClick={() =>
               confirmReset(
                 i18n.str`Do you want to IRREVOCABLY DESTROY everything inside 
your wallet and LOSE ALL YOUR COINS?`,
-                wxApi.resetDb,
+                () => wxApi.background.resetDb(),
               )
             }
           >
@@ -182,7 +190,7 @@ export function View({
             onClick={() =>
               confirmReset(
                 i18n.str`TESTING: This may delete all your coin, proceed with 
caution`,
-                wxApi.runGarbageCollector,
+                () => wxApi.background.runGarbageCollector(),
               )
             }
           >
diff --git 
a/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/index.ts 
b/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/index.ts
index 605c71e80..4b7725264 100644
--- 
a/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/index.ts
+++ 
b/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/index.ts
@@ -17,9 +17,9 @@
 import { Loading } from "../../components/Loading.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import { LoadingUriView, ReadyView } from "./views.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
+import { LoadingUriView, ReadyView } from "./views.js";
 
 export interface Props {
   p: string;
diff --git 
a/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/state.ts 
b/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/state.ts
index 2c5ac95c0..d194b3f97 100644
--- 
a/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/state.ts
+++ 
b/packages/taler-wallet-webextension/src/wallet/EmptyComponentExample/state.ts
@@ -14,7 +14,7 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState({ p }: Props, api: typeof wxApi): State {
diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx
index 859a7f86b..a0c62787a 100644
--- a/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx
@@ -18,11 +18,12 @@ import {
   canonicalizeBaseUrl,
   TalerConfigResponse,
 } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
 import { queryToSlashKeys } from "../utils/index.js";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 import { ExchangeAddConfirmPage } from "./ExchangeAddConfirm.js";
 import { ExchangeSetUrlPage } from "./ExchangeSetUrl.js";
 
@@ -36,7 +37,9 @@ export function ExchangeAddPage({ currency, onBack }: Props): 
VNode {
     { url: string; config: TalerConfigResponse } | undefined
   >(undefined);
 
-  const knownExchangesResponse = useAsyncAsHook(wxApi.listExchanges);
+  const knownExchangesResponse = useAsyncAsHook(() =>
+    wxApi.wallet.call(WalletApiOperation.ListExchanges, {}),
+  );
   const knownExchanges = !knownExchangesResponse
     ? []
     : knownExchangesResponse.hasError
@@ -72,7 +75,7 @@ export function ExchangeAddPage({ currency, onBack }: Props): 
VNode {
       url={verifying.url}
       onCancel={onBack}
       onConfirm={async () => {
-        await wxApi.addExchange({
+        await wxApi.wallet.call(WalletApiOperation.AddExchange, {
           exchangeBaseUrl: canonicalizeBaseUrl(verifying.url),
           forceUpdate: true,
         });
diff --git 
a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts 
b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts
index 2ea73d310..ddfaa71f9 100644
--- a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/index.ts
@@ -18,15 +18,14 @@ import {
   DenomOperationMap,
   ExchangeFullDetails,
   ExchangeListItem,
-  FeeDescriptionPair,
+  FeeDescriptionPair
 } from "@gnu-taler/taler-util";
 import { Loading } from "../../components/Loading.js";
-import { TermsState } from "../../components/TermsOfService/utils.js";
 import { HookError } from "../../hooks/useAsyncAsHook.js";
 import { State as SelectExchangeState } from 
"../../hooks/useSelectedExchange.js";
 import { ButtonHandler, SelectFieldHandler } from "../../mui/handlers.js";
 import { compose, StateViewMap } from "../../utils/index.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { useComponentState } from "./state.js";
 import {
   ComparingView,
@@ -34,7 +33,7 @@ import {
   NoExchangesView,
   PrivacyContentView,
   ReadyView,
-  TosContentView,
+  TosContentView
 } from "./views.js";
 
 export interface Props {
diff --git 
a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts 
b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts
index 2450a90ca..ee839cad7 100644
--- a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts
@@ -15,10 +15,10 @@
  */
 
 import { DenomOperationMap, FeeDescription } from "@gnu-taler/taler-util";
-import { createPairTimeline } from "@gnu-taler/taler-wallet-core";
+import { createPairTimeline, WalletApiOperation } from 
"@gnu-taler/taler-wallet-core";
 import { useState } from "preact/hooks";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
-import * as wxApi from "../../wxApi.js";
+import { wxApi } from "../../wxApi.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState(
@@ -36,22 +36,20 @@ export function useComponentState(
   const [value, setValue] = useState(String(initialValue));
 
   const hook = useAsyncAsHook(async () => {
-    // const { exchanges } = await api.listExchanges();
-
     const selectedIdx = parseInt(value, 10);
     const selectedExchange =
       exchanges.length == 0 ? undefined : exchanges[selectedIdx];
     const selected = !selectedExchange
       ? undefined
-      : await api.getExchangeDetailedInfo(selectedExchange.exchangeBaseUrl);
+      : await api.wallet.call(WalletApiOperation.GetExchangeDetailedInfo, { 
exchangeBaseUrl: selectedExchange.exchangeBaseUrl });
 
     const initialExchange =
       selectedIdx === initialValue ? undefined : exchanges[initialValue];
     const original = !initialExchange
       ? undefined
-      : await api.getExchangeDetailedInfo(initialExchange.exchangeBaseUrl);
+      : await api.wallet.call(WalletApiOperation.GetExchangeDetailedInfo, { 
exchangeBaseUrl: initialExchange.exchangeBaseUrl });
 
-    return { exchanges, selected, original };
+    return { exchanges, selected: selected?.exchange, original: 
original?.exchange };
   }, [value]);
 
   const [showingTos, setShowingTos] = useState<string | undefined>(undefined);
diff --git a/packages/taler-wallet-webextension/src/wallet/History.tsx 
b/packages/taler-wallet-webextension/src/wallet/History.tsx
index 53913501d..4b9c5c711 100644
--- a/packages/taler-wallet-webextension/src/wallet/History.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/History.tsx
@@ -20,6 +20,7 @@ import {
   NotificationType,
   Transaction,
 } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { Fragment, h, VNode } from "preact";
 import { useEffect, useState } from "preact/hooks";
 import { Loading } from "../components/Loading.js";
@@ -38,7 +39,7 @@ import { Button } from "../mui/Button.js";
 import { NoBalanceHelp } from "../popup/NoBalanceHelp.js";
 import DownloadIcon from "../svg/download_24px.svg";
 import UploadIcon from "../svg/upload_24px.svg";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 
 interface Props {
   currency?: string;
@@ -52,16 +53,14 @@ export function HistoryPage({
 }: Props): VNode {
   const { i18n } = useTranslationContext();
   const state = useAsyncAsHook(async () => ({
-    b: await wxApi.getBalance(),
-    tx: await wxApi.getTransactions(),
+    b: await wxApi.wallet.call(WalletApiOperation.GetBalances, {}),
+    tx: await wxApi.wallet.call(WalletApiOperation.GetTransactions, {}),
   }));
 
   useEffect(() => {
-    return wxApi.onUpdateNotification(
+    return wxApi.listener.onUpdateNotification(
       [NotificationType.WithdrawGroupFinished],
-      () => {
-        state?.retry();
-      },
+      state?.retry,
     );
   });
 
diff --git 
a/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx
index 3714ae538..e2284a466 100644
--- a/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx
@@ -22,13 +22,14 @@ import {
   parsePaytoUri,
   PaytoUri,
 } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { h, VNode } from "preact";
 import { useEffect, useState } from "preact/hooks";
 import { Loading } from "../components/Loading.js";
 import { LoadingError } from "../components/LoadingError.js";
 import { useTranslationContext } from "../context/translation.js";
 import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 import { CreateManualWithdraw } from "./CreateManualWithdraw.js";
 import { ReserveCreated } from "./ReserveCreated.js";
 
@@ -50,11 +51,14 @@ export function ManualWithdrawPage({ amount, onCancel }: 
Props): VNode {
   >(undefined);
   const [error, setError] = useState<string | undefined>(undefined);
 
-  const state = useAsyncAsHook(wxApi.listExchanges);
+  const state = useAsyncAsHook(() =>
+    wxApi.wallet.call(WalletApiOperation.ListExchanges, {}),
+  );
   useEffect(() => {
-    return wxApi.onUpdateNotification([NotificationType.ExchangeAdded], () => {
-      state?.retry();
-    });
+    return wxApi.listener.onUpdateNotification(
+      [NotificationType.ExchangeAdded],
+      state?.retry,
+    );
   });
   const { i18n } = useTranslationContext();
 
@@ -63,9 +67,12 @@ export function ManualWithdrawPage({ amount, onCancel }: 
Props): VNode {
     amount: AmountJson,
   ): Promise<void> {
     try {
-      const response = await wxApi.acceptManualWithdrawal(
-        exchangeBaseUrl,
-        Amounts.stringify(amount),
+      const response = await wxApi.wallet.call(
+        WalletApiOperation.AcceptManualWithdrawal,
+        {
+          exchangeBaseUrl: exchangeBaseUrl,
+          amount: Amounts.stringify(amount),
+        },
       );
       const payto = response.exchangePaytoUris[0];
       const paytoURI = parsePaytoUri(payto);
diff --git a/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx
index e0bdeec5f..d5f072828 100644
--- a/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx
@@ -34,8 +34,7 @@ import {
 import { useTranslationContext } from "../context/translation.js";
 import { Button } from "../mui/Button.js";
 import { queryToSlashConfig } from "../utils/index.js";
-import * as wxApi from "../wxApi.js";
-import { wxClient } from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 
 interface Props {
   currency: string;
@@ -71,7 +70,7 @@ export function ProviderAddPage({ onBack }: Props): VNode {
         setVerifying(undefined);
       }}
       onConfirm={() => {
-        return wxClient
+        return wxApi.wallet
           .call(WalletApiOperation.AddBackupProvider, {
             backupProviderBaseUrl: verifying.url,
             name: verifying.name,
diff --git 
a/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx
index 5378f4b93..d9dd1d746 100644
--- a/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx
@@ -20,6 +20,7 @@ import {
   ProviderInfo,
   ProviderPaymentStatus,
   ProviderPaymentType,
+  WalletApiOperation,
 } from "@gnu-taler/taler-wallet-core";
 import { Fragment, h, VNode } from "preact";
 import { ErrorMessage } from "../components/ErrorMessage.js";
@@ -30,7 +31,7 @@ import { Time } from "../components/Time.js";
 import { useTranslationContext } from "../context/translation.js";
 import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
 import { Button } from "../mui/Button.js";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 
 interface Props {
   pid: string;
@@ -41,7 +42,10 @@ export function ProviderDetailPage({ pid: providerURL, 
onBack }: Props): VNode {
   const { i18n } = useTranslationContext();
   async function getProviderInfo(): Promise<ProviderInfo | null> {
     //create a first list of backup info by currency
-    const status = await wxApi.getBackupInfo();
+    const status = await wxApi.wallet.call(
+      WalletApiOperation.GetBackupInfo,
+      {},
+    );
 
     const providers = status.providers.filter(
       (p) => p.syncProviderBaseUrl === providerURL,
@@ -72,8 +76,20 @@ export function ProviderDetailPage({ pid: providerURL, 
onBack }: Props): VNode {
     <ProviderView
       url={providerURL}
       info={state.response}
-      onSync={() => wxApi.syncOneProvider(providerURL)}
-      onDelete={() => wxApi.removeProvider(providerURL).then(onBack)}
+      onSync={async () =>
+        wxApi.wallet
+          .call(WalletApiOperation.RunBackupCycle, {
+            providers: [providerURL],
+          })
+          .then()
+      }
+      onDelete={() =>
+        wxApi.wallet
+          .call(WalletApiOperation.RemoveBackupProvider, {
+            provider: providerURL,
+          })
+          .then(onBack)
+      }
       onBack={onBack}
       onExtend={async () => {
         null;
diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.tsx 
b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
index 8f6807d46..a4f51de29 100644
--- a/packages/taler-wallet-webextension/src/wallet/Settings.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
@@ -43,7 +43,7 @@ import { useClipboardPermissions } from 
"../hooks/useClipboardPermissions.js";
 import { ToggleHandler } from "../mui/handlers.js";
 import { Pages } from "../NavigationBar.js";
 import { platform } from "../platform/api.js";
-import { wxClient } from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 
 const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : 
undefined;
 
@@ -55,8 +55,8 @@ export function SettingsPage(): VNode {
   const webex = platform.getWalletWebExVersion();
 
   const exchangesHook = useAsyncAsHook(async () => {
-    const list = await wxClient.call(WalletApiOperation.ListExchanges, {});
-    const version = await wxClient.call(WalletApiOperation.GetVersion, {});
+    const list = await wxApi.wallet.call(WalletApiOperation.ListExchanges, {});
+    const version = await wxApi.wallet.call(WalletApiOperation.GetVersion, {});
     return { exchanges: list.exchanges, version };
   });
   const { exchanges, version } =
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx 
b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index c95b79fbc..d7b6e3b1c 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -34,6 +34,7 @@ import {
   TransactionType,
   WithdrawalType,
 } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { styled } from "@linaria/react";
 import { differenceInSeconds } from "date-fns";
 import { ComponentChildren, Fragment, h, VNode } from "preact";
@@ -62,31 +63,33 @@ import { useTranslationContext } from 
"../context/translation.js";
 import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
 import { Button } from "../mui/Button.js";
 import { Pages } from "../NavigationBar.js";
-import * as wxApi from "../wxApi.js";
+import { wxApi } from "../wxApi.js";
 
 interface Props {
   tid: string;
   goToWalletHistory: (currency?: string) => Promise<void>;
 }
 
-async function getTransaction(tid: string): Promise<Transaction> {
-  const res = await wxApi.getTransactionById(tid);
-  return res;
-}
-
-export function TransactionPage({ tid, goToWalletHistory }: Props): VNode {
+export function TransactionPage({
+  tid: transactionId,
+  goToWalletHistory,
+}: Props): VNode {
   const { i18n } = useTranslationContext();
 
-  const state = useAsyncAsHook(() => getTransaction(tid), [tid]);
+  const state = useAsyncAsHook(
+    () =>
+      wxApi.wallet.call(WalletApiOperation.GetTransactionById, {
+        transactionId,
+      }),
+    [transactionId],
+  );
 
-  useEffect(() => {
-    return wxApi.onUpdateNotification(
+  useEffect(() =>
+    wxApi.listener.onUpdateNotification(
       [NotificationType.WithdrawGroupFinished],
-      () => {
-        state?.retry();
-      },
-    );
-  });
+      state?.retry,
+    ),
+  );
 
   if (!state) {
     return <Loading />;
@@ -113,15 +116,23 @@ export function TransactionPage({ tid, goToWalletHistory 
}: Props): VNode {
       onSend={async () => {
         null;
       }}
-      onDelete={() =>
-        wxApi.deleteTransaction(tid).then(() => goToWalletHistory(currency))
-      }
-      onRetry={async () =>
-        await wxApi
-          .retryTransaction(tid)
-          .then(() => goToWalletHistory(currency))
-      }
-      onRefund={(id) => wxApi.applyRefundFromPurchaseId(id).then()}
+      onDelete={async () => {
+        await wxApi.wallet.call(WalletApiOperation.DeleteTransaction, {
+          transactionId,
+        });
+        goToWalletHistory(currency);
+      }}
+      onRetry={async () => {
+        await wxApi.wallet.call(WalletApiOperation.RetryTransaction, {
+          transactionId,
+        });
+        goToWalletHistory(currency);
+      }}
+      onRefund={async (purchaseId) => {
+        await wxApi.wallet.call(WalletApiOperation.ApplyRefundFromPurchaseId, {
+          purchaseId,
+        });
+      }}
       onBack={() => goToWalletHistory(currency)}
     />
   );
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts 
b/packages/taler-wallet-webextension/src/wxApi.ts
index cb333f1dc..bd1184d46 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -22,77 +22,16 @@
  * Imports.
  */
 import {
-  AcceptExchangeTosRequest,
-  AcceptManualWithdrawalResult,
-  AcceptPeerPullPaymentRequest,
-  AcceptPeerPullPaymentResponse,
-  AcceptPeerPushPaymentRequest,
-  AcceptPeerPushPaymentResponse,
-  AcceptTipRequest,
-  AcceptTipResponse,
-  AcceptWithdrawalResponse,
-  AddExchangeRequest,
-  AddKnownBankAccountsRequest,
-  AmountString,
-  ApplyRefundResponse,
-  BalancesResponse,
-  CheckPeerPullPaymentRequest,
-  CheckPeerPullPaymentResponse,
-  CheckPeerPushPaymentRequest,
-  CheckPeerPushPaymentResponse,
-  CoinDumpJson,
-  ConfirmPayResult,
-  CoreApiResponse,
-  CreateDepositGroupRequest,
-  CreateDepositGroupResponse,
-  DeleteTransactionRequest,
-  DepositGroupFees,
-  ExchangeFullDetails,
-  ExchangesListResponse,
-  ForgetKnownBankAccountsRequest,
-  GetExchangeTosResult,
-  GetFeeForDepositRequest,
-  GetWithdrawalDetailsForAmountRequest,
-  GetWithdrawalDetailsForUriRequest,
-  InitiatePeerPullPaymentRequest,
-  InitiatePeerPullPaymentResponse,
-  InitiatePeerPushPaymentRequest,
-  InitiatePeerPushPaymentResponse,
-  KnownBankAccounts,
-  Logger,
-  ManualWithdrawalDetails,
-  NotificationType,
-  PaytoUri,
-  PrepareDepositRequest,
-  PrepareDepositResponse,
-  PreparePayResult,
-  PrepareRefundRequest,
-  PrepareRefundResult,
-  PrepareTipRequest,
-  PrepareTipResult,
-  RetryTransactionRequest,
-  SetWalletDeviceIdRequest,
-  stringifyPaytoUri,
-  Transaction,
-  TransactionsResponse,
-  WalletCoreVersion,
-  WalletDiagnostics,
-  WithdrawUriInfoResponse,
+  CoreApiResponse, Logger, NotificationType, WalletDiagnostics
 } from "@gnu-taler/taler-util";
 import {
-  AddBackupProviderRequest,
-  BackupInfo,
-  PendingOperationsResponse,
-  RemoveBackupProviderRequest,
-  TalerError,
-  WalletApiOperation,
-  WalletContractData,
-  WalletCoreApiClient,
+  TalerError, WalletCoreApiClient,
   WalletCoreOpKeys,
   WalletCoreRequestType,
-  WalletCoreResponseType,
+  WalletCoreResponseType
 } from "@gnu-taler/taler-wallet-core";
 import { MessageFromBackend, platform } from "./platform/api.js";
+import { nullFunction } from "./test-utils.js";
 
 /**
  *
@@ -167,381 +106,39 @@ export class WxWalletCoreApiClient implements 
WalletCoreApiClient {
   }
 }
 
-export const wxClient = new WxWalletCoreApiClient();
+export class BackgroundApiClient {
 
-/**
- * Pay for a proposal.
- */
-export function confirmPay(
-  proposalId: string,
-  sessionId: string | undefined,
-): Promise<ConfirmPayResult> {
-  return wxClient.call(WalletApiOperation.ConfirmPay, {
-    proposalId,
-    sessionId,
-  });
-}
-
-/**
- * Check upgrade information
- */
-export function checkUpgrade(): Promise<UpgradeResponse> {
-  return callBackend("check-upgrade", {});
-}
-
-/**
- * Reset database
- */
-export function resetDb(): Promise<void> {
-  return callBackend("reset-db", {});
-}
-
-/**
- * Reset database
- */
-export function runGarbageCollector(): Promise<void> {
-  return callBackend("run-gc", {});
-}
-
-export function getFeeForDeposit(
-  depositPaytoUri: string,
-  amount: AmountString,
-): Promise<DepositGroupFees> {
-  return callBackend("getFeeForDeposit", {
-    depositPaytoUri,
-    amount,
-  } as GetFeeForDepositRequest);
-}
-
-export function prepareDeposit(
-  depositPaytoUri: string,
-  amount: AmountString,
-): Promise<PrepareDepositResponse> {
-  return callBackend("prepareDeposit", {
-    depositPaytoUri,
-    amount,
-  } as PrepareDepositRequest);
-}
-
-export function createDepositGroup(
-  depositPaytoUri: string,
-  amount: AmountString,
-): Promise<CreateDepositGroupResponse> {
-  return callBackend("createDepositGroup", {
-    depositPaytoUri,
-    amount,
-  } as CreateDepositGroupRequest);
-}
-
-/**
- * Get balances for all currencies/exchanges.
- */
-export function getBalance(): Promise<BalancesResponse> {
-  return callBackend("getBalances", {});
-}
-
-export function getContractTermsDetails(
-  proposalId: string,
-): Promise<WalletContractData> {
-  return callBackend("getContractTermsDetails", { proposalId });
-}
-
-/**
- * Retrieve the full event history for this wallet.
- */
-export function getTransactions(): Promise<TransactionsResponse> {
-  return callBackend("getTransactions", {});
-}
-
-interface CurrencyInfo {
-  name: string;
-  baseUrl: string;
-  pub: string;
-}
-interface ListOfKnownCurrencies {
-  auditors: CurrencyInfo[];
-  exchanges: CurrencyInfo[];
-}
-
-/**
- * Get a list of currencies from known auditors and exchanges
- */
-export function listKnownCurrencies(): Promise<ListOfKnownCurrencies> {
-  return callBackend("listCurrencies", {}).then((result) => {
-    const auditors = result.trustedAuditors.map(
-      (a: Record<string, string>) => ({
-        name: a.currency,
-        baseUrl: a.auditorBaseUrl,
-        pub: a.auditorPub,
-      }),
-    );
-    const exchanges = result.trustedExchanges.map(
-      (a: Record<string, string>) => ({
-        name: a.currency,
-        baseUrl: a.exchangeBaseUrl,
-        pub: a.exchangeMasterPub,
-      }),
-    );
-    return { auditors, exchanges };
-  });
-}
-
-export function listExchanges(): Promise<ExchangesListResponse> {
-  return callBackend("listExchanges", {});
-}
-
-export function getExchangeDetailedInfo(
-  exchangeBaseUrl: string,
-): Promise<ExchangeFullDetails> {
-  return callBackend("getExchangeDetailedInfo", {
-    exchangeBaseUrl,
-  });
-}
-
-export function getVersion(): Promise<WalletCoreVersion> {
-  return callBackend("getVersion", {});
-}
-
-export function listKnownBankAccounts(
-  currency?: string,
-): Promise<KnownBankAccounts> {
-  return callBackend("listKnownBankAccounts", { currency });
-}
-
-export function addKnownBankAccounts(
-  payto: PaytoUri,
-  currency: string,
-  alias: string,
-): Promise<void> {
-  return callBackend("addKnownBankAccounts", {
-    payto: stringifyPaytoUri(payto),
-    currency,
-    alias,
-  } as AddKnownBankAccountsRequest);
-}
-export function forgetKnownBankAccounts(payto: string): Promise<void> {
-  return callBackend("forgetKnownBankAccounts", {
-    payto,
-  } as ForgetKnownBankAccountsRequest);
-}
-
-/**
- * Get information about the current state of wallet backups.
- */
-export function getBackupInfo(): Promise<BackupInfo> {
-  return callBackend("getBackupInfo", {});
-}
-
-/**
- * Add a backup provider and activate it
- */
-export function addBackupProvider(
-  backupProviderBaseUrl: string,
-  name: string,
-): Promise<void> {
-  return callBackend("addBackupProvider", {
-    backupProviderBaseUrl,
-    activate: true,
-    name,
-  } as AddBackupProviderRequest);
-}
-
-export function setWalletDeviceId(walletDeviceId: string): Promise<void> {
-  return callBackend("setWalletDeviceId", {
-    walletDeviceId,
-  } as SetWalletDeviceIdRequest);
-}
-
-export function syncAllProviders(): Promise<void> {
-  return callBackend("runBackupCycle", {});
-}
-
-export function syncOneProvider(url: string): Promise<void> {
-  return callBackend("runBackupCycle", { providers: [url] });
-}
-export function removeProvider(url: string): Promise<void> {
-  return callBackend("removeBackupProvider", {
-    provider: url,
-  } as RemoveBackupProviderRequest);
-}
-export function extendedProvider(url: string): Promise<void> {
-  return callBackend("extendBackupProvider", { provider: url });
-}
-
-/**
- * Retry a transaction
- * @param transactionId
- * @returns
- */
-export function retryTransaction(transactionId: string): Promise<void> {
-  return callBackend("retryTransaction", {
-    transactionId,
-  } as RetryTransactionRequest);
-}
-
-/**
- * Permanently delete a transaction from the transaction list
- */
-export function deleteTransaction(transactionId: string): Promise<void> {
-  return callBackend("deleteTransaction", {
-    transactionId,
-  } as DeleteTransactionRequest);
-}
-
-/**
- * Download a refund and accept it.
- */
-export function applyRefund(
-  talerRefundUri: string,
-): Promise<ApplyRefundResponse> {
-  return callBackend("applyRefund", { talerRefundUri });
-}
-
-/**
- * Do refund for purchase.
- */
-export function applyRefundFromPurchaseId(
-  purchaseId: string,
-): Promise<ApplyRefundResponse> {
-  return callBackend("applyRefundFromPurchaseId", { purchaseId });
-}
-
-/**
- * Get details about a pay operation.
- */
-export function preparePay(talerPayUri: string): Promise<PreparePayResult> {
-  return callBackend("preparePayForUri", { talerPayUri });
-}
-
-/**
- * Get details about a withdraw operation.
- */
-export function acceptWithdrawal(
-  talerWithdrawUri: string,
-  selectedExchange: string,
-  restrictAge?: number,
-): Promise<AcceptWithdrawalResponse> {
-  return callBackend("acceptBankIntegratedWithdrawal", {
-    talerWithdrawUri,
-    exchangeBaseUrl: selectedExchange,
-    restrictAge,
-  });
-}
-
-/**
- * Create a reserve into the exchange that expect the amount indicated
- * @param exchangeBaseUrl
- * @param amount
- * @returns
- */
-export function acceptManualWithdrawal(
-  exchangeBaseUrl: string,
-  amount: string,
-  restrictAge?: number,
-): Promise<AcceptManualWithdrawalResult> {
-  return callBackend("acceptManualWithdrawal", {
-    amount,
-    exchangeBaseUrl,
-    restrictAge,
-  });
-}
-
-export function setExchangeTosAccepted(
-  exchangeBaseUrl: string,
-  etag: string | undefined,
-): Promise<void> {
-  return callBackend("setExchangeTosAccepted", {
-    exchangeBaseUrl,
-    etag,
-  } as AcceptExchangeTosRequest);
-}
-
-/**
- * Get diagnostics information
- */
-export function getDiagnostics(): Promise<WalletDiagnostics> {
-  return callBackend("wxGetDiagnostics", {});
-}
-
-/**
- * Get diagnostics information
- */
-export function toggleHeaderListener(
-  value: boolean,
-): Promise<ExtendedPermissionsResponse> {
-  return callBackend("toggleHeaderListener", { value });
-}
-
-/**
- * Get diagnostics information
- */
-export function containsHeaderListener(): Promise<ExtendedPermissionsResponse> 
{
-  return callBackend("containsHeaderListener", {});
-}
-
-/**
- * Get diagnostics information
- */
-export function getWithdrawalDetailsForUri(
-  req: GetWithdrawalDetailsForUriRequest,
-): Promise<WithdrawUriInfoResponse> {
-  return callBackend("getWithdrawalDetailsForUri", req);
-}
-
-export function getWithdrawalDetailsForAmount(
-  req: GetWithdrawalDetailsForAmountRequest,
-): Promise<ManualWithdrawalDetails> {
-  return callBackend("getWithdrawalDetailsForAmount", req);
-}
-
-export function getExchangeTos(
-  exchangeBaseUrl: string,
-  acceptedFormat: string[],
-): Promise<GetExchangeTosResult> {
-  return callBackend("getExchangeTos", {
-    exchangeBaseUrl,
-    acceptedFormat,
-  });
-}
-
-export function dumpCoins(): Promise<CoinDumpJson> {
-  return callBackend("dumpCoins", {});
-}
-
-export function getPendingOperations(): Promise<PendingOperationsResponse> {
-  return callBackend("getPendingOperations", {});
-}
-
-export function addExchange(req: AddExchangeRequest): Promise<void> {
-  return callBackend("addExchange", req);
-}
+  public resetDb(): Promise<void> {
+    return callBackend("reset-db", {});
+  }
 
-export function prepareRefund(
-  req: PrepareRefundRequest,
-): Promise<PrepareRefundResult> {
-  return callBackend("prepareRefund", req);
-}
+  public containsHeaderListener(): Promise<ExtendedPermissionsResponse> {
+    return callBackend("containsHeaderListener", {});
+  }
 
-export function prepareTip(req: PrepareTipRequest): Promise<PrepareTipResult> {
-  return callBackend("prepareTip", req);
-}
+  public getDiagnostics(): Promise<WalletDiagnostics> {
+    return callBackend("wxGetDiagnostics", {});
+  }
 
-export function acceptTip(req: AcceptTipRequest): Promise<AcceptTipResponse> {
-  return callBackend("acceptTip", req);
-}
+  public toggleHeaderListener(
+    value: boolean,
+  ): Promise<ExtendedPermissionsResponse> {
+    return callBackend("toggleHeaderListener", { value });
+  }
 
-export function exportDB(): Promise<any> {
-  return callBackend("exportDb", {});
-}
+  public runGarbageCollector(): Promise<void> {
+    return callBackend("run-gc", {});
+  }
 
-export function importDB(dump: any): Promise<void> {
-  return callBackend("importDb", { dump });
 }
-
-export function onUpdateNotification(
+function onUpdateNotification(
   messageTypes: Array<NotificationType>,
-  doCallback: () => void,
+  doCallback: undefined | (() => void),
 ): () => void {
+  //if no callback, then ignore
+  if (!doCallback) return () => {
+    return
+  };
   const onNewMessage = (message: MessageFromBackend): void => {
     const shouldNotify = messageTypes.includes(message.type);
     if (shouldNotify) {
@@ -551,39 +148,11 @@ export function onUpdateNotification(
   return platform.listenToWalletBackground(onNewMessage);
 }
 
-export function initiatePeerPushPayment(
-  req: InitiatePeerPushPaymentRequest,
-): Promise<InitiatePeerPushPaymentResponse> {
-  return callBackend("initiatePeerPushPayment", req);
-}
-export function checkPeerPushPayment(
-  req: CheckPeerPushPaymentRequest,
-): Promise<CheckPeerPushPaymentResponse> {
-  return callBackend("checkPeerPushPayment", req);
-}
-export function acceptPeerPushPayment(
-  req: AcceptPeerPushPaymentRequest,
-): Promise<AcceptPeerPushPaymentResponse> {
-  return callBackend("acceptPeerPushPayment", req);
-}
-export function initiatePeerPullPayment(
-  req: InitiatePeerPullPaymentRequest,
-): Promise<InitiatePeerPullPaymentResponse> {
-  return callBackend("initiatePeerPullPayment", req);
-}
-export function checkPeerPullPayment(
-  req: CheckPeerPullPaymentRequest,
-): Promise<CheckPeerPullPaymentResponse> {
-  return callBackend("checkPeerPullPayment", req);
-}
-export function acceptPeerPullPayment(
-  req: AcceptPeerPullPaymentRequest,
-): Promise<AcceptPeerPullPaymentResponse> {
-  return callBackend("acceptPeerPullPayment", req);
+export const wxApi = {
+  wallet: new WxWalletCoreApiClient(),
+  background: new BackgroundApiClient(),
+  listener: {
+    onUpdateNotification
+  }
 }
 
-export function getTransactionById(tid: string): Promise<Transaction> {
-  return callBackend("getTransactionById", {
-    transactionId: tid,
-  });
-}

-- 
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]