gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated (26590fbae -> fb8854320)


From: gnunet
Subject: [taler-wallet-core] branch master updated (26590fbae -> fb8854320)
Date: Mon, 05 Feb 2024 13:18:42 +0100

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

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

    from 26590fbae harness: coin gen without fees
     new fc42d265b rename tip to rewards
     new 83ff7de59 fix: reward URI parser and tests didn't take into account 
the last '/'
     new b71d6f2b1 wip DD39: removed webRequest permission and changes made 
into demobank
     new fb8854320 wrong routing sending into a loop

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 packages/demobank-ui/src/Routing.tsx               | 153 ++++++-----
 packages/demobank-ui/src/components/app.tsx        |   8 +-
 packages/demobank-ui/src/context/navigation.ts     |  80 ++++++
 .../demobank-ui/src/context/wallet-integration.ts  |  90 ++++++
 packages/demobank-ui/src/index.html                |  42 +--
 .../demobank-ui/src/pages/OperationState/views.tsx |  16 +-
 packages/demobank-ui/src/pages/PaymentOptions.tsx  |  49 +++-
 .../demobank-ui/src/pages/ProfileNavigation.tsx    |  10 +-
 packages/demobank-ui/src/pages/QrCodeSection.tsx   |  19 +-
 .../demobank-ui/src/pages/WalletWithdrawForm.tsx   |  31 ++-
 .../demobank-ui/src/pages/WithdrawalQRCode.tsx     |  46 ++--
 .../src/pages/business/CreateCashout.tsx           |   2 +-
 packages/demobank-ui/src/route.ts                  | 124 +--------
 packages/taler-util/src/taleruri.test.ts           |   4 +-
 packages/taler-util/src/taleruri.ts                |   5 +-
 .../taler-wallet-webextension/manifest-v2.json     |   1 -
 .../taler-wallet-webextension/manifest-v3.json     |   1 -
 .../src/NavigationBar.tsx                          |   3 +-
 .../taler-wallet-webextension/src/platform/api.ts  |  35 ++-
 .../src/platform/chrome.ts                         | 302 ++-------------------
 .../taler-wallet-webextension/src/platform/dev.ts  |   7 -
 .../src/platform/firefox.ts                        |  11 -
 .../src/popup/TalerActionFound.tsx                 |   6 +-
 .../src/taler-wallet-interaction-loader.ts         | 121 ++++++---
 .../src/taler-wallet-interaction-support.ts        |  26 +-
 .../src/wallet/Application.tsx                     |  16 +-
 .../src/wallet/DeveloperPage.tsx                   | 205 +++++++-------
 .../src/wallet/Settings.stories.tsx                |   4 -
 .../src/wallet/Settings.tsx                        |  23 --
 packages/taler-wallet-webextension/src/wxApi.ts    |  10 +-
 .../taler-wallet-webextension/src/wxBackend.ts     |  81 +-----
 31 files changed, 686 insertions(+), 845 deletions(-)
 create mode 100644 packages/demobank-ui/src/context/navigation.ts
 create mode 100644 packages/demobank-ui/src/context/wallet-integration.ts

diff --git a/packages/demobank-ui/src/Routing.tsx 
b/packages/demobank-ui/src/Routing.tsx
index e73493d60..afc13636a 100644
--- a/packages/demobank-ui/src/Routing.tsx
+++ b/packages/demobank-ui/src/Routing.tsx
@@ -48,6 +48,8 @@ import { RemoveAccount } from 
"./pages/admin/RemoveAccount.js";
 import { CreateCashout } from "./pages/business/CreateCashout.js";
 import { ShowCashoutDetails } from "./pages/business/ShowCashoutDetails.js";
 import { RouteParamsType, urlPattern, useCurrentLocation } from "./route.js";
+import { useNavigationContext } from "./context/navigation.js";
+import { useEffect } from "preact/hooks";
 
 export function Routing(): VNode {
   const backend = useBackendState();
@@ -89,12 +91,18 @@ function PublicRounting({
 }): VNode {
   const settings = useSettingsContext();
   const { i18n } = useTranslationContext();
-  const [loc, routeTo] = useCurrentLocation(publicPages);
+  const location = useCurrentLocation(publicPages);
+  const { navigateTo } = useNavigationContext()
   const { api } = useBankCoreApiContext();
   const [notification, notify, handleError] = useLocalNotification();
 
-  if (loc === undefined) {
-    routeTo("login", {});
+  useEffect(() => {
+    if (location === undefined) {
+      navigateTo(publicPages.login.url({}))
+    }
+  }, [location])
+
+  if (location === undefined) {
     return <Fragment />;
   }
 
@@ -132,7 +140,7 @@ function PublicRounting({
     });
   }
 
-  switch (loc.name) {
+  switch (location.name) {
     case "login": {
       return (
         <Fragment>
@@ -148,17 +156,17 @@ function PublicRounting({
       return <PublicHistoriesPage />;
     }
     case "operationDetails": {
-      const { wopid } = loc.values as RouteParamsType<
-        typeof loc.parent,
-        typeof loc.name
+      const { wopid } = location.values as RouteParamsType<
+        typeof location.parent,
+        typeof location.name
       >;
 
       return (
         <WithdrawalOperationPage
           operationId={wopid}
-          onOperationAborted={() => routeTo("login", {})}
+          onOperationAborted={() => navigateTo(publicPages.login.url({}))}
           routeClose={publicPages.login}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onAuthorizationRequired={() => 
navigateTo(publicPages.solveSecondFactor.url({}))}
         />
       );
     }
@@ -176,18 +184,17 @@ function PublicRounting({
     case "solveSecondFactor": {
       return (
         <SolveChallengePage
-          onChallengeCompleted={() => routeTo("login", {})}
+          onChallengeCompleted={() => navigateTo(publicPages.login.url({}))}
           routeClose={publicPages.login}
         />
       );
     }
     default:
-      assertUnreachable(loc.name);
+      assertUnreachable(location.name);
   }
 }
 
 export const privatePages = {
-  home: urlPattern(/\/account/, () => "#/account"),
   homeChargeWallet: urlPattern(
     /\/account\/charge-wallet/,
     () => "#/account/charge-wallet",
@@ -196,6 +203,7 @@ export const privatePages = {
     /\/account\/wire-transfer/,
     () => "#/account/wire-transfer",
   ),
+  home: urlPattern(/\/account/, () => "#/account"),
   solveSecondFactor: urlPattern(/\/2fa/, () => "#/2fa"),
   cashoutCreate: urlPattern(/\/new-cashout/, () => "#/new-cashout"),
   cashoutDetails: urlPattern<{ cid: string }>(
@@ -233,7 +241,7 @@ export const privatePages = {
     ({ account }) => `#/profile/${account}/cashouts`,
   ),
   operationDetails: urlPattern<{ wopid: string }>(
-    /\/operation\/(?<wopid>[a-zA-Z0-9]+)/,
+    /\/operation\/(?<wopid>[a-zA-Z0-9-]+)/,
     ({ wopid }) => `#/operation/${wopid}`,
   ),
 };
@@ -245,33 +253,38 @@ function PrivateRouting({
   username: string;
   isAdmin: boolean;
 }): VNode {
-  const [loc, routeTo] = useCurrentLocation(privatePages);
+  const { navigateTo } = useNavigationContext()
+  const location = useCurrentLocation(privatePages);
+  useEffect(() => {
+    if (location === undefined) {
+      navigateTo(privatePages.home.url({}))
+    }
+  }, [location])
 
-  if (loc === undefined) {
-    routeTo("home", {});
+  if (location === undefined) {
     return <Fragment />;
   }
 
-  switch (loc.name) {
+  switch (location.name) {
     case "operationDetails": {
-      const { wopid } = loc.values as RouteParamsType<
-        typeof loc.parent,
-        typeof loc.name
+      const { wopid } = location.values as RouteParamsType<
+        typeof location.parent,
+        typeof location.name
       >;
 
       return (
         <WithdrawalOperationPage
           operationId={wopid}
-          onOperationAborted={() => routeTo("home", {})}
+          onOperationAborted={() => navigateTo(privatePages.home.url({}))}
           routeClose={privatePages.home}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
         />
       );
     }
     case "solveSecondFactor": {
       return (
         <SolveChallengePage
-          onChallengeCompleted={() => routeTo("home", {})}
+          onChallengeCompleted={() => navigateTo(privatePages.home.url({}))}
           routeClose={privatePages.home}
         />
       );
@@ -286,64 +299,64 @@ function PrivateRouting({
       return (
         <CreateNewAccount
           routeCancel={privatePages.home}
-          onCreateSuccess={() => routeTo("home", {})}
+          onCreateSuccess={() => navigateTo(privatePages.home.url({}))}
         />
       );
     }
     case "accountDetails": {
-      const { account } = loc.values as RouteParamsType<
-        typeof loc.parent,
-        typeof loc.name
+      const { account } = location.values as RouteParamsType<
+        typeof location.parent,
+        typeof location.name
       >;
       return (
         <ShowAccountDetails
           account={account}
-          onUpdateSuccess={() => routeTo("home", {})}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
           routeClose={privatePages.home}
         />
       );
     }
     case "accountChangePassword": {
-      const { account } = loc.values as RouteParamsType<
-        typeof loc.parent,
-        typeof loc.name
+      const { account } = location.values as RouteParamsType<
+        typeof location.parent,
+        typeof location.name
       >;
       return (
         <UpdateAccountPassword
           focus
           account={account}
-          onUpdateSuccess={() => routeTo("home", {})}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
           routeClose={privatePages.home}
         />
       );
     }
     case "accountDelete": {
-      const { account } = loc.values as RouteParamsType<
-        typeof loc.parent,
-        typeof loc.name
+      const { account } = location.values as RouteParamsType<
+        typeof location.parent,
+        typeof location.name
       >;
       return (
         <RemoveAccount
           account={account}
-          onUpdateSuccess={() => routeTo("home", {})}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
           routeCancel={privatePages.home}
         />
       );
     }
     case "accountCashouts": {
-      const { account } = loc.values as RouteParamsType<
-        typeof loc.parent,
-        typeof loc.name
+      const { account } = location.values as RouteParamsType<
+        typeof location.parent,
+        typeof location.name
       >;
       return (
         <CashoutListForAccount
           account={account}
           routeCashoutDetails={privatePages.cashoutDetails}
           routeClose={privatePages.home}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
         />
       );
     }
@@ -351,8 +364,8 @@ function PrivateRouting({
       return (
         <RemoveAccount
           account={username}
-          onUpdateSuccess={() => routeTo("home", {})}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
           routeCancel={privatePages.home}
         />
       );
@@ -361,8 +374,8 @@ function PrivateRouting({
       return (
         <ShowAccountDetails
           account={username}
-          onUpdateSuccess={() => routeTo("home", {})}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
           routeClose={privatePages.home}
         />
       );
@@ -372,8 +385,8 @@ function PrivateRouting({
         <UpdateAccountPassword
           focus
           account={username}
-          onUpdateSuccess={() => routeTo("home", {})}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onUpdateSuccess={() => navigateTo(privatePages.home.url({}))}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
           routeClose={privatePages.home}
         />
       );
@@ -383,7 +396,7 @@ function PrivateRouting({
         <CashoutListForAccount
           account={username}
           routeCashoutDetails={privatePages.cashoutDetails}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
           routeClose={privatePages.home}
         />
       );
@@ -392,7 +405,7 @@ function PrivateRouting({
       if (isAdmin) {
         return (
           <AdminHome
-            onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+            onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
             routeCreate={privatePages.accountCreate}
             routeRemoveAccount={privatePages.accountDelete}
             routeShowAccount={privatePages.accountDetails}
@@ -408,9 +421,9 @@ function PrivateRouting({
           routeChargeWallet={privatePages.homeChargeWallet}
           routeWireTransfer={privatePages.homeWireTransfer}
           routeClose={privatePages.home}
-          onClose={() => routeTo("home", {})}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
-          onOperationCreated={(wopid) => routeTo("operationDetails", { wopid 
})}
+          onClose={() => navigateTo(privatePages.home.url({}))}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onOperationCreated={(wopid) => 
navigateTo(privatePages.operationDetails.url({ wopid }))}
         />
       );
     }
@@ -418,15 +431,15 @@ function PrivateRouting({
       return (
         <CreateCashout
           account={username}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
           routeClose={privatePages.home}
         />
       );
     }
     case "cashoutDetails": {
-      const { cid } = loc.values as RouteParamsType<
-        typeof loc.parent,
-        typeof loc.name
+      const { cid } = location.values as RouteParamsType<
+        typeof location.parent,
+        typeof location.name
       >;
       return (
         <ShowCashoutDetails
@@ -436,16 +449,16 @@ function PrivateRouting({
       );
     }
     case "wireTranserCreate": {
-      const { destination } = loc.values as RouteParamsType<
-        typeof loc.parent,
-        typeof loc.name
+      const { destination } = location.values as RouteParamsType<
+        typeof location.parent,
+        typeof location.name
       >;
       return (
         <WireTransfer
           toAccount={destination}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
           routeCancel={privatePages.home}
-          onSuccess={() => routeTo("home", {})}
+          onSuccess={() => navigateTo(privatePages.home.url({}))}
         />
       );
     }
@@ -457,9 +470,9 @@ function PrivateRouting({
           routeChargeWallet={privatePages.homeChargeWallet}
           routeWireTransfer={privatePages.homeWireTransfer}
           routeClose={privatePages.home}
-          onClose={() => routeTo("home", {})}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
-          onOperationCreated={(wopid) => routeTo("operationDetails", { wopid 
})}
+          onClose={() => navigateTo(privatePages.home.url({}))}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onOperationCreated={(wopid) => 
navigateTo(privatePages.operationDetails.url({ wopid }))}
         />
       );
     }
@@ -471,13 +484,13 @@ function PrivateRouting({
           routeChargeWallet={privatePages.homeChargeWallet}
           routeWireTransfer={privatePages.homeWireTransfer}
           routeClose={privatePages.home}
-          onClose={() => routeTo("home", {})}
-          onAuthorizationRequired={() => routeTo("solveSecondFactor", {})}
-          onOperationCreated={(wopid) => routeTo("operationDetails", { wopid 
})}
+          onClose={() => navigateTo(privatePages.home.url({}))}
+          onAuthorizationRequired={() => 
navigateTo(privatePages.solveSecondFactor.url({}))}
+          onOperationCreated={(wopid) => 
navigateTo(privatePages.operationDetails.url({ wopid }))}
         />
       );
     }
     default:
-      assertUnreachable(loc.name);
+      assertUnreachable(location.name);
   }
 }
diff --git a/packages/demobank-ui/src/components/app.tsx 
b/packages/demobank-ui/src/components/app.tsx
index 31013388b..97778e6d7 100644
--- a/packages/demobank-ui/src/components/app.tsx
+++ b/packages/demobank-ui/src/components/app.tsx
@@ -30,6 +30,8 @@ import { SettingsProvider } from "../context/settings.js";
 import { strings } from "../i18n/strings.js";
 import { BankFrame } from "../pages/BankFrame.js";
 import { BankUiSettings, fetchSettings } from "../settings.js";
+import { TalerWalletIntegrationBrowserProvider } from 
"../context/wallet-integration.js";
+import { BrowserHashNavigationProvider } from "../context/navigation.js";
 const WITH_LOCAL_STORAGE_CACHE = false;
 
 const App: FunctionalComponent = () => {
@@ -78,7 +80,11 @@ const App: FunctionalComponent = () => {
                 keepPreviousData: true,
               }}
             >
-              <Routing />
+              <TalerWalletIntegrationBrowserProvider>
+                <BrowserHashNavigationProvider>
+                  <Routing />
+                </BrowserHashNavigationProvider>
+              </TalerWalletIntegrationBrowserProvider>
             </SWRConfig>
           </BankCoreApiProvider>
         </BackendStateProvider>
diff --git a/packages/demobank-ui/src/context/navigation.ts 
b/packages/demobank-ui/src/context/navigation.ts
new file mode 100644
index 000000000..fc1460c02
--- /dev/null
+++ b/packages/demobank-ui/src/context/navigation.ts
@@ -0,0 +1,80 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { ComponentChildren, createContext, h, VNode } from "preact";
+import { useContext, useEffect, useState } from "preact/hooks";
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+export type Type = {
+  path: string;
+  params: Record<string, string>;
+  navigateTo: (path: string) => void;
+  // addNavigationListener: (listener: (path: string, params: Record<string, 
string>) => void) => (() => void);
+};
+
+// @ts-expect-error shold not be used without provider
+const Context = createContext<Type>(undefined);
+
+export const useNavigationContext = (): Type => useContext(Context);
+
+function getPathAndParamsFromWindow() {
+  const path = typeof window !== "undefined" ? 
window.location.hash.substring(1) : "/";
+  const params: Record<string, string> = {}
+  if (typeof window !== "undefined") {
+    for (const [key, value] of new URLSearchParams(window.location.search)) {
+      params[key] = value;
+    }
+  }
+  return { path, params }
+}
+
+const { path: initialPath, params: initialParams } = 
getPathAndParamsFromWindow()
+
+// there is a posibility that if the browser does a redirection
+// (which doesn't go through navigatTo function) and that exectued
+// too early (before addEventListener runs) it won't be taking
+// into account
+const PopStateEventType = "popstate";
+
+export const BrowserHashNavigationProvider = ({ children }: { children: 
ComponentChildren }): VNode => {
+  const [{ path, params }, setState] = useState({ path: initialPath, params: 
initialParams })
+  if (typeof window === "undefined") {
+    throw Error("Can't use BrowserHashNavigationProvider if there is no window 
object")
+  }
+  function navigateTo(path: string) {
+    const { params } = getPathAndParamsFromWindow()
+    setState({ path, params })
+    window.location.href = path
+  }
+
+  useEffect(() => {
+    function eventListener() {
+      setState(getPathAndParamsFromWindow())
+    }
+    window.addEventListener(PopStateEventType, eventListener);
+    return () => {
+      window.removeEventListener(PopStateEventType, eventListener)
+    }
+  }, [])
+  return h(Context.Provider, {
+    value: { path, params, navigateTo },
+    children,
+  });
+};
diff --git a/packages/demobank-ui/src/context/wallet-integration.ts 
b/packages/demobank-ui/src/context/wallet-integration.ts
new file mode 100644
index 000000000..47bdc90ec
--- /dev/null
+++ b/packages/demobank-ui/src/context/wallet-integration.ts
@@ -0,0 +1,90 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import {
+  stringifyTalerUri,
+  TalerUri
+} from "@gnu-taler/taler-util";
+import {
+  ComponentChildren,
+  createContext,
+  h,
+  VNode
+} from "preact";
+import { useContext } from "preact/hooks";
+
+/**
+ * https://docs.taler.net/design-documents/039-taler-browser-integration.html
+ * 
+ * @param uri 
+ */
+function createHeadMetaTag(uri: TalerUri, onNotFound?: () => void) {
+
+  const meta = document.createElement("meta");
+  meta.setAttribute("name", "taler-uri");
+  meta.setAttribute("content", stringifyTalerUri(uri));
+
+  document.head.appendChild(meta);
+
+  let walletFound = false
+  window.addEventListener("beforeunload", () => {
+    walletFound = true
+  })
+  setTimeout(() => {
+    if (!walletFound && onNotFound) {
+      onNotFound()
+    }
+  }, 10)//very short timeout
+}
+interface Type {
+  /**
+   * Tell the active wallet that an action is found
+   * 
+   * @param uri 
+   * @returns 
+   */
+  publishTalerAction: (uri: TalerUri, onNotFound?: () => void) => void;
+}
+
+// @ts-expect-error default value to undefined, should it be another thing?
+const Context = createContext<Type>(undefined);
+
+export const useTalerWalletIntegrationAPI = (): Type => useContext(Context);
+
+export const TalerWalletIntegrationBrowserProvider = ({ children }: { 
children: ComponentChildren }): VNode => {
+  const value: Type = {
+    publishTalerAction: createHeadMetaTag
+  };
+  return h(Context.Provider, {
+    value,
+    children,
+  });
+};
+
+
+export const TalerWalletIntegrationTestingProvider = ({
+  children,
+  value,
+}: {
+  children: ComponentChildren;
+  value: Type;
+}): VNode => {
+
+  return h(Context.Provider, {
+    value,
+    children,
+  });
+};
diff --git a/packages/demobank-ui/src/index.html 
b/packages/demobank-ui/src/index.html
index 720b678a3..6e0638e3f 100644
--- a/packages/demobank-ui/src/index.html
+++ b/packages/demobank-ui/src/index.html
@@ -17,25 +17,25 @@
 -->
 <!doctype html>
 <html lang="en" class="h-full bg-gray-100">
-  <head>
-    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
-    <meta charset="utf-8" />
-    <meta name="viewport" content="width=device-width,initial-scale=1" />
-    <meta name="taler-support" content="uri" />
-    <meta name="mobile-web-app-capable" content="yes" />
-    <meta name="apple-mobile-web-app-capable" content="yes" />
-    <link
-      rel="icon"
-      
href="data:;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////////////7//v38//78/P/+/fz//vz7///+/v/+/f3//vz7///+/v/+/fz//v38///////////////////////+/v3///7+/////////////////////////////////////////////////////////v3//v79///////+/v3///////r28v/ct5//06SG/9Gffv/Xqo7/7N/V/9e2nf/bsJb/6uDW/9Sskf/euKH/+/j2///////+/v3//////+3azv+/eE3/2rWd/9Kkhv/Vr5T/48i2/8J+VP/
 [...]
-    />
-    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
-    <title>Bank</title>
-    <!-- Entry point for the bank SPA. -->
-    <script type="module" src="index.js"></script>
-    <link rel="stylesheet" href="index.css" />
-  </head>
 
-  <body class="h-full">
-    <div id="app"></div>
-  </body>
-</html>
+<head>
+  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+  <meta charset="utf-8" />
+  <meta name="viewport" content="width=device-width,initial-scale=1" />
+  <meta name="taler-support" content="uri,api" />
+  <meta name="mobile-web-app-capable" content="yes" />
+  <meta name="apple-mobile-web-app-capable" content="yes" />
+  <link rel="icon"
+    
href="data:;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////////////7//v38//78/P/+/fz//vz7///+/v/+/f3//vz7///+/v/+/fz//v38///////////////////////+/v3///7+/////////////////////////////////////////////////////////v3//v79///////+/v3///////r28v/ct5//06SG/9Gffv/Xqo7/7N/V/9e2nf/bsJb/6uDW/9Sskf/euKH/+/j2///////+/v3//////+3azv+/eE3/2rWd/9Kkhv/Vr5T/48i2/8J+VP/Qn
 [...]
+  <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
+  <title>Bank</title>
+  <!-- Entry point for the bank SPA. -->
+  <script type="module" src="index.js"></script>
+  <link rel="stylesheet" href="index.css" />
+</head>
+
+<body class="h-full">
+  <div id="app"></div>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/packages/demobank-ui/src/pages/OperationState/views.tsx 
b/packages/demobank-ui/src/pages/OperationState/views.tsx
index ac3724eb8..4d193505e 100644
--- a/packages/demobank-ui/src/pages/OperationState/views.tsx
+++ b/packages/demobank-ui/src/pages/OperationState/views.tsx
@@ -36,6 +36,7 @@ import { useBankState } from "../../hooks/bank-state.js";
 import { usePreferences } from "../../hooks/preferences.js";
 import { ShouldBeSameUser } from "../WithdrawalConfirmationQuestion.js";
 import { State } from "./index.js";
+import { useTalerWalletIntegrationAPI } from 
"../../context/wallet-integration.js";
 
 export function InvalidPaytoView({ payto }: State.InvalidPayto) {
   return <div>Payto from server is not valid &quot;{payto}&quot;</div>;
@@ -328,23 +329,12 @@ export function ReadyView({
   onAbort: doAbort,
 }: State.Ready): VNode<Record<string, never>> {
   const { i18n } = useTranslationContext();
+  const walletInegrationApi = useTalerWalletIntegrationAPI()
   const [notification, notify, errorHandler] = useLocalNotification();
 
   const talerWithdrawUri = stringifyWithdrawUri(uri);
   useEffect(() => {
-    // Taler Wallet WebExtension is listening to headers response and tab 
updates.
-    // In the SPA there is no header response with the Taler URI so
-    // this hack manually triggers the tab update after the QR is in the DOM.
-    // WebExtension will be using
-    // 
https://developer.chrome.com/docs/extensions/reference/tabs/#event-onUpdated
-    document.title = `${document.title} ${uri.withdrawalOperationId}`;
-    const meta = document.createElement("meta");
-    meta.setAttribute("name", "taler-uri");
-    meta.setAttribute("content", talerWithdrawUri);
-    document.head.insertBefore(
-      meta,
-      document.head.children.length ? document.head.children[0] : null,
-    );
+    walletInegrationApi.publishTalerAction(uri)
   }, []);
 
   async function onAbort() {
diff --git a/packages/demobank-ui/src/pages/PaymentOptions.tsx 
b/packages/demobank-ui/src/pages/PaymentOptions.tsx
index 53086d4cc..51a6a17a9 100644
--- a/packages/demobank-ui/src/pages/PaymentOptions.tsx
+++ b/packages/demobank-ui/src/pages/PaymentOptions.tsx
@@ -14,13 +14,43 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { AmountJson } from "@gnu-taler/taler-util";
-import { VNode, h } from "preact";
+import { AmountJson, TalerError } from "@gnu-taler/taler-util";
+import { Fragment, VNode, h } from "preact";
 import { useBankState } from "../hooks/bank-state.js";
 import { PaytoWireTransferForm } from "./PaytoWireTransferForm.js";
 import { WalletWithdrawForm } from "./WalletWithdrawForm.js";
 import { RouteDefinition } from "../route.js";
 import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { useWithdrawalDetails } from "../hooks/access.js";
+import { useEffect } from "preact/hooks";
+
+function ShowOperationPendingTag({ woid, onOperationAlreadyCompleted }: { 
woid: string, onOperationAlreadyCompleted?: () => void }): VNode {
+  const { i18n } = useTranslationContext();
+  const result = useWithdrawalDetails(woid);
+  const error = !result || result instanceof TalerError || result.type === 
"fail"
+  const completed = !error && (result.body.status === "aborted" || 
result.body.status === "confirmed")
+  useEffect(() => {
+    if (completed && onOperationAlreadyCompleted) {
+      onOperationAlreadyCompleted()
+    }
+  }, [completed])
+
+  if (error || completed) {
+    return <Fragment />;
+  }
+
+  return <span class="flex items-center gap-x-1.5 w-fit rounded-md 
bg-green-100 px-2 py-1 text-xs font-medium text-green-700 whitespace-pre">
+    <svg
+      class="h-1.5 w-1.5 fill-green-500"
+      viewBox="0 0 6 6"
+      aria-hidden="true"
+    >
+      <circle cx="3" cy="3" r="3" />
+    </svg>
+    <i18n.Translate>operation ready</i18n.Translate>
+  </span>
+
+}
 
 /**
  * Let the user choose a payment option,
@@ -46,7 +76,7 @@ export function PaymentOptions({
   routeWireTransfer: RouteDefinition<Record<string, never>>;
 }): VNode {
   const { i18n } = useTranslationContext();
-  const [bankState] = useBankState();
+  const [bankState, updateBankState] = useBankState();
 
   return (
     <div class="mt-4">
@@ -98,16 +128,9 @@ export function PaymentOptions({
                   </i18n.Translate>
                 </div>
                 {!!bankState.currentWithdrawalOperationId && (
-                  <span class="flex items-center gap-x-1.5 w-fit rounded-md 
bg-green-100 px-2 py-1 text-xs font-medium text-green-700 whitespace-pre">
-                    <svg
-                      class="h-1.5 w-1.5 fill-green-500"
-                      viewBox="0 0 6 6"
-                      aria-hidden="true"
-                    >
-                      <circle cx="3" cy="3" r="3" />
-                    </svg>
-                    <i18n.Translate>operation ready</i18n.Translate>
-                  </span>
+                  <ShowOperationPendingTag 
woid={bankState.currentWithdrawalOperationId} onOperationAlreadyCompleted={() 
=> {
+                    updateBankState("currentWithdrawalOperationId", undefined)
+                  }} />
                 )}
               </div>
             </label>
diff --git a/packages/demobank-ui/src/pages/ProfileNavigation.tsx 
b/packages/demobank-ui/src/pages/ProfileNavigation.tsx
index a6615d578..02f30d8e8 100644
--- a/packages/demobank-ui/src/pages/ProfileNavigation.tsx
+++ b/packages/demobank-ui/src/pages/ProfileNavigation.tsx
@@ -19,6 +19,7 @@ import { privatePages } from "../Routing.js";
 import { useBankCoreApiContext } from "../context/config.js";
 import { useBackendState } from "../hooks/backend.js";
 import { assertUnreachable } from "@gnu-taler/taler-util";
+import { useNavigationContext } from "../context/navigation.js";
 
 export function ProfileNavigation({
   current,
@@ -32,6 +33,7 @@ export function ProfileNavigation({
     credentials.status !== "loggedIn"
       ? false
       : !credentials.isUserAdministrator;
+  const { navigateTo } = useNavigationContext()
   return (
     <div>
       <div class="sm:hidden">
@@ -46,19 +48,19 @@ export function ProfileNavigation({
             const op = e.currentTarget.value as typeof current;
             switch (op) {
               case "details": {
-                window.location.href = privatePages.myAccountDetails.url({});
+                navigateTo(privatePages.myAccountDetails.url({}));
                 return;
               }
               case "delete": {
-                window.location.href = privatePages.myAccountDelete.url({});
+                navigateTo(privatePages.myAccountDelete.url({}));
                 return;
               }
               case "credentials": {
-                window.location.href = privatePages.myAccountPassword.url({});
+                navigateTo(privatePages.myAccountPassword.url({}));
                 return;
               }
               case "cashouts": {
-                window.location.href = privatePages.myAccountCashouts.url({});
+                navigateTo(privatePages.myAccountCashouts.url({}));
                 return;
               }
               default:
diff --git a/packages/demobank-ui/src/pages/QrCodeSection.tsx 
b/packages/demobank-ui/src/pages/QrCodeSection.tsx
index f21134aa1..037849804 100644
--- a/packages/demobank-ui/src/pages/QrCodeSection.tsx
+++ b/packages/demobank-ui/src/pages/QrCodeSection.tsx
@@ -19,7 +19,7 @@ import {
   HttpStatusCode,
   stringifyWithdrawUri,
   TranslatedString,
-  WithdrawUriResult,
+  WithdrawUriResult
 } from "@gnu-taler/taler-util";
 import {
   LocalNotificationBanner,
@@ -30,6 +30,7 @@ import { Fragment, h, VNode } from "preact";
 import { useEffect } from "preact/hooks";
 import { QR } from "../components/QR.js";
 import { useBankCoreApiContext } from "../context/config.js";
+import { useTalerWalletIntegrationAPI } from 
"../context/wallet-integration.js";
 import { useBackendState } from "../hooks/backend.js";
 
 export function QrCodeSection({
@@ -40,25 +41,15 @@ export function QrCodeSection({
   onAborted: () => void;
 }): VNode {
   const { i18n } = useTranslationContext();
+  const walletInegrationApi = useTalerWalletIntegrationAPI()
   const talerWithdrawUri = stringifyWithdrawUri(withdrawUri);
   const { state: credentials } = useBackendState();
   const creds = credentials.status !== "loggedIn" ? undefined : credentials;
 
   useEffect(() => {
-    // Taler Wallet WebExtension is listening to headers response and tab 
updates.
-    // In the SPA there is no header response with the Taler URI so
-    // this hack manually triggers the tab update after the QR is in the DOM.
-    // WebExtension will be using
-    // 
https://developer.chrome.com/docs/extensions/reference/tabs/#event-onUpdated
-    document.title = `${document.title} ${withdrawUri.withdrawalOperationId}`;
-    const meta = document.createElement("meta");
-    meta.setAttribute("name", "taler-uri");
-    meta.setAttribute("content", talerWithdrawUri);
-    document.head.insertBefore(
-      meta,
-      document.head.children.length ? document.head.children[0] : null,
-    );
+    walletInegrationApi.publishTalerAction(withdrawUri)
   }, []);
+
   const [notification, notify, handleError] = useLocalNotification();
 
   const { api } = useBankCoreApiContext();
diff --git a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx 
b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
index 1e48b818a..9f7f46c4f 100644
--- a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
+++ b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
@@ -21,6 +21,7 @@ import {
   TranslatedString,
   assertUnreachable,
   parseWithdrawUri,
+  stringifyWithdrawUri,
 } from "@gnu-taler/taler-util";
 import {
   Attention,
@@ -41,6 +42,8 @@ import { RouteDefinition } from "../route.js";
 import { undefinedIfEmpty } from "../utils.js";
 import { OperationState } from "./OperationState/index.js";
 import { InputAmount, doAutoFocus } from "./PaytoWireTransferForm.js";
+import { useTalerWalletIntegrationAPI } from 
"../context/wallet-integration.js";
+import { useNavigationContext } from "../context/navigation.js";
 
 const RefAmount = forwardRef(InputAmount);
 
@@ -57,18 +60,32 @@ function OldWithdrawalForm({
 }): VNode {
   const { i18n } = useTranslationContext();
   const [settings] = usePreferences();
+
+  // const walletInegrationApi = useTalerWalletIntegrationAPI()
+  // const { navigateTo } = useNavigationContext();
+
   const [bankState, updateBankState] = useBankState();
+  const { api } = useBankCoreApiContext();
 
   const { state: credentials } = useBackendState();
   const creds = credentials.status !== "loggedIn" ? undefined : credentials;
 
-  const { api } = useBankCoreApiContext();
   const [amountStr, setAmountStr] = useState<string | undefined>(
     `${settings.maxWithdrawalAmount}`,
   );
   const [notification, notify, handleError] = useLocalNotification();
 
   if (bankState.currentWithdrawalOperationId) {
+    // FIXME: doing the preventDefault is not optimal
+
+    // const suri = stringifyWithdrawUri({
+    //   bankIntegrationApiBaseUrl: api.getIntegrationAPI().baseUrl,
+    //   withdrawalOperationId: bankState.currentWithdrawalOperationId,
+    // });
+    // const uri = parseWithdrawUri(suri)!
+    const url = privatePages.operationDetails.url({
+      wopid: bankState.currentWithdrawalOperationId,
+    })
     return (
       <Attention type="warning" title={i18n.str`There is an operation 
already`}>
         <span ref={focus ? doAutoFocus : undefined} />
@@ -77,9 +94,13 @@ function OldWithdrawalForm({
         </i18n.Translate>{" "}
         <a
           class="font-semibold text-yellow-700 hover:text-yellow-600"
-          href={privatePages.operationDetails.url({
-            wopid: bankState.currentWithdrawalOperationId,
-          })}
+          href={url}
+        // onClick={(e) => {
+        //   e.preventDefault()
+        //   walletInegrationApi.publishTalerAction(uri, () => {
+        //     navigateTo(url)
+        //   })
+        // }}
         >
           <i18n.Translate>this page</i18n.Translate>
         </a>
@@ -324,7 +345,7 @@ export function WalletWithdrawForm({
             onAuthorizationRequired={onAuthorizationRequired}
             routeClose={routeCancel}
             onAbort={onOperationAborted}
-            // route={routeCancel}
+          // route={routeCancel}
           />
         )}
       </div>
diff --git a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx 
b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
index 3cf552f39..03f6556af 100644
--- a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
@@ -75,29 +75,39 @@ export function WithdrawalQRCode({
 
   if (data.status === "aborted") {
     return (
-      <section id="main" class="content">
-        <h1 class="nav">{i18n.str`Operation aborted`}</h1>
-        <section>
-          <p>
-            <i18n.Translate>
-              The wire transfer to the Taler Exchange operator's account was
-              aborted, your balance was not affected.
-            </i18n.Translate>
-          </p>
-          <p>
-            <i18n.Translate>
-              You can close this page now or continue to the account page.
-            </i18n.Translate>
-          </p>
+      <div class="relative ml-auto mr-auto transform overflow-hidden 
rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 
sm:w-full sm:max-w-sm sm:p-6">
+        <div>
+          <div class="mx-auto flex h-12 w-12 items-center justify-center 
rounded-full bg-yellow-100">
+            <svg class="h-5 w-5 text-yellow-400" viewBox="0 0 20 20" 
fill="currentColor" aria-hidden="true">
+              <path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 
3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 
0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 
01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" 
clip-rule="evenodd" />
+            </svg>
+          </div>
+          <div class="mt-3 text-center sm:mt-5">
+            <h3
+              class="text-base font-semibold leading-6 text-gray-900"
+              id="modal-title"
+            >
+              <i18n.Translate>Operation aborted</i18n.Translate>
+            </h3>
+            <div class="mt-2">
+              <p class="text-sm text-gray-500">
+                <i18n.Translate>
+                  The wire transfer to the Taler Exchange operator's account 
was
+                  aborted from somewhere else, your balance was not affected.
+                </i18n.Translate>
+              </p>
+            </div>
+          </div>
+        </div>
+        <div class="mt-5 sm:mt-6">
           <a
             href={routeClose.url({})}
-            class="pure-button pure-button-primary"
-            style={{ float: "right" }}
+            class="inline-flex w-full justify-center rounded-md bg-indigo-600 
px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 
focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 
focus-visible:outline-indigo-600"
           >
             <i18n.Translate>Continue</i18n.Translate>
           </a>
-        </section>
-      </section>
+        </div>
+      </div>
     );
   }
 
diff --git a/packages/demobank-ui/src/pages/business/CreateCashout.tsx 
b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
index 75e0a9b84..46da5c847 100644
--- a/packages/demobank-ui/src/pages/business/CreateCashout.tsx
+++ b/packages/demobank-ui/src/pages/business/CreateCashout.tsx
@@ -316,7 +316,7 @@ export function CreateCashout({
   const cashoutDisabled =
     config.supported_tan_channels.length < 1 ||
     !resultAccount.body.cashout_payto_uri;
-  console.log("disab", cashoutDisabled);
+
   const cashoutAccount = !resultAccount.body.cashout_payto_uri
     ? undefined
     : parsePaytoUri(resultAccount.body.cashout_payto_uri);
diff --git a/packages/demobank-ui/src/route.ts 
b/packages/demobank-ui/src/route.ts
index 72b405791..912ba274d 100644
--- a/packages/demobank-ui/src/route.ts
+++ b/packages/demobank-ui/src/route.ts
@@ -13,7 +13,7 @@
  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 { useEffect, useState } from "preact/hooks";
+import { useNavigationContext } from "./context/navigation.js";
 
 export function urlPattern<
   T extends Record<string, string> = Record<string, never>,
@@ -24,29 +24,6 @@ export function urlPattern<
   };
 }
 
-// export function Router({
-//   pageList,
-//   onNotFound,
-// }: {
-//   pageList: Array<PageEntry<unknown>>;
-//   onNotFound: () => VNode;
-// }): VNode {
-//   const current = useCurrentLocation<unknown>(pageList);
-//   if (current !== undefined) {
-//     const d = current.page.url
-//     if (typeof current.page.url === "string") {
-//       const p = current.page.url
-//       return create(current.page.view, {});
-//     }
-//     const p = current.page.url
-//     return create(current.page.view, current.values);
-//   }
-//   return onNotFound();
-// }
-// type PagesMap<T extends object> = {
-//   [name in keyof T]: PageDefinition<any>;
-// };
-
 export type RouteDefinition<T> = {
   pattern: RegExp;
   url: (p: T) => string;
@@ -72,17 +49,9 @@ export type RouteParamsType<
 type Location<E, T extends RouteMap<E>, NAME extends keyof T> = {
   parent: T;
   name: NAME;
-  // mapped values from params and url
   values: RouteParamsType<T, NAME>;
 };
 
-const STARTUP_SPA_LOCATION =
-  typeof window !== "undefined" ? window.location.hash.substring(1) : "/";
-const STARTUP_SPA_PARAMS =
-  typeof window !== "undefined"
-    ? new URLSearchParams(window.location.search)
-    : new URLSearchParams();
-
 /**
  * Search path in the pageList
  * get the values from the path found
@@ -91,11 +60,11 @@ const STARTUP_SPA_PARAMS =
  * @param path
  * @param params
  */
-function doSync<DEF, RM extends RouteMap<DEF>, ROUTES extends keyof RM>(
+function findMatch<DEF, RM extends RouteMap<DEF>, ROUTES extends keyof RM>(
   pagesMap: RM,
   pageList: Array<ROUTES>,
   path: string,
-  params: URLSearchParams,
+  params: Record<string, string>,
 ): Location<DEF, RM, ROUTES> | undefined {
   for (let idx = 0; idx < pageList.length; idx++) {
     const name = pageList[idx];
@@ -103,9 +72,10 @@ function doSync<DEF, RM extends RouteMap<DEF>, ROUTES 
extends keyof RM>(
     if (found !== null) {
       const values =
         found.groups === undefined ? {} : structuredClone(found.groups);
-      params.forEach((v, k) => {
-        values[k] = v;
-      });
+
+      Object.entries(params).forEach(([key, value]) => {
+        values[key] = value
+      })
 
       // @ts-expect-error values is a map string which is equivalent to the 
RouteParamsType
       return { name, parent: pagesMap, values };
@@ -114,87 +84,13 @@ function doSync<DEF, RM extends RouteMap<DEF>, ROUTES 
extends keyof RM>(
   return undefined;
 }
 
-const PopStateEventType = "popstate";
-
 export function useCurrentLocation<
   DEF,
   RM extends RouteMap<DEF>,
   ROUTES extends keyof RM,
 >(pagesMap: RM) {
   const pageList = Object.keys(pagesMap) as Array<ROUTES>;
-  const [currentLocation, setCurrentLocation] = useState<
-    Location<DEF, RM, ROUTES> | undefined
-  >(doSync(pagesMap, pageList, STARTUP_SPA_LOCATION, STARTUP_SPA_PARAMS));
-  useEffect(() => {
-    window.addEventListener(PopStateEventType, () => {
-      const path = window.location.hash.substring(1);
-      console.log("event", path);
-      const l = doSync(
-        pagesMap,
-        pageList,
-        path,
-        new URLSearchParams(window.location.search),
-      );
-      setCurrentLocation(l);
-    });
-  }, []);
-  function routeTo<N extends ROUTES>(
-    n: N,
-    values: RouteParamsType<RM, N>,
-  ): void {
-    setCurrentLocation({
-      parent: pagesMap,
-      name: n,
-      values,
-    });
-  }
-  return [currentLocation, routeTo] as const;
-}
-
-// function doestUrlMatchToRoute(
-//   url: string,
-//   route: string,
-// ): undefined | Record<string, string> {
-//   const paramsPattern = /(?:\?([^#]*))?$/;
+  const { path, params } = useNavigationContext()
 
-//   const urlSeg = url.replace(paramsPattern, "").split("/");
-//   const routeSeg = route.split("/");
-//   let max = Math.max(urlSeg.length, routeSeg.length);
-
-//   const result: Record<string, string> = {};
-//   for (let i = 0; i < max; i++) {
-//     if (routeSeg[i] && routeSeg[i].charAt(0) === ":") {
-//       const param = routeSeg[i].replace(/(^:|[+*?]+$)/g, "");
-
-//       const flags = (routeSeg[i].match(/[+*?]+$/) || EMPTY)[0] || "";
-//       const plus = ~flags.indexOf("+");
-//       const star = ~flags.indexOf("*");
-//       const val = urlSeg[i] || "";
-
-//       if (!val && !star && (flags.indexOf("?") < 0 || plus)) {
-//         return undefined;
-//       }
-//       result[param] = decodeURIComponent(val);
-//       if (plus || star) {
-//         result[param] = urlSeg.slice(i).map(decodeURIComponent).join("/");
-//         break;
-//       }
-//     } else if (routeSeg[i] !== urlSeg[i]) {
-//       return undefined;
-//     }
-//   }
-
-//   const params = url.match(paramsPattern);
-//   if (params && params[1]) {
-//     const paramList = params[1].split("&");
-//     for (let i = 0; i < paramList.length; i++) {
-//       const idx = paramList[i].indexOf("=");
-//       const name = paramList[i].substring(0, idx);
-//       const value = paramList[i].substring(idx + 1);
-//       result[decodeURIComponent(name)] = decodeURIComponent(value);
-//     }
-//   }
-
-//   return result;
-// }
-// const EMPTY: Record<string, string> = {};
+  return findMatch(pagesMap, pageList, path, params);
+}
diff --git a/packages/taler-util/src/taleruri.test.ts 
b/packages/taler-util/src/taleruri.test.ts
index 208beebbb..4ed97cec2 100644
--- a/packages/taler-util/src/taleruri.test.ts
+++ b/packages/taler-util/src/taleruri.test.ts
@@ -237,7 +237,7 @@ test("taler reward pickup uri", (t) => {
 });
 
 test("taler reward pickup uri with instance", (t) => {
-  const url1 = "taler://reward/merchant.example.com/instances/tipm/tipid";
+  const url1 = "taler://reward/merchant.example.com/instances/tipm/tipid/";
   const r1 = parseRewardUri(url1);
   if (!r1) {
     t.fail();
@@ -248,7 +248,7 @@ test("taler reward pickup uri with instance", (t) => {
 });
 
 test("taler reward pickup uri with instance and prefix", (t) => {
-  const url1 = "taler://reward/merchant.example.com/my/pfx/tipm/tipid";
+  const url1 = "taler://reward/merchant.example.com/my/pfx/tipm/tipid/";
   const r1 = parseRewardUri(url1);
   if (!r1) {
     t.fail();
diff --git a/packages/taler-util/src/taleruri.ts 
b/packages/taler-util/src/taleruri.ts
index 8f37dfe76..22846c7a4 100644
--- a/packages/taler-util/src/taleruri.ts
+++ b/packages/taler-util/src/taleruri.ts
@@ -438,8 +438,9 @@ export function parseRewardUri(s: string): RewardUriResult 
| undefined {
     return undefined;
   }
   const host = parts[0].toLowerCase();
-  const rewardId = parts[parts.length - 1];
-  const pathSegments = parts.slice(1, parts.length - 1);
+  const unused = parts[parts.length - 1];
+  const rewardId = parts[parts.length - 2];
+  const pathSegments = parts.slice(1, parts.length - 2);
   const hostAndSegments = [host, ...pathSegments].join("/");
   const merchantBaseUrl = canonicalizeBaseUrl(
     `${pi.innerProto}://${hostAndSegments}/`,
diff --git a/packages/taler-wallet-webextension/manifest-v2.json 
b/packages/taler-wallet-webextension/manifest-v2.json
index 3475cd8aa..6f2096b05 100644
--- a/packages/taler-wallet-webextension/manifest-v2.json
+++ b/packages/taler-wallet-webextension/manifest-v2.json
@@ -18,7 +18,6 @@
   "permissions": [
     "unlimitedStorage",
     "storage",
-    "webRequest",
     "<all_urls>",
     "activeTab"
   ],
diff --git a/packages/taler-wallet-webextension/manifest-v3.json 
b/packages/taler-wallet-webextension/manifest-v3.json
index d6a303ed6..65a75824b 100644
--- a/packages/taler-wallet-webextension/manifest-v3.json
+++ b/packages/taler-wallet-webextension/manifest-v3.json
@@ -17,7 +17,6 @@
     "storage",
     "activeTab",
     "scripting",
-    "webRequest",
     "declarativeContent",
     "alarms"
   ],
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx 
b/packages/taler-wallet-webextension/src/NavigationBar.tsx
index 167f1797c..97b1fbcde 100644
--- a/packages/taler-wallet-webextension/src/NavigationBar.tsx
+++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx
@@ -126,6 +126,7 @@ export const Pages = {
   ctaRecovery: "/cta/recovery",
   ctaRefund: "/cta/refund",
   ctaTips: "/cta/tip",
+  ctaRewards: "/cta/rewards",
   ctaWithdraw: "/cta/withdraw",
   ctaDeposit: "/cta/deposit",
   ctaInvoiceCreate: pageDefinition<{ amount?: string }>(
@@ -146,7 +147,7 @@ const talerUriActionToPageName: {
 } = {
   [TalerUriAction.Withdraw]: "ctaWithdraw",
   [TalerUriAction.Pay]: "ctaPay",
-  [TalerUriAction.Reward]: "ctaTips",
+  [TalerUriAction.Reward]: "ctaRewards",
   [TalerUriAction.Refund]: "ctaRefund",
   [TalerUriAction.PayPull]: "ctaInvoicePay",
   [TalerUriAction.PayPush]: "ctaTransferPickup",
diff --git a/packages/taler-wallet-webextension/src/platform/api.ts 
b/packages/taler-wallet-webextension/src/platform/api.ts
index a2b26441b..c7d297db9 100644
--- a/packages/taler-wallet-webextension/src/platform/api.ts
+++ b/packages/taler-wallet-webextension/src/platform/api.ts
@@ -46,20 +46,32 @@ export interface Permissions {
  * Compatibility API that works on multiple browsers.
  */
 export interface CrossBrowserPermissionsApi {
-  containsHostPermissions(): Promise<boolean>;
-  requestHostPermissions(): Promise<boolean>;
-  removeHostPermissions(): Promise<boolean>;
 
   containsClipboardPermissions(): Promise<boolean>;
   requestClipboardPermissions(): Promise<boolean>;
   removeClipboardPermissions(): Promise<boolean>;
 
-  addPermissionsListener(
-    callback: (p: Permissions, lastError?: string) => void,
-  ): void;
 }
 
-export type MessageFromBackend = WalletNotification;
+export enum ExtensionNotificationType {
+  SettingsChange = "settings-change",
+}
+
+export interface SettingsChangeNotification {
+  type: ExtensionNotificationType.SettingsChange;
+
+  currentValue: Settings;
+}
+
+export type ExtensionNotification = SettingsChangeNotification
+
+export type MessageFromBackend = {
+  type: "wallet",
+  notification: WalletNotification
+} | {
+  type: "web-extension",
+  notification: ExtensionNotification
+};
 
 export type MessageFromFrontend<
   Op extends BackgroundOperations | WalletOperations | ExtensionOperations,
@@ -110,7 +122,7 @@ export interface Settings extends WebexWalletConfig {
 }
 
 export const defaultSettings: Settings = {
-  injectTalerSupport: true,
+  injectTalerSupport: false,
   autoOpen: true,
   advanceMode: false,
   backup: false,
@@ -207,13 +219,6 @@ export interface BackgroundPlatformAPI {
     ) => Promise<MessageResponse>,
   ): void;
 
-  /**
-   * Use by the wallet backend to activate the listener of HTTP request
-   */
-  registerTalerHeaderListener(): void;
-
-  containsTalerHeaderListener(): boolean;
-
 }
 export interface ForegroundPlatformAPI {
   /**
diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts 
b/packages/taler-wallet-webextension/src/platform/chrome.ts
index 68fa63474..d791a560f 100644
--- a/packages/taler-wallet-webextension/src/platform/chrome.ts
+++ b/packages/taler-wallet-webextension/src/platform/chrome.ts
@@ -28,6 +28,7 @@ import { BackgroundOperations } from "../wxApi.js";
 import {
   BackgroundPlatformAPI,
   CrossBrowserPermissionsApi,
+  ExtensionNotificationType,
   ForegroundPlatformAPI,
   MessageFromBackend,
   MessageFromFrontend,
@@ -60,27 +61,31 @@ const api: BackgroundPlatformAPI & ForegroundPlatformAPI = {
   useServiceWorkerAsBackgroundProcess,
   keepAlive,
   listenNetworkConnectionState,
-  registerTalerHeaderListener,
-  containsTalerHeaderListener,
 };
 
 export default api;
 
 const logger = new Logger("chrome.ts");
 
-async function getSettingsFromStorage(): Promise<Settings> {
-  const data = await chrome.storage.local.get("wallet-settings");
-  if (!data) return defaultSettings;
-  const settings = data["wallet-settings"];
-  if (!settings) return defaultSettings;
+
+const WALLET_STORAGE_KEY = "wallet-settings";
+
+function jsonParseOrDefault(unparsed: any, def: any) {
+  if (!unparsed) return def
   try {
-    const parsed = JSON.parse(settings);
-    return parsed;
+    return JSON.parse(unparsed);
   } catch (e) {
-    return defaultSettings;
+    return def;
   }
 }
 
+async function getSettingsFromStorage(): Promise<Settings> {
+  const data = await chrome.storage.local.get(WALLET_STORAGE_KEY);
+  if (!data) return defaultSettings;
+  const settings = data[WALLET_STORAGE_KEY];
+  return jsonParseOrDefault(settings, defaultSettings)
+}
+
 function keepAlive(callback: any): void {
   if (extensionIsManifestV3()) {
     chrome.alarms.create("wallet-worker", { periodInMinutes: 1 });
@@ -140,21 +145,8 @@ export function removeClipboardPermissions(): 
Promise<boolean> {
   });
 }
 
-function addPermissionsListener(
-  callback: (p: Permissions, lastError?: string) => void,
-): void {
-  chrome.permissions.onAdded.addListener((perm: Permissions) => {
-    const lastError = chrome.runtime.lastError?.message;
-    callback(perm, lastError);
-  });
-}
-
 function getPermissionsApi(): CrossBrowserPermissionsApi {
   return {
-    containsHostPermissions,
-    requestHostPermissions,
-    removeHostPermissions,
-    addPermissionsListener,
     requestClipboardPermissions,
     removeClipboardPermissions,
     containsClipboardPermissions,
@@ -207,7 +199,7 @@ function openWalletURIFromPopup(uri: TalerUri): void {
       break;
     case TalerUriAction.Reward:
       url = chrome.runtime.getURL(
-        `static/wallet.html#/cta/tip?talerUri=${encodeURIComponent(talerUri)}`,
+        
`static/wallet.html#/cta/rewards?talerUri=${encodeURIComponent(talerUri)}`,
       );
       break;
     case TalerUriAction.Refund:
@@ -363,6 +355,18 @@ function registerAllIncomingConnections(): void {
       logger.error("error trying to save incoming connection", e);
     }
   });
+  chrome.storage.onChanged.addListener((event) => {
+    if (event[WALLET_STORAGE_KEY]) {
+      sendMessageToAllChannels({
+        type: "web-extension",
+        notification: {
+          type: ExtensionNotificationType.SettingsChange,
+          currentValue: jsonParseOrDefault(event[WALLET_STORAGE_KEY], 
defaultSettings)
+        }
+      })
+    }
+  })
+
 }
 
 function listenToAllChannels(
@@ -723,253 +727,3 @@ function listenNetworkConnectionState(
   };
 }
 
-type HeaderListenerFunc = (
-  details: chrome.webRequest.WebResponseHeadersDetails,
-) => void;
-let currentHeaderListener: HeaderListenerFunc | undefined = undefined;
-
-// type TabListenerFunc = (tabId: number, info: chrome.tabs.TabChangeInfo) => 
void;
-// let currentTabListener: TabListenerFunc | undefined = undefined;
-
-
-function containsTalerHeaderListener(): boolean {
-  return (
-    currentHeaderListener !== undefined
-    // || currentTabListener !== undefined
-  );
-}
-
-function headerListener(
-  details: chrome.webRequest.WebResponseHeadersDetails,
-): chrome.webRequest.BlockingResponse | undefined {
-  logger.trace("header listener run", details.statusCode, 
chrome.runtime.lastError)
-  if (chrome.runtime.lastError) {
-    logger.error(JSON.stringify(chrome.runtime.lastError));
-    return;
-  }
-
-  if (
-    details.statusCode === 402 ||
-    details.statusCode === 202 ||
-    details.statusCode === 200
-  ) {
-    const values = (details.responseHeaders || [])
-      .filter((h) => h.name.toLowerCase() === "taler")
-      .map((h) => h.value)
-      .filter((value): value is string => !!value);
-
-    const talerUri = values.length > 0 ? values[0] : undefined
-    if (talerUri) {
-      logger.info(
-        `Found a Taler URI in a response header for the request ${details.url} 
from tab ${details.tabId}: ${talerUri}`,
-      );
-      parseTalerUriAndRedirect(details.tabId, talerUri);
-      return;
-    }
-  }
-  return details;
-}
-function parseTalerUriAndRedirect(tabId: number, maybeTalerUri: string): void {
-  const talerUri = maybeTalerUri.startsWith("ext+")
-    ? maybeTalerUri.substring(4)
-    : maybeTalerUri;
-  const uri = parseTalerUri(talerUri);
-  if (!uri) {
-    logger.warn(
-      `Response with HTTP 402 the Taler header but could not classify 
${talerUri}`,
-    );
-    return;
-  }
-  redirectTabToWalletPage(
-    tabId,
-    `/taler-uri/${encodeURIComponent(talerUri)}`,
-  );
-}
-
-/**
- * Not needed anymore since SPA use taler support
- */
-
-// async function tabListener(
-//   tabId: number,
-//   info: chrome.tabs.TabChangeInfo,
-// ): Promise<void> {
-//   if (tabId < 0) return;
-//   const tabLocationHasBeenUpdated = info.status === "complete";
-//   const tabTitleHasBeenUpdated = info.title !== undefined;
-//   if (tabLocationHasBeenUpdated || tabTitleHasBeenUpdated) {
-//     const uri = await findTalerUriInTab(tabId);
-//     if (!uri) return;
-//     logger.info(`Found a Taler URI in the tab ${tabId}`);
-//     parseTalerUriAndRedirect(tabId, uri);
-//   }
-// }
-
-/**
- * unused, declarative redirect is not good enough
- *
- */
-// async function registerDeclarativeRedirect() {
-//   await chrome.declarativeNetRequest.updateDynamicRules({
-//     removeRuleIds: [1],
-//     addRules: [
-//       {
-//         id: 1,
-//         priority: 1,
-//         condition: {
-//           urlFilter: "https://developer.chrome.com/docs/extensions/mv2/";,
-//           regexFilter: ".*taler_uri=([^&]*).*",
-//           // isUrlFilterCaseSensitive: false,
-//           // requestMethods: 
[chrome.declarativeNetRequest.RequestMethod.GET]
-//           // resourceTypes: 
[chrome.declarativeNetRequest.ResourceType.MAIN_FRAME],
-//         },
-//         action: {
-//           type: chrome.declarativeNetRequest.RuleActionType.REDIRECT,
-//           redirect: {
-//             regexSubstitution: 
`chrome-extension://${chrome.runtime.id}/static/wallet.html?action=\\1`,
-//           },
-//         },
-//       },
-//     ],
-//   });
-// }
-
-function registerTalerHeaderListener(): void {
-  logger.info("setting up header listener");
-
-  const prevHeaderListener = currentHeaderListener;
-  // const prevTabListener = currentTabListener;
-
-  if (
-    prevHeaderListener &&
-    chrome?.webRequest?.onHeadersReceived?.hasListener(prevHeaderListener)
-  ) {
-    return;
-    // console.log("removming on header listener")
-    // chrome.webRequest.onHeadersReceived.removeListener(prevHeaderListener);
-    // chrome.webRequest.onCompleted.removeListener(prevHeaderListener);
-    // chrome.webRequest.onResponseStarted.removeListener(prevHeaderListener);
-    // chrome.webRequest.onErrorOccurred.removeListener(prevHeaderListener);
-  }
-
-  // if (
-  //   prevTabListener &&
-  //   chrome?.tabs?.onUpdated?.hasListener(prevTabListener)
-  // ) {
-  //   console.log("removming on tab listener")
-  //   chrome.tabs.onUpdated.removeListener(prevTabListener);
-  // }
-
-  console.log("headers on, disabled:", chrome?.webRequest?.onHeadersReceived 
=== undefined)
-  if (chrome?.webRequest) {
-    if (extensionIsManifestV3()) {
-      chrome.webRequest.onHeadersReceived.addListener(headerListener,
-        { urls: ["<all_urls>"] },
-        ["responseHeaders"]
-      );
-    } else {
-      chrome.webRequest.onHeadersReceived.addListener(headerListener,
-        { urls: ["<all_urls>"] },
-        ["responseHeaders"]
-      );
-    }
-    // chrome.webRequest.onCompleted.addListener(headerListener,
-    //   { urls: ["<all_urls>"] },
-    //   ["responseHeaders", "extraHeaders"]
-    // );
-    // chrome.webRequest.onResponseStarted.addListener(headerListener,
-    //   { urls: ["<all_urls>"] },
-    //   ["responseHeaders", "extraHeaders"]
-    // );
-    // chrome.webRequest.onErrorOccurred.addListener(headerListener,
-    //   { urls: ["<all_urls>"] },
-    //   ["extraHeaders"]
-    // );
-    currentHeaderListener = headerListener;
-  }
-
-  // const tabsEvent: chrome.tabs.TabUpdatedEvent | undefined =
-  //   chrome?.tabs?.onUpdated;
-  // if (tabsEvent) {
-  //   tabsEvent.addListener(tabListener);
-  //   currentTabListener = tabListener;
-  // }
-
-  //notify the browser about this change, this operation is expensive
-  chrome?.webRequest?.handlerBehaviorChanged(() => {
-    if (chrome.runtime.lastError) {
-      logger.error(JSON.stringify(chrome.runtime.lastError));
-    }
-  });
-}
-
-const hostPermissions = {
-  permissions: ["webRequest"],
-  origins: ["http://*/*";, "https://*/*";],
-};
-
-export function containsHostPermissions(): Promise<boolean> {
-  return new Promise((res, rej) => {
-    chrome.permissions.contains(hostPermissions, (resp) => {
-      const le = chrome.runtime.lastError?.message;
-      if (le) {
-        rej(le);
-      }
-      res(resp);
-    });
-  });
-}
-
-export async function requestHostPermissions(): Promise<boolean> {
-  return new Promise((res, rej) => {
-    chrome.permissions.request(hostPermissions, (resp) => {
-      const le = chrome.runtime.lastError?.message;
-      if (le) {
-        rej(le);
-      }
-      res(resp);
-    });
-  });
-}
-
-export async function removeHostPermissions(): Promise<boolean> {
-  //if there is a handler already, remove it
-  if (
-    currentHeaderListener &&
-    chrome?.webRequest?.onHeadersReceived?.hasListener(currentHeaderListener)
-  ) {
-    chrome.webRequest.onHeadersReceived.removeListener(currentHeaderListener);
-  }
-  // if (
-  //   currentTabListener &&
-  //   chrome?.tabs?.onUpdated?.hasListener(currentTabListener)
-  // ) {
-  //   chrome.tabs.onUpdated.removeListener(currentTabListener);
-  // }
-
-  currentHeaderListener = undefined;
-  // currentTabListener = undefined;
-
-  //notify the browser about this change, this operation is expensive
-  if ("webRequest" in chrome) {
-    chrome.webRequest.handlerBehaviorChanged(() => {
-      if (chrome.runtime.lastError) {
-        logger.error(JSON.stringify(chrome.runtime.lastError));
-      }
-    });
-  }
-
-  if (extensionIsManifestV3()) {
-    // Trying to remove host permissions with manifest >= v3 throws an error
-    return true;
-  }
-  return new Promise((res, rej) => {
-    chrome.permissions.remove(hostPermissions, (resp) => {
-      const le = chrome.runtime.lastError?.message;
-      if (le) {
-        rej(le);
-      }
-      res(resp);
-    });
-  });
-}
\ No newline at end of file
diff --git a/packages/taler-wallet-webextension/src/platform/dev.ts 
b/packages/taler-wallet-webextension/src/platform/dev.ts
index 51744e318..2993c88bc 100644
--- a/packages/taler-wallet-webextension/src/platform/dev.ts
+++ b/packages/taler-wallet-webextension/src/platform/dev.ts
@@ -37,18 +37,11 @@ const api: BackgroundPlatformAPI & ForegroundPlatformAPI = {
   listenNetworkConnectionState,
   openNewURLFromPopup: () => undefined,
   getPermissionsApi: () => ({
-    addPermissionsListener: () => undefined,
-    containsHostPermissions: async () => true,
-    removeHostPermissions: async () => false,
-    requestHostPermissions: async () => false,
     containsClipboardPermissions: async () => true,
     removeClipboardPermissions: async () => false,
     requestClipboardPermissions: async () => false,
   }),
 
-  // registerDeclarativeRedirect: () => false,
-  registerTalerHeaderListener: () => false,
-  containsTalerHeaderListener: () => false,
   getWalletWebExVersion: () => ({
     version: "none",
   }),
diff --git a/packages/taler-wallet-webextension/src/platform/firefox.ts 
b/packages/taler-wallet-webextension/src/platform/firefox.ts
index 0bbe805cf..3d67423fd 100644
--- a/packages/taler-wallet-webextension/src/platform/firefox.ts
+++ b/packages/taler-wallet-webextension/src/platform/firefox.ts
@@ -26,9 +26,6 @@ import chromePlatform, {
   containsClipboardPermissions as chromeClipContains,
   removeClipboardPermissions as chromeClipRemove,
   requestClipboardPermissions as chromeClipRequest,
-  containsHostPermissions as chromeHostContains,
-  requestHostPermissions as chromeHostRequest,
-  removeHostPermissions as chromeHostRemove,
 } from "./chrome.js";
 
 const api: BackgroundPlatformAPI & ForegroundPlatformAPI = {
@@ -47,16 +44,8 @@ function isFirefox(): boolean {
   return true;
 }
 
-function addPermissionsListener(callback: (p: Permissions) => void): void {
-  // throw Error("addPermissionListener is not supported for Firefox");
-}
-
 function getPermissionsApi(): CrossBrowserPermissionsApi {
   return {
-    addPermissionsListener,
-    containsHostPermissions: chromeHostContains,
-    requestHostPermissions: chromeHostRequest,
-    removeHostPermissions: chromeHostRemove,
     containsClipboardPermissions: chromeClipContains,
     removeClipboardPermissions: chromeClipRemove,
     requestClipboardPermissions: chromeClipRequest,
diff --git a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx 
b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
index e120334e8..304c15f0b 100644
--- a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
+++ b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
@@ -19,7 +19,7 @@
  * @author Sebastian Javier Marchano (sebasjm)
  */
 
-import { parseTalerUri, TalerUri, TalerUriAction } from 
"@gnu-taler/taler-util";
+import { parseTalerUri, stringifyTalerUri, TalerUri, TalerUriAction } from 
"@gnu-taler/taler-util";
 import { useTranslationContext } from "@gnu-taler/web-util/browser";
 import { Fragment, h, VNode } from "preact";
 import { Title } from "../components/styled/index.js";
@@ -69,10 +69,10 @@ function ContentByUriType({
       return (
         <div>
           <p>
-            <i18n.Translate>This page has a tip action.</i18n.Translate>
+            <i18n.Translate>This page has a reward action.</i18n.Translate>
           </p>
           <Button variant="contained" color="success" onClick={onConfirm}>
-            <i18n.Translate>Open tip page</i18n.Translate>
+            <i18n.Translate>Open reward page</i18n.Translate>
           </Button>
         </div>
       );
diff --git 
a/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts 
b/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts
index d1b1dc374..6cc4eb2b4 100644
--- a/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts
+++ b/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts
@@ -15,6 +15,7 @@
  */
 
 import { CoreApiResponse, TalerError, TalerErrorCode } from 
"@gnu-taler/taler-util";
+import type { MessageFromBackend } from "./platform/api.js";
 
 /**
  * This will modify all the pages that the user load when navigating with Web 
Extension enabled
@@ -46,6 +47,9 @@ const suffixIsNotXMLorPDF =
 const rootElementIsHTML =
   document.documentElement.nodeName &&
   document.documentElement.nodeName.toLowerCase() === "html";
+// const pageAcceptsTalerSupport = document.head.querySelector(
+//   "meta[name=taler-support]",
+// );
 
 
 
@@ -67,6 +71,7 @@ function convertURIToWebExtensionPath(uri: string) {
 const shouldNotInject =
   !documentDocTypeIsHTML ||
   !suffixIsNotXMLorPDF ||
+  // !pageAcceptsTalerSupport ||
   !rootElementIsHTML;
 
 const logger = {
@@ -93,16 +98,22 @@ function redirectToTalerActionHandler(element: 
HTMLMetaElement) {
     return;
   }
 
-  location.href = convertURIToWebExtensionPath(uri)
+  const walletPage = convertURIToWebExtensionPath(uri)
+  window.location.replace(walletPage)
 }
 
-function injectTalerSupportScript(head: HTMLHeadElement) {
+function injectTalerSupportScript(head: HTMLHeadElement, trusted: boolean) {
   const meta = head.querySelector("meta[name=taler-support]")
+  if (!meta) return;
+  const content = meta.getAttribute("content");
+  if (!content) return;
+  const features = content.split(",")
 
-  const debugEnabled = meta?.getAttribute("debug") === "true";
+  const debugEnabled = meta.getAttribute("debug") === "true";
+  const hijackEnabled = features.indexOf("uri") !== -1
+  const talerApiEnabled = features.indexOf("api") !== -1 && trusted
 
   const scriptTag = document.createElement("script");
-
   scriptTag.setAttribute("async", "false");
   const url = new URL(
     chrome.runtime.getURL("/dist/taler-wallet-interaction-support.js"),
@@ -111,6 +122,12 @@ function injectTalerSupportScript(head: HTMLHeadElement) {
   if (debugEnabled) {
     url.searchParams.set("debug", "true");
   }
+  if (talerApiEnabled) {
+    url.searchParams.set("api", "true");
+  }
+  if (hijackEnabled) {
+    url.searchParams.set("hijack", "true");
+  }
   scriptTag.src = url.href;
 
   try {
@@ -123,12 +140,14 @@ function injectTalerSupportScript(head: HTMLHeadElement) {
 
 
 export interface ExtensionOperations {
-  isInjectionEnabled: {
+  isAutoOpenEnabled: {
     request: void;
     response: boolean;
   };
-  isAutoOpenEnabled: {
-    request: void;
+  isDomainTrusted: {
+    request: {
+      domain: string;
+    };
     response: boolean;
   };
 }
@@ -200,48 +219,82 @@ async function sendMessageToBackground<Op extends keyof 
ExtensionOperations>(
   });
 }
 
+let notificationPort: chrome.runtime.Port | undefined;
+function listenToWalletBackground(listener: (m: any) => void): () => void {
+  if (notificationPort === undefined) {
+    notificationPort = chrome.runtime.connect({ name: "notifications" });
+  }
+  notificationPort.onMessage.addListener(listener);
+  function removeListener(): void {
+    if (notificationPort !== undefined) {
+      notificationPort.onMessage.removeListener(listener);
+    }
+  }
+  return removeListener;
+}
+
+const loaderSettings = {
+  isAutoOpenEnabled: false,
+}
+
 function start(
-  onTalerMetaTagFound: (listener:(el: HTMLMetaElement)=>void) => void,
-  onHeadReady: (listener:(el: HTMLHeadElement)=>void) => void
+  onTalerMetaTagFound: (listener: (el: HTMLMetaElement) => void) => void,
+  onHeadReady: (listener: (el: HTMLHeadElement) => void) => void
 ) {
-  // do not run everywhere, this is just expected to run on html
-  // sites
+  // do not run everywhere, this is just expected to run on site
+  // that are aware of taler
   if (shouldNotInject) return;
 
-  const isAutoOpenEnabled_promise = callBackground("isAutoOpenEnabled", 
undefined)
-  const isInjectionEnabled_promise = callBackground("isInjectionEnabled", 
undefined)
+  callBackground("isAutoOpenEnabled", undefined).then(result => {
+    loaderSettings.isAutoOpenEnabled = result
+  })
+  const isDomainTrusted_promise = callBackground("isDomainTrusted", {
+    domain: window.location.origin
+  })
 
-  onTalerMetaTagFound(async (el)=> {
-    const enabled = await isAutoOpenEnabled_promise;
-    if (!enabled) return;
+  onTalerMetaTagFound(async (el) => {
+    if (!loaderSettings.isAutoOpenEnabled) return;
     redirectToTalerActionHandler(el)
   })
 
   onHeadReady(async (el) => {
-    const enabled = await isInjectionEnabled_promise;
-    if (!enabled) return;
-    injectTalerSupportScript(el)
+    const trusted = await isDomainTrusted_promise
+    injectTalerSupportScript(el, trusted)
+  })
+
+  listenToWalletBackground((e: MessageFromBackend) => {
+    if (e.type === "web-extension" && e.notification.type === 
"settings-change") {
+      const settings = e.notification.currentValue
+      loaderSettings.isAutoOpenEnabled = settings.autoOpen
+    }
+    console.log("loader ->", e)
   })
 
 }
 
+function isCorrectMetaElement(el: HTMLMetaElement): boolean {
+  const name = el.getAttribute("name")
+  if (!name) return false;
+  if (name !== "taler-uri") return false;
+  const uri = el.getAttribute("content");
+  if (!uri) return false;
+  return true
+}
+
 /**
  * Tries to find taler meta tag ASAP and report
  * @param notify 
  * @returns 
  */
-function onTalerMetaTag(notify: (el: HTMLMetaElement) => void) {
+function notifyWhenTalerUriIsFound(notify: (el: HTMLMetaElement) => void) {
   if (document.head) {
     const element = document.head.querySelector("meta[name=taler-uri]")
     if (!element) return;
     if (!(element instanceof HTMLMetaElement)) return;
-    const name = element.getAttribute("name")
-    if (!name) return;
-    if (name !== "taler-uri") return;
-    const uri = element.getAttribute("content");
-    if (!uri) return;
 
-    notify(element)
+    if (isCorrectMetaElement(element)) {
+      notify(element)
+    }
     return;
   }
   const obs = new MutationObserver(async function (mutations) {
@@ -250,13 +303,10 @@ function onTalerMetaTag(notify: (el: HTMLMetaElement) => 
void) {
         if (mut.type === "childList") {
           mut.addedNodes.forEach((added) => {
             if (added instanceof HTMLMetaElement) {
-              const name = added.getAttribute("name")
-              if (!name) return;
-              if (name !== "taler-uri") return;
-              const uri = added.getAttribute("content");
-              if (!uri) return;
-              notify(added)
-              obs.disconnect()
+              if (isCorrectMetaElement(added)) {
+                notify(added)
+                obs.disconnect()
+              }
             }
           });
         }
@@ -279,7 +329,7 @@ function onTalerMetaTag(notify: (el: HTMLMetaElement) => 
void) {
  * @param notify 
  * @returns 
  */
-function onHeaderReady(notify: (el: HTMLHeadElement) => void) {
+function notifyWhenHeadIsFound(notify: (el: HTMLHeadElement) => void) {
   if (document.head) {
     notify(document.head)
     return;
@@ -290,7 +340,6 @@ function onHeaderReady(notify: (el: HTMLHeadElement) => 
void) {
         if (mut.type === "childList") {
           mut.addedNodes.forEach((added) => {
             if (added instanceof HTMLHeadElement) {
-
               notify(added)
               obs.disconnect()
             }
@@ -309,4 +358,4 @@ function onHeaderReady(notify: (el: HTMLHeadElement) => 
void) {
   })
 }
 
-start(onTalerMetaTag, onHeaderReady);
+start(notifyWhenTalerUriIsFound, notifyWhenHeadIsFound);
diff --git 
a/packages/taler-wallet-webextension/src/taler-wallet-interaction-support.ts 
b/packages/taler-wallet-webextension/src/taler-wallet-interaction-support.ts
index 993c12703..8b15380f9 100644
--- a/packages/taler-wallet-webextension/src/taler-wallet-interaction-support.ts
+++ b/packages/taler-wallet-webextension/src/taler-wallet-interaction-support.ts
@@ -47,7 +47,7 @@
   const shouldNotRun =
     !documentDocTypeIsHTML ||
     !suffixIsNotXMLorPDF ||
-    // !pageAcceptsTalerSupport || FIXME: removing this before release for 
testing
+    !pageAcceptsTalerSupport ||
     !rootElementIsHTML;
 
   interface Info {
@@ -154,32 +154,38 @@
 
   function start() {
     if (shouldNotRun) return;
-    // FIXME: we can remove this if the script caller send information we need
     if (!(document.currentScript instanceof HTMLScriptElement)) return;
 
     const url = new URL(document.currentScript.src);
     const { protocol, searchParams, hostname } = url;
     const extensionId = searchParams.get("id") ?? "";
     const debugEnabled = searchParams.get("debug") === "true";
-    if (debugEnabled) {
-      logger.debug = logger.info;
-    }
+    const apiEnabled = searchParams.get("api") === "true";
+    const hijackEnabled = searchParams.get("hijack") === "true";
 
     const info: Info = Object.freeze({
       extensionId,
       protocol,
       hostname,
     });
+
+    if (debugEnabled) {
+      logger.debug = logger.info;
+    }
+
     const taler: TalerSupport = {
       info,
       __internal: buildApi(info),
     };
 
-    //@ts-ignore
-    window.taler = taler;
+    if (apiEnabled) {
+      //@ts-ignore
+      window.taler = taler;
+    }
 
-    //default behavior: register on install
-    taler.__internal.registerProtocolHandler();
+    if (hijackEnabled) {
+      taler.__internal.registerProtocolHandler();
+    }
   }
 
   // utils functions
@@ -189,6 +195,6 @@
     );
   }
 
-  return start
+  start();
 })()
 
diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx 
b/packages/taler-wallet-webextension/src/wallet/Application.tsx
index df0e968b9..3867845f2 100644
--- a/packages/taler-wallet-webextension/src/wallet/Application.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx
@@ -368,7 +368,21 @@ export function Application(): VNode {
           <Route
             path={Pages.ctaTips}
             component={({ talerUri }: { talerUri: string }) => (
-              <CallToActionTemplate title={i18n.str`Digital cash tip`}>
+              <CallToActionTemplate title={i18n.str`Digital cash rewards`}>
+                <TipPage
+                  talerTipUri={decodeURIComponent(talerUri)}
+                  onCancel={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaRewards}
+            component={({ talerUri }: { talerUri: string }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash rewards`}>
                 <TipPage
                   talerTipUri={decodeURIComponent(talerUri)}
                   onCancel={() => redirectTo(Pages.balance)}
diff --git a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
index faa64e07d..d12ae864b 100644
--- a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
@@ -40,6 +40,9 @@ import { Button } from "../mui/Button.js";
 import { Grid } from "../mui/Grid.js";
 import { Paper } from "../mui/Paper.js";
 import { TextField } from "../mui/TextField.js";
+import { Checkbox } from "../components/Checkbox.js";
+import { useSettings } from "../hooks/useSettings.js";
+import { useAlertContext } from "../context/alert.js";
 
 export function DeveloperPage(): VNode {
   const listenAllEvents = Array.from<NotificationType>({ length: 1 });
@@ -132,6 +135,8 @@ export function View({ operations, coins, 
onDownloadDatabase }: Props): VNode {
       dump: JSON.parse(str),
     });
   }
+  const [settings, updateSettings] = useSettings();
+  const { safely } = useAlertContext();
 
   const hook = useAsyncAsHook(() =>
     api.wallet.call(WalletApiOperation.ListExchanges, {}),
@@ -252,26 +257,6 @@ export function View({ operations, coins, 
onDownloadDatabase }: Props): VNode {
             <i18n.Translate>export database</i18n.Translate>
           </Button>
         </Grid>
-        <Grid item>
-          <Button
-            variant="contained"
-            onClick={async () => {
-              api.background.call("toggleHeaderListener", true);
-            }}
-          >
-            <i18n.Translate>enable header listener</i18n.Translate>
-          </Button>
-        </Grid>
-        <Grid item>
-          <Button
-            variant="contained"
-            onClick={async () => {
-              api.background.call("toggleHeaderListener", false);
-            }}
-          >
-            <i18n.Translate>disable header listener</i18n.Translate>
-          </Button>
-        </Grid>
         <Grid item>
           <Button
             variant="contained"
@@ -360,6 +345,22 @@ export function View({ operations, coins, 
onDownloadDatabase }: Props): VNode {
           </Button>
         </Grid>{" "}
       </Grid>
+      <Checkbox
+        label={i18n.str`Inject Taler support in all pages`}
+        name="inject"
+        description={
+          <i18n.Translate>
+            Enabling this option will make `window.taler` be available
+            in all sites
+          </i18n.Translate>
+        }
+        enabled={settings.injectTalerSupport!}
+        onToggle={safely("update support injection", async () => {
+          updateSettings("injectTalerSupport", !settings.injectTalerSupport);
+        })}
+      />
+
+
       <Paper style={{ padding: 10, margin: 10 }}>
         <h3>Logging</h3>
         <div>
@@ -396,92 +397,98 @@ export function View({ operations, coins, 
onDownloadDatabase }: Props): VNode {
           Set log level
         </Button>
       </Paper>
-      {downloadedDatabase && (
-        <div>
-          <i18n.Translate>
-            Database exported at{" "}
-            <Time
-              timestamp={AbsoluteTime.fromMilliseconds(
-                downloadedDatabase.time.getTime(),
-              )}
-              format="yyyy/MM/dd HH:mm:ss"
-            />{" "}
-            <a
-              href={`data:text/plain;charset=utf-8;base64,${toBase64(
-                downloadedDatabase.content,
-              )}`}
-              download={`taler-wallet-database-${format(
-                downloadedDatabase.time,
-                "yyyy/MM/dd_HH:mm",
-              )}.json`}
-            >
-              <i18n.Translate>click here</i18n.Translate>
-            </a>{" "}
-            to download
-          </i18n.Translate>
-        </div>
-      )}
+      {
+        downloadedDatabase && (
+          <div>
+            <i18n.Translate>
+              Database exported at{" "}
+              <Time
+                timestamp={AbsoluteTime.fromMilliseconds(
+                  downloadedDatabase.time.getTime(),
+                )}
+                format="yyyy/MM/dd HH:mm:ss"
+              />{" "}
+              <a
+                href={`data:text/plain;charset=utf-8;base64,${toBase64(
+                  downloadedDatabase.content,
+                )}`}
+                download={`taler-wallet-database-${format(
+                  downloadedDatabase.time,
+                  "yyyy/MM/dd_HH:mm",
+                )}.json`}
+              >
+                <i18n.Translate>click here</i18n.Translate>
+              </a>{" "}
+              to download
+            </i18n.Translate>
+          </div>
+        )
+      }
       <br />
       <p>
         <i18n.Translate>Coins</i18n.Translate>:
       </p>
-      {Object.keys(money_by_exchange).map((ex, idx) => {
-        const allcoins = money_by_exchange[ex];
-        allcoins.sort((a, b) => {
-          if (b.denom_value !== a.denom_value) {
-            return b.denom_value - a.denom_value;
-          }
-          return b.denom_fraction - a.denom_fraction;
-        });
+      {
+        Object.keys(money_by_exchange).map((ex, idx) => {
+          const allcoins = money_by_exchange[ex];
+          allcoins.sort((a, b) => {
+            if (b.denom_value !== a.denom_value) {
+              return b.denom_value - a.denom_value;
+            }
+            return b.denom_fraction - a.denom_fraction;
+          });
 
-        const coins = allcoins.reduce(
-          (prev, cur) => {
-            if (cur.status === CoinStatus.Fresh) prev.usable.push(cur);
-            if (cur.status === CoinStatus.Dormant) prev.spent.push(cur);
-            return prev;
-          },
-          {
-            spent: [],
-            usable: [],
-          } as SplitedCoinInfo,
-        );
+          const coins = allcoins.reduce(
+            (prev, cur) => {
+              if (cur.status === CoinStatus.Fresh) prev.usable.push(cur);
+              if (cur.status === CoinStatus.Dormant) prev.spent.push(cur);
+              return prev;
+            },
+            {
+              spent: [],
+              usable: [],
+            } as SplitedCoinInfo,
+          );
 
-        return (
-          <ShowAllCoins
-            key={idx}
-            coins={coins}
-            ex={ex}
-            currencies={currencies}
-          />
-        );
-      })}
+          return (
+            <ShowAllCoins
+              key={idx}
+              coins={coins}
+              ex={ex}
+              currencies={currencies}
+            />
+          );
+        })
+      }
       <br />
-      {operations && operations.length > 0 && (
-        <Fragment>
-          <p>
-            <i18n.Translate>Pending operations</i18n.Translate>
-          </p>
-          <dl>
-            {operations.reverse().map((o) => {
-              return (
-                <NotifyUpdateFadeOut key={hashObjectId(o)}>
-                  <dt>
-                    {o.type}{" "}
-                    <Time
-                      timestamp={o.timestampDue}
-                      format="yy/MM/dd HH:mm:ss"
-                    />
-                  </dt>
-                  <dd>
-                    <pre>{JSON.stringify(o, undefined, 2)}</pre>
-                  </dd>
-                </NotifyUpdateFadeOut>
-              );
-            })}
-          </dl>
-        </Fragment>
-      )}
-    </div>
+      {
+        operations && operations.length > 0 && (
+          <Fragment>
+            <p>
+              <i18n.Translate>Pending operations</i18n.Translate>
+            </p>
+            <dl>
+              {operations.reverse().map((o) => {
+                return (
+                  <NotifyUpdateFadeOut key={hashObjectId(o)}>
+                    <dt>
+                      {o.type}{" "}
+                      <Time
+                        timestamp={o.timestampDue}
+                        format="yy/MM/dd HH:mm:ss"
+                      />
+                    </dt>
+                    <dd>
+                      <pre>{JSON.stringify(o, undefined, 2)}</pre>
+                    </dd>
+                  </NotifyUpdateFadeOut>
+                );
+              })}
+            </dl>
+          </Fragment>
+        )
+      }
+    </div >
   );
 }
 
diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
index 86c420b91..a5d6972de 100644
--- a/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
@@ -55,7 +55,6 @@ export const AllOff = tests.createExample(TestedComponent, {
   deviceName: "this-is-the-device-name",
   advanceToggle: { value: false, button: {} },
   autoOpenToggle: { value: false, button: {} },
-  injectTalerToggle: { value: false, button: {} },
   langToggle: { value: false, button: {} },
   setDeviceName: () => Promise.resolve(),
   ...version,
@@ -65,7 +64,6 @@ export const OneChecked = 
tests.createExample(TestedComponent, {
   deviceName: "this-is-the-device-name",
   advanceToggle: { value: false, button: {} },
   autoOpenToggle: { value: false, button: {} },
-  injectTalerToggle: { value: false, button: {} },
   langToggle: { value: false, button: {} },
   setDeviceName: () => Promise.resolve(),
   ...version,
@@ -75,7 +73,6 @@ export const WithOneExchange = 
tests.createExample(TestedComponent, {
   deviceName: "this-is-the-device-name",
   advanceToggle: { value: false, button: {} },
   autoOpenToggle: { value: false, button: {} },
-  injectTalerToggle: { value: false, button: {} },
   langToggle: { value: false, button: {} },
   setDeviceName: () => Promise.resolve(),
   knownExchanges: [
@@ -100,7 +97,6 @@ export const WithExchangeInDifferentState = 
tests.createExample(
     deviceName: "this-is-the-device-name",
     advanceToggle: { value: false, button: {} },
     autoOpenToggle: { value: false, button: {} },
-    injectTalerToggle: { value: false, button: {} },
     langToggle: { value: false, button: {} },
     setDeviceName: () => Promise.resolve(),
     knownExchanges: [
diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.tsx 
b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
index b27413a96..e25629148 100644
--- a/packages/taler-wallet-webextension/src/wallet/Settings.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
@@ -80,14 +80,6 @@ export function SettingsPage(): VNode {
           }),
         },
       }}
-      injectTalerToggle={{
-        value: settings.injectTalerSupport,
-        button: {
-          onClick: safely("update support injection", async () => {
-            updateSettings("injectTalerSupport", !settings.injectTalerSupport);
-          }),
-        },
-      }}
       advanceToggle={{
         value: settings.advanceMode,
         button: {
@@ -117,7 +109,6 @@ export interface ViewProps {
   deviceName: string;
   setDeviceName: (s: string) => Promise<void>;
   autoOpenToggle: ToggleHandler;
-  injectTalerToggle: ToggleHandler;
   advanceToggle: ToggleHandler;
   langToggle: ToggleHandler;
   knownExchanges: Array<ExchangeListItem>;
@@ -131,7 +122,6 @@ export interface ViewProps {
 export function SettingsView({
   knownExchanges,
   autoOpenToggle,
-  injectTalerToggle,
   advanceToggle,
   langToggle,
   coreVersion,
@@ -275,19 +265,6 @@ export function SettingsView({
         <SubTitle>
           <i18n.Translate>Navigator</i18n.Translate>
         </SubTitle>
-        <Checkbox
-          label={i18n.str`Inject Taler support in all pages`}
-          name="inject"
-          description={
-            <i18n.Translate>
-              Disabling this option will make some web application not able to
-              trigger the wallet when clicking links but you will be able to
-              open the wallet using the keyboard shortcut
-            </i18n.Translate>
-          }
-          enabled={injectTalerToggle.value!}
-          onToggle={injectTalerToggle.button.onClick!}
-        />
         <Checkbox
           label={i18n.str`Automatically open wallet`}
           name="autoOpen"
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts 
b/packages/taler-wallet-webextension/src/wxApi.ts
index 8fb8211ae..d989c9662 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -83,14 +83,6 @@ export interface BackgroundOperations {
     };
     response: void;
   };
-  containsHeaderListener: {
-    request: void;
-    response: ExtendedPermissionsResponse;
-  };
-  toggleHeaderListener: {
-    request: boolean;
-    response: ExtendedPermissionsResponse;
-  };
 }
 
 export interface BackgroundApiClient {
@@ -194,7 +186,7 @@ function onUpdateNotification(
       return;
     };
   const onNewMessage = (message: MessageFromBackend): void => {
-    const shouldNotify = messageTypes.includes(message.type);
+    const shouldNotify = message.type === "wallet" && 
messageTypes.includes(message.notification.type);
     if (shouldNotify) {
       doCallback();
     }
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts 
b/packages/taler-wallet-webextension/src/wxBackend.ts
index 1ecd66f05..95d31c519 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -122,18 +122,18 @@ async function sum(ns: Array<number>): Promise<number> {
 }
 
 const extensionHandlers: ExtensionHandlerType = {
-  isInjectionEnabled,
   isAutoOpenEnabled,
+  isDomainTrusted,
 };
 
-async function isInjectionEnabled(): Promise<boolean> {
+async function isAutoOpenEnabled(): Promise<boolean> {
   const settings = await platform.getSettingsFromStorage();
-  return settings.injectTalerSupport === true;
+  return settings.autoOpen === true;
 }
 
-async function isAutoOpenEnabled(): Promise<boolean> {
+async function isDomainTrusted(): Promise<boolean> {
   const settings = await platform.getSettingsFromStorage();
-  return settings.autoOpen === true;
+  return settings.injectTalerSupport === true;
 }
 
 const backendHandlers: BackendHandlerType = {
@@ -142,14 +142,8 @@ const backendHandlers: BackendHandlerType = {
   resetDb,
   runGarbageCollector,
   setLoggingLevel,
-  containsHeaderListener,
-  toggleHeaderListener,
 };
 
-async function containsHeaderListener(): Promise<ExtendedPermissionsResponse> {
-  const result = platform.containsTalerHeaderListener();
-  return { newValue: result };
-}
 
 async function setLoggingLevel({
   tag,
@@ -309,8 +303,10 @@ async function reinitWallet(): Promise<void> {
     return;
   }
   wallet.addNotificationListener((message) => {
-    logger.info("wallet -> ui", message);
-    platform.sendMessageToAllChannels(message);
+    platform.sendMessageToAllChannels({
+      type: "wallet",
+      notification: message
+    });
   });
 
   platform.keepAlive(() => {
@@ -360,65 +356,6 @@ export async function wxMain(): Promise<void> {
     console.error(e);
   }
 
-  // platform.registerDeclarativeRedirect();
-  // if (false) {
-  /**
-   * this is not working reliable on chrome, just
-   * intercepts queries after the user clicks the popups
-   * which doesn't make sense, keeping it to make more tests 
-   */
-
-  logger.trace("check taler header listener");
-  const enabled = platform.containsTalerHeaderListener()
-  if (!enabled) {
-    logger.info("header listener on")
-    const perm = await platform.getPermissionsApi().containsHostPermissions()
-    if (perm) {
-      logger.info("header listener allowed")
-      try {
-        platform.registerTalerHeaderListener();
-      } catch (e) {
-        logger.error("could not register header listener", e);
-      }
-    } else {
-      logger.info("header listener requested")
-      await platform.getPermissionsApi().requestHostPermissions()
-    }
-  }
-
-  // On platforms that support it, also listen to external
-  // modification of permissions.
-  platform.getPermissionsApi().addPermissionsListener((perm, lastError) => {
-    logger.info(`permission added: ${perm}`,)
-    if (lastError) {
-      logger.error(
-        `there was a problem trying to get permission ${perm}`,
-        lastError,
-      );
-      return;
-    }
-    platform.registerTalerHeaderListener();
-  });
-
-  // }
 }
 
 
-async function toggleHeaderListener(
-  newVal: boolean,
-): Promise<ExtendedPermissionsResponse> {
-  logger.trace("new extended permissions value", newVal);
-  if (newVal) {
-    try {
-      platform.registerTalerHeaderListener();
-      return { newValue: true };
-    } catch (e) {
-      logger.error("FAIL to toggle", e)
-    }
-    return { newValue: false }
-  }
-
-  const rem = await platform.getPermissionsApi().removeHostPermissions();
-  logger.trace("permissions removed:", rem);
-  return { newValue: false };
-}

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