gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: fix #7704


From: gnunet
Subject: [taler-wallet-core] branch master updated: fix #7704
Date: Wed, 19 Apr 2023 17:42:54 +0200

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

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

The following commit(s) were added to refs/heads/master by this push:
     new d483a3f55 fix #7704
d483a3f55 is described below

commit d483a3f5574355ed9c43eb6ddea59e5734323cf0
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Wed Apr 19 12:42:47 2023 -0300

    fix #7704
---
 packages/taler-util/src/wallet-types.ts            |  12 +-
 packages/taler-wallet-cli/src/index.ts             |  81 +-
 packages/taler-wallet-core/src/dbless.ts           |   8 +-
 packages/taler-wallet-core/src/dev-experiments.ts  |  62 +-
 packages/taler-wallet-core/src/host-common.ts      |   6 +
 packages/taler-wallet-core/src/host-impl.node.ts   |   8 +-
 packages/taler-wallet-core/src/host-impl.qtart.ts  |   8 +-
 packages/taler-wallet-core/src/index.ts            |   1 -
 .../taler-wallet-core/src/internal-wallet-state.ts |   7 +-
 .../taler-wallet-core/src/operations/deposits.ts   |   7 +-
 .../taler-wallet-core/src/operations/exchanges.ts  |  11 +-
 .../src/operations/pay-merchant.ts                 |  30 +-
 .../taler-wallet-core/src/operations/pay-peer.ts   |   1 +
 .../taler-wallet-core/src/operations/refresh.ts    |  13 +-
 .../taler-wallet-core/src/operations/withdraw.ts   |  16 +-
 .../taler-wallet-core/src/util/coinSelection.ts    |  12 +-
 packages/taler-wallet-core/src/util/debugFlags.ts  |  32 -
 .../taler-wallet-core/src/util/denominations.ts    |   9 +-
 packages/taler-wallet-core/src/wallet-api-types.ts |  90 ++-
 packages/taler-wallet-core/src/wallet.ts           | 217 +++---
 .../src/NavigationBar.tsx                          |  16 +-
 .../src/background.dev.ts                          |   1 -
 .../taler-wallet-webextension/src/background.ts    |   2 -
 .../{JustInDevMode.tsx => EnabledBySettings.tsx}   |  19 +-
 .../src/components/ErrorTalerOperation.tsx         |   7 +-
 .../src/components/TermsOfService/utils.ts         |  16 +-
 .../src/context/devContext.ts                      |  70 --
 .../src/cta/Payment/state.ts                       |   2 -
 .../src/cta/PaymentTemplate/views.tsx              |   1 -
 .../src/hooks/useClipboardPermissions.ts           |   1 -
 .../src/hooks/useSettings.ts                       |   1 -
 .../src/hooks/useWalletDevMode.ts                  |  52 --
 .../taler-wallet-webextension/src/platform/api.ts  |  31 +-
 .../src/platform/firefox.ts                        |   2 +-
 .../src/popup/Application.tsx                      |  19 +-
 .../src/popupEntryPoint.dev.tsx                    |   1 -
 .../src/popupEntryPoint.tsx                        |   2 -
 .../taler-wallet-webextension/src/test-utils.ts    |   1 -
 .../src/wallet/Application.tsx                     | 853 ++++++++++-----------
 .../src/wallet/DestinationSelection/views.tsx      |   6 +-
 .../src/wallet/ManageAccount/state.ts              |   7 +-
 .../src/wallet/Settings.stories.tsx                |  16 +-
 .../src/wallet/Settings.tsx                        | 183 +++--
 .../src/wallet/Transaction.tsx                     |  15 +-
 .../src/walletEntryPoint.dev.tsx                   |   1 -
 .../src/walletEntryPoint.tsx                       |   2 -
 packages/taler-wallet-webextension/src/wxApi.ts    |   2 +-
 .../taler-wallet-webextension/src/wxBackend.ts     |   7 +
 48 files changed, 958 insertions(+), 1009 deletions(-)

diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index 7a2442e2d..5979f14b4 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -725,6 +725,9 @@ export interface WalletCoreVersion {
   exchange: string;
   merchant: string;
   bank: string;
+  /**
+   * @deprecated will be removed
+   */
   devMode: boolean;
 }
 
@@ -2157,15 +2160,6 @@ export interface ConfirmPeerPullDebitRequest {
   peerPullPaymentIncomingId: string;
 }
 
-export interface SetDevModeRequest {
-  devModeEnabled: boolean;
-}
-
-export const codecForSetDevModeRequest = (): Codec<SetDevModeRequest> =>
-  buildCodecForObject<SetDevModeRequest>()
-    .property("devModeEnabled", codecForBoolean())
-    .build("SetDevModeRequest");
-
 export interface ApplyDevExperimentRequest {
   devExperimentUri: string;
 }
diff --git a/packages/taler-wallet-cli/src/index.ts 
b/packages/taler-wallet-cli/src/index.ts
index fadf84d5c..cc7c119b9 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -27,25 +27,18 @@ import {
   CoreApiResponse,
   Duration,
   encodeCrock,
-  ExtendedStatus,
   getErrorDetailFromException,
   getRandomBytes,
   j2s,
   Logger,
   parsePaytoUri,
-  PaymentStatus,
   PreparePayResultType,
   RecoveryMergeStrategy,
-  RefreshReason,
   sampleWalletCoreTransactions,
   setDangerousTimetravel,
   setGlobalLogLevelFromString,
   summarizeTalerErrorDetail,
   TalerUriType,
-  Transaction,
-  TransactionState,
-  TransactionSubstate,
-  TransactionType,
   WalletNotification,
 } from "@gnu-taler/taler-util";
 import { clk } from "@gnu-taler/taler-util/clk";
@@ -61,15 +54,9 @@ import { JsonMessage, runRpcServer } from 
"@gnu-taler/taler-util/twrpc";
 import {
   createNativeWalletHost,
   createNativeWalletHost2,
-  CryptoDispatcher,
-  nativeCrypto,
-  //NodeThreadCryptoWorkerFactory,
-  //SynchronousCryptoWorkerFactoryPlain,
-  TalerCryptoInterface,
   Wallet,
   WalletApiOperation,
   WalletCoreApiClient,
-  walletCoreDebugFlags,
 } from "@gnu-taler/taler-wallet-core";
 import {
   createRemoteWallet,
@@ -264,12 +251,19 @@ async function createLocalWallet(
       }
     },
     cryptoWorkerType: walletCliArgs.wallet.cryptoWorker as any,
+    config: {
+      features: {
+        batchWithdrawal: checkEnvFlag("TALER_WALLET_BATCH_WITHDRAWAL"),
+      },
+      testing: {
+        devModeActive: checkEnvFlag("TALER_WALLET_DEV_MODE"),
+        denomselAllowLate: checkEnvFlag(
+          "TALER_WALLET_DEBUG_DENOMSEL_ALLOW_LATE",
+        ),
+      },
+    },
   });
 
-  if (checkEnvFlag("TALER_WALLET_BATCH_WITHDRAWAL")) {
-    wallet.setBatchWithdrawal(true);
-  }
-
   applyVerbose(walletCliArgs.wallet.verbose);
   try {
     await wallet.handleCoreApiRequest("initWallet", "native-init", {
@@ -1405,30 +1399,6 @@ advancedCli
     });
   });
 
-advancedCli
-  .subcommand("enableDevMode", "enable-dev-mode", {
-    help: "Enable developer mode (dangerous!)",
-  })
-  .action(async (args) => {
-    await withWallet(args, async (wallet) => {
-      await wallet.client.call(WalletApiOperation.SetDevMode, {
-        devModeEnabled: true,
-      });
-    });
-  });
-
-advancedCli
-  .subcommand("disableDevMode", "disable-dev-mode", {
-    help: "Disable developer mode",
-  })
-  .action(async (args) => {
-    await withWallet(args, async (wallet) => {
-      await wallet.client.call(WalletApiOperation.SetDevMode, {
-        devModeEnabled: false,
-      });
-    });
-  });
-
 const coinPubListCodec = codecForList(codecForString());
 
 advancedCli
@@ -1647,35 +1617,6 @@ async function read(stream: NodeJS.ReadStream) {
   return Buffer.concat(chunks).toString("utf8");
 }
 
-// testCli
-//   .subcommand("cryptoworker", "cryptoworker")
-//   .maybeOption("impl", ["--impl"], clk.STRING)
-//   .action(async (args) => {
-//     let cryptoApi: TalerCryptoInterface;
-//     if (!args.cryptoworker.impl || args.cryptoworker.impl === "node") {
-//       const workerFactory = new NodeThreadCryptoWorkerFactory();
-//       const cryptoDisp = new CryptoDispatcher(workerFactory);
-//       cryptoApi = cryptoDisp.cryptoApi;
-//     } else if (args.cryptoworker.impl === "sync") {
-//       const workerFactory = new SynchronousCryptoWorkerFactoryPlain();
-//       const cryptoDisp = new CryptoDispatcher(workerFactory);
-//       cryptoApi = cryptoDisp.cryptoApi;
-//     } else if (args.cryptoworker.impl === "none") {
-//       cryptoApi = nativeCrypto;
-//     } else {
-//       throw Error(`invalid crypto worker type ${args.cryptoworker.impl}`);
-//     }
-
-//     const input = "foo";
-//     console.log(`testing crypto worker by hashing string '${input}'`);
-//     const res = await cryptoApi.hashString({ str: input });
-//     console.log(res);
-//   });
-
 export function main() {
-  if (getenv("TALER_WALLET_DEBUG_DENOMSEL_ALLOW_LATE")) {
-    logger.warn("Allowing withdrawal of late denominations for debugging");
-    walletCoreDebugFlags.denomselAllowLate = true;
-  }
   walletCli.run();
 }
diff --git a/packages/taler-wallet-core/src/dbless.ts 
b/packages/taler-wallet-core/src/dbless.ts
index 5dc13433a..04bfa1359 100644
--- a/packages/taler-wallet-core/src/dbless.ts
+++ b/packages/taler-wallet-core/src/dbless.ts
@@ -65,7 +65,7 @@ import {
 } from "./operations/withdraw.js";
 import { ExchangeInfo } from "./operations/exchanges.js";
 import { assembleRefreshRevealRequest } from "./operations/refresh.js";
-import { isWithdrawableDenom } from "./index.js";
+import { isWithdrawableDenom, WalletConfig } from "./index.js";
 
 const logger = new Logger("dbless.ts");
 
@@ -206,6 +206,7 @@ export async function withdrawCoin(args: {
 }
 
 export function findDenomOrThrow(
+  denomselAllowLate: boolean,
   exchangeInfo: ExchangeInfo,
   amount: AmountString,
 ): DenominationRecord {
@@ -215,7 +216,10 @@ export function findDenomOrThrow(
       fraction: d.amountFrac,
       value: d.amountVal,
     };
-    if (Amounts.cmp(value, amount) === 0 && isWithdrawableDenom(d)) {
+    if (
+      Amounts.cmp(value, amount) === 0 &&
+      isWithdrawableDenom(d, denomselAllowLate)
+    ) {
       return d;
     }
   }
diff --git a/packages/taler-wallet-core/src/dev-experiments.ts 
b/packages/taler-wallet-core/src/dev-experiments.ts
index 3e6194ccd..113e9bede 100644
--- a/packages/taler-wallet-core/src/dev-experiments.ts
+++ b/packages/taler-wallet-core/src/dev-experiments.ts
@@ -36,35 +36,6 @@ import {
 
 const logger = new Logger("dev-experiments.ts");
 
-export async function setDevMode(
-  ws: InternalWalletState,
-  enabled: boolean,
-): Promise<void> {
-  if (enabled) {
-    logger.info("enabling devmode");
-    await ws.db
-      .mktx((x) => [x.config])
-      .runReadWrite(async (tx) => {
-        tx.config.put({
-          key: ConfigRecordKey.DevMode,
-          value: true,
-        });
-      });
-    await maybeInitDevMode(ws);
-  } else {
-    logger.info("disabling devmode");
-    await ws.db
-      .mktx((x) => [x.config])
-      .runReadWrite(async (tx) => {
-        tx.config.put({
-          key: ConfigRecordKey.DevMode,
-          value: false,
-        });
-      });
-    await leaveDevMode(ws);
-  }
-}
-
 /**
  * Apply a dev experiment to the wallet database / state.
  */
@@ -78,7 +49,7 @@ export async function applyDevExperiment(
     logger.info("unable to parse dev experiment URI");
     return;
   }
-  if (!ws.devModeActive) {
+  if (!ws.config.testing.devModeActive) {
     throw Error(
       "can't handle devmode URI (other than enable-devmode) unless devmode is 
active",
     );
@@ -86,37 +57,6 @@ export async function applyDevExperiment(
   throw Error(`dev-experiment id not understood ${parsedUri.devExperimentId}`);
 }
 
-/**
- * Enter dev mode, if the wallet's config entry in the DB demands it.
- */
-export async function maybeInitDevMode(ws: InternalWalletState): Promise<void> 
{
-  const devMode = await ws.db
-    .mktx((x) => [x.config])
-    .runReadOnly(async (tx) => {
-      const rec = await tx.config.get(ConfigRecordKey.DevMode);
-      if (!rec || rec.key !== ConfigRecordKey.DevMode) {
-        return false;
-      }
-      return rec.value;
-    });
-  if (!devMode) {
-    ws.devModeActive = false;
-    return;
-  }
-  ws.devModeActive = true;
-  if (ws.http instanceof DevExperimentHttpLib) {
-    return;
-  }
-  ws.http = new DevExperimentHttpLib(ws.http);
-}
-
-export async function leaveDevMode(ws: InternalWalletState): Promise<void> {
-  if (ws.http instanceof DevExperimentHttpLib) {
-    ws.http = ws.http.underlyingLib;
-  }
-  ws.devModeActive = false;
-}
-
 export class DevExperimentHttpLib implements HttpRequestLibrary {
   _isDevExperimentLib = true;
   underlyingLib: HttpRequestLibrary;
diff --git a/packages/taler-wallet-core/src/host-common.ts 
b/packages/taler-wallet-core/src/host-common.ts
index 7651e5a12..21e7f1157 100644
--- a/packages/taler-wallet-core/src/host-common.ts
+++ b/packages/taler-wallet-core/src/host-common.ts
@@ -16,6 +16,7 @@
 
 import { WalletNotification } from "@gnu-taler/taler-util";
 import { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
+import { WalletConfig, WalletConfigParameter } from "./index.js";
 
 /**
  * Helpers to initiate a wallet in a host environment.
@@ -44,6 +45,11 @@ export interface DefaultNodeWalletArgs {
   httpLib?: HttpRequestLibrary;
 
   cryptoWorkerType?: "sync" | "node-worker-thread";
+
+  /**
+   * Config parameters
+   */
+  config?: WalletConfigParameter;
 }
 
 /**
diff --git a/packages/taler-wallet-core/src/host-impl.node.ts 
b/packages/taler-wallet-core/src/host-impl.node.ts
index 097b5856a..bf5c14f99 100644
--- a/packages/taler-wallet-core/src/host-impl.node.ts
+++ b/packages/taler-wallet-core/src/host-impl.node.ts
@@ -144,7 +144,13 @@ export async function createNativeWalletHost2(
 
   const timer = new SetTimeoutTimerAPI();
 
-  const w = await Wallet.create(myDb, myHttpLib, timer, workerFactory);
+  const w = await Wallet.create(
+    myDb,
+    myHttpLib,
+    timer,
+    workerFactory,
+    args.config,
+  );
 
   if (args.notifyHandler) {
     w.addNotificationListener(args.notifyHandler);
diff --git a/packages/taler-wallet-core/src/host-impl.qtart.ts 
b/packages/taler-wallet-core/src/host-impl.qtart.ts
index 337914292..db7a1fa5c 100644
--- a/packages/taler-wallet-core/src/host-impl.qtart.ts
+++ b/packages/taler-wallet-core/src/host-impl.qtart.ts
@@ -108,7 +108,13 @@ export async function createNativeWalletHost2(
 
   const timer = new SetTimeoutTimerAPI();
 
-  const w = await Wallet.create(myDb, myHttpLib, timer, workerFactory);
+  const w = await Wallet.create(
+    myDb,
+    myHttpLib,
+    timer,
+    workerFactory,
+    args.config,
+  );
 
   if (args.notifyHandler) {
     w.addNotificationListener(args.notifyHandler);
diff --git a/packages/taler-wallet-core/src/index.ts 
b/packages/taler-wallet-core/src/index.ts
index 7b21d8f91..8dd06fe2b 100644
--- a/packages/taler-wallet-core/src/index.ts
+++ b/packages/taler-wallet-core/src/index.ts
@@ -36,7 +36,6 @@ export {
 
 export * from "./pending-types.js";
 
-export * from "./util/debugFlags.js";
 export { InternalWalletState } from "./internal-wallet-state.js";
 export * from "./wallet-api-types.js";
 export * from "./wallet.js";
diff --git a/packages/taler-wallet-core/src/internal-wallet-state.ts 
b/packages/taler-wallet-core/src/internal-wallet-state.ts
index 8434c3b8f..e59781471 100644
--- a/packages/taler-wallet-core/src/internal-wallet-state.ts
+++ b/packages/taler-wallet-core/src/internal-wallet-state.ts
@@ -52,6 +52,7 @@ import {
   GetReadWriteAccess,
 } from "./util/query.js";
 import { TimerGroup } from "./util/timer.js";
+import { WalletConfig } from "./wallet-api-types.js";
 
 export const EXCHANGE_COINS_LOCK = "exchange-coins-lock";
 export const EXCHANGE_RESERVES_LOCK = "exchange-reserves-lock";
@@ -168,9 +169,7 @@ export interface InternalWalletState {
   timerGroup: TimerGroup;
   stopped: boolean;
 
-  insecureTrustExchange: boolean;
-
-  batchWithdrawal: boolean;
+  config: Readonly<WalletConfig>;
 
   /**
    * Asynchronous condition to interrupt the sleep of the
@@ -191,8 +190,6 @@ export interface InternalWalletState {
   merchantOps: MerchantOperations;
   refreshOps: RefreshOperations;
 
-  devModeActive: boolean;
-
   getDenomInfo(
     ws: InternalWalletState,
     tx: GetReadOnlyAccess<{
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts 
b/packages/taler-wallet-core/src/operations/deposits.ts
index d1dbf5f53..700b875d3 100644
--- a/packages/taler-wallet-core/src/operations/deposits.ts
+++ b/packages/taler-wallet-core/src/operations/deposits.ts
@@ -840,7 +840,12 @@ export async function getTotalFeesForDepositAmount(
           denom.value,
           pcs.coinContributions[i],
         ).amount;
-        const refreshCost = getTotalRefreshCost(allDenoms, denom, amountLeft);
+        const refreshCost = getTotalRefreshCost(
+          allDenoms,
+          denom,
+          amountLeft,
+          ws.config.testing.denomselAllowLate,
+        );
         refreshFee.push(refreshCost);
       }
 
diff --git a/packages/taler-wallet-core/src/operations/exchanges.ts 
b/packages/taler-wallet-core/src/operations/exchanges.ts
index d9051b32f..b5e02e64d 100644
--- a/packages/taler-wallet-core/src/operations/exchanges.ts
+++ b/packages/taler-wallet-core/src/operations/exchanges.ts
@@ -245,7 +245,7 @@ async function validateWireInfo(
   for (const a of wireInfo.accounts) {
     logger.trace("validating exchange acct");
     let isValid = false;
-    if (ws.insecureTrustExchange) {
+    if (ws.config.testing.insecureTrustExchange) {
       isValid = true;
     } else {
       const { valid: v } = await ws.cryptoApi.isValidWireAccount({
@@ -275,7 +275,7 @@ async function validateWireInfo(
         wireFee: Amounts.stringify(x.wire_fee),
       };
       let isValid = false;
-      if (ws.insecureTrustExchange) {
+      if (ws.config.testing.insecureTrustExchange) {
         isValid = true;
       } else {
         const { valid: v } = await ws.cryptoApi.isValidWireFee({
@@ -308,7 +308,7 @@ async function validateGlobalFees(
   for (const gf of fees) {
     logger.trace("validating exchange global fees");
     let isValid = false;
-    if (ws.insecureTrustExchange) {
+    if (ws.config.testing.insecureTrustExchange) {
       isValid = true;
     } else {
       const { valid: v } = await ws.cryptoApi.isValidGlobalFees({
@@ -665,7 +665,10 @@ export async function updateExchangeFromUrlHandler(
 
   let ageMask = 0;
   for (const x of keysInfo.currentDenominations) {
-    if (isWithdrawableDenom(x) && x.denomPub.age_mask != 0) {
+    if (
+      isWithdrawableDenom(x, ws.config.testing.denomselAllowLate) &&
+      x.denomPub.age_mask != 0
+    ) {
       ageMask = x.denomPub.age_mask;
       break;
     }
diff --git a/packages/taler-wallet-core/src/operations/pay-merchant.ts 
b/packages/taler-wallet-core/src/operations/pay-merchant.ts
index 496641fe7..2419d32a2 100644
--- a/packages/taler-wallet-core/src/operations/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/operations/pay-merchant.ts
@@ -168,6 +168,7 @@ export async function getTotalPaymentCost(
           allDenoms,
           DenominationRecord.toDenomInfo(denom),
           amountLeft,
+          ws.config.testing.denomselAllowLate,
         );
         costs.push(Amounts.parseOrThrow(pcs.coinContributions[i]));
         costs.push(refreshCost);
@@ -1659,6 +1660,7 @@ async function applySuccessfulRefund(
   p: PurchaseRecord,
   refreshCoinsMap: Record<string, CoinRefreshRequest>,
   r: MerchantCoinRefundSuccessStatus,
+  denomselAllowLate: boolean,
 ): Promise<void> {
   // FIXME: check signature before storing it as valid!
 
@@ -1688,6 +1690,7 @@ async function applySuccessfulRefund(
     allDenoms,
     DenominationRecord.toDenomInfo(denom),
     amountLeft,
+    denomselAllowLate,
   );
 
   refreshCoinsMap[coin.coinPub] = {
@@ -1714,6 +1717,7 @@ async function storePendingRefund(
   }>,
   p: PurchaseRecord,
   r: MerchantCoinRefundFailureStatus,
+  denomselAllowLate: boolean,
 ): Promise<void> {
   const refundKey = getRefundKey(r);
 
@@ -1745,6 +1749,7 @@ async function storePendingRefund(
     allDenoms,
     DenominationRecord.toDenomInfo(denom),
     amountLeft,
+    denomselAllowLate,
   );
 
   p.refunds[refundKey] = {
@@ -1767,6 +1772,7 @@ async function storeFailedRefund(
   p: PurchaseRecord,
   refreshCoinsMap: Record<string, CoinRefreshRequest>,
   r: MerchantCoinRefundFailureStatus,
+  denomselAllowLate: boolean,
 ): Promise<void> {
   const refundKey = getRefundKey(r);
 
@@ -1797,6 +1803,7 @@ async function storeFailedRefund(
     allDenoms,
     DenominationRecord.toDenomInfo(denom),
     amountLeft,
+    denomselAllowLate,
   );
 
   p.refunds[refundKey] = {
@@ -1905,11 +1912,28 @@ async function acceptRefunds(
         // Invariant: (!existingRefundInfo) || (existingRefundInfo === Pending)
 
         if (refundStatus.type === "success") {
-          await applySuccessfulRefund(tx, p, refreshCoinsMap, refundStatus);
+          await applySuccessfulRefund(
+            tx,
+            p,
+            refreshCoinsMap,
+            refundStatus,
+            ws.config.testing.denomselAllowLate,
+          );
         } else if (isPermanentFailure) {
-          await storeFailedRefund(tx, p, refreshCoinsMap, refundStatus);
+          await storeFailedRefund(
+            tx,
+            p,
+            refreshCoinsMap,
+            refundStatus,
+            ws.config.testing.denomselAllowLate,
+          );
         } else {
-          await storePendingRefund(tx, p, refundStatus);
+          await storePendingRefund(
+            tx,
+            p,
+            refundStatus,
+            ws.config.testing.denomselAllowLate,
+          );
         }
       }
 
diff --git a/packages/taler-wallet-core/src/operations/pay-peer.ts 
b/packages/taler-wallet-core/src/operations/pay-peer.ts
index ebf521079..33659afe0 100644
--- a/packages/taler-wallet-core/src/operations/pay-peer.ts
+++ b/packages/taler-wallet-core/src/operations/pay-peer.ts
@@ -417,6 +417,7 @@ export async function getTotalPeerPaymentCost(
           allDenoms,
           DenominationRecord.toDenomInfo(denom),
           amountLeft,
+          ws.config.testing.denomselAllowLate,
         );
         costs.push(Amounts.parseOrThrow(pcs[i].contribution));
         costs.push(refreshCost);
diff --git a/packages/taler-wallet-core/src/operations/refresh.ts 
b/packages/taler-wallet-core/src/operations/refresh.ts
index 70f0579c0..3122c9685 100644
--- a/packages/taler-wallet-core/src/operations/refresh.ts
+++ b/packages/taler-wallet-core/src/operations/refresh.ts
@@ -86,7 +86,7 @@ import {
 import { makeCoinAvailable } from "./common.js";
 import { updateExchangeFromUrl } from "./exchanges.js";
 import { selectWithdrawalDenominations } from "../util/coinSelection.js";
-import { isWithdrawableDenom } from "../index.js";
+import { isWithdrawableDenom, WalletConfig } from "../index.js";
 
 const logger = new Logger("refresh.ts");
 
@@ -105,13 +105,18 @@ export function getTotalRefreshCost(
   denoms: DenominationRecord[],
   refreshedDenom: DenominationInfo,
   amountLeft: AmountJson,
+  denomselAllowLate: boolean,
 ): AmountJson {
   const withdrawAmount = Amounts.sub(
     amountLeft,
     refreshedDenom.feeRefresh,
   ).amount;
   const denomMap = Object.fromEntries(denoms.map((x) => [x.denomPubHash, x]));
-  const withdrawDenoms = selectWithdrawalDenominations(withdrawAmount, denoms);
+  const withdrawDenoms = selectWithdrawalDenominations(
+    withdrawAmount,
+    denoms,
+    denomselAllowLate,
+  );
   const resultingAmount = Amounts.add(
     Amounts.zeroOfCurrency(withdrawAmount.currency),
     ...withdrawDenoms.selectedDenoms.map(
@@ -232,6 +237,7 @@ async function refreshCreateSession(
   const newCoinDenoms = selectWithdrawalDenominations(
     availableAmount,
     availableDenoms,
+    ws.config.testing.denomselAllowLate,
   );
 
   if (newCoinDenoms.selectedDenoms.length === 0) {
@@ -897,7 +903,7 @@ export async function createRefreshGroup(
     const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl
       .iter(exchangeBaseUrl)
       .filter((x) => {
-        return isWithdrawableDenom(x);
+        return isWithdrawableDenom(x, ws.config.testing.denomselAllowLate);
       });
     denomsPerExchange[exchangeBaseUrl] = allDenoms;
     return allDenoms;
@@ -955,6 +961,7 @@ export async function createRefreshGroup(
       denoms,
       denom,
       Amounts.parseOrThrow(refreshAmount),
+      ws.config.testing.denomselAllowLate,
     );
     const output = Amounts.sub(refreshAmount, cost).amount;
     estimatedOutputPerCoin.push(output);
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts 
b/packages/taler-wallet-core/src/operations/withdraw.ts
index 643737e93..23c3e6713 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -210,7 +210,9 @@ export async function getCandidateWithdrawalDenoms(
       const allDenoms = await 
tx.denominations.indexes.byExchangeBaseUrl.getAll(
         exchangeBaseUrl,
       );
-      return allDenoms.filter(isWithdrawableDenom);
+      return allDenoms.filter((d) =>
+        isWithdrawableDenom(d, ws.config.testing.denomselAllowLate),
+      );
     });
 }
 
@@ -719,7 +721,7 @@ export async function updateWithdrawalDenoms(
           }) signature of ${denom.denomPubHash}`,
         );
         let valid = false;
-        if (ws.insecureTrustExchange) {
+        if (ws.config.testing.insecureTrustExchange) {
           valid = true;
         } else {
           const res = await ws.cryptoApi.isValidDenom({
@@ -1003,7 +1005,7 @@ export async function processWithdrawalGroup(
     const resp = await processPlanchetExchangeBatchRequest(ws, wgContext, {
       batchSize: maxBatchSize,
       coinStartIndex: i,
-      useBatchRequest: ws.batchWithdrawal,
+      useBatchRequest: ws.config.features.batchWithdrawal,
     });
     let work: Promise<void>[] = [];
     work = [];
@@ -1180,6 +1182,7 @@ export async function getExchangeWithdrawalInfo(
   const selectedDenoms = selectWithdrawalDenominations(
     instructedAmount,
     denoms,
+    ws.config.testing.denomselAllowLate,
   );
 
   if (selectedDenoms.selectedDenoms.length === 0) {
@@ -1710,9 +1713,14 @@ export async function internalCreateWithdrawalGroup(
       amount,
       denoms,
       args.forcedDenomSel,
+      ws.config.testing.denomselAllowLate,
     );
   } else {
-    initialDenomSel = selectWithdrawalDenominations(amount, denoms);
+    initialDenomSel = selectWithdrawalDenominations(
+      amount,
+      denoms,
+      ws.config.testing.denomselAllowLate,
+    );
   }
 
   const withdrawalGroup: WithdrawalGroupRecord = {
diff --git a/packages/taler-wallet-core/src/util/coinSelection.ts 
b/packages/taler-wallet-core/src/util/coinSelection.ts
index 176d636fc..3b986d72b 100644
--- a/packages/taler-wallet-core/src/util/coinSelection.ts
+++ b/packages/taler-wallet-core/src/util/coinSelection.ts
@@ -48,7 +48,11 @@ import {
   AllowedExchangeInfo,
   DenominationRecord,
 } from "../db.js";
-import { getExchangeDetails, isWithdrawableDenom } from "../index.js";
+import {
+  getExchangeDetails,
+  isWithdrawableDenom,
+  WalletConfig,
+} from "../index.js";
 import { InternalWalletState } from "../internal-wallet-state.js";
 import { getMerchantPaymentBalanceDetails } from "../operations/balance.js";
 import { checkDbInvariant, checkLogicInvariant } from "./invariants.js";
@@ -664,6 +668,7 @@ export async function selectCandidates(
 export function selectWithdrawalDenominations(
   amountAvailable: AmountJson,
   denoms: DenominationRecord[],
+  denomselAllowLate: boolean = false,
 ): DenomSelectionState {
   let remaining = Amounts.copy(amountAvailable);
 
@@ -675,7 +680,7 @@ export function selectWithdrawalDenominations(
   let totalCoinValue = Amounts.zeroOfCurrency(amountAvailable.currency);
   let totalWithdrawCost = Amounts.zeroOfCurrency(amountAvailable.currency);
 
-  denoms = denoms.filter(isWithdrawableDenom);
+  denoms = denoms.filter((d) => isWithdrawableDenom(d, denomselAllowLate));
   denoms.sort((d1, d2) =>
     Amounts.cmp(
       DenominationRecord.getValue(d2),
@@ -737,6 +742,7 @@ export function selectForcedWithdrawalDenominations(
   amountAvailable: AmountJson,
   denoms: DenominationRecord[],
   forcedDenomSel: ForcedDenomSel,
+  denomselAllowLate: boolean,
 ): DenomSelectionState {
   const selectedDenoms: {
     count: number;
@@ -746,7 +752,7 @@ export function selectForcedWithdrawalDenominations(
   let totalCoinValue = Amounts.zeroOfCurrency(amountAvailable.currency);
   let totalWithdrawCost = Amounts.zeroOfCurrency(amountAvailable.currency);
 
-  denoms = denoms.filter(isWithdrawableDenom);
+  denoms = denoms.filter((d) => isWithdrawableDenom(d, denomselAllowLate));
   denoms.sort((d1, d2) =>
     Amounts.cmp(
       DenominationRecord.getValue(d2),
diff --git a/packages/taler-wallet-core/src/util/debugFlags.ts 
b/packages/taler-wallet-core/src/util/debugFlags.ts
deleted file mode 100644
index cea249d27..000000000
--- a/packages/taler-wallet-core/src/util/debugFlags.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- * Debug flags for wallet-core.
- *
- * @author Florian Dold
- */
-
-export interface WalletCoreDebugFlags {
-  /**
-   * Allow withdrawal of denominations even though they are about to expire.
-   */
-  denomselAllowLate: boolean;
-}
-
-export const walletCoreDebugFlags: WalletCoreDebugFlags = {
-  denomselAllowLate: false,
-};
diff --git a/packages/taler-wallet-core/src/util/denominations.ts 
b/packages/taler-wallet-core/src/util/denominations.ts
index fb766e96a..5cc57bdab 100644
--- a/packages/taler-wallet-core/src/util/denominations.ts
+++ b/packages/taler-wallet-core/src/util/denominations.ts
@@ -29,7 +29,7 @@ import {
   WireFee,
 } from "@gnu-taler/taler-util";
 import { DenominationRecord } from "../db.js";
-import { walletCoreDebugFlags } from "./debugFlags.js";
+import { WalletConfig } from "../index.js";
 
 /**
  * Given a list of denominations with the same value and same period of time:
@@ -452,13 +452,16 @@ export function createTimeline<Type extends object>(
  * Check if a denom is withdrawable based on the expiration time,
  * revocation and offered state.
  */
-export function isWithdrawableDenom(d: DenominationRecord): boolean {
+export function isWithdrawableDenom(
+  d: DenominationRecord,
+  denomselAllowLate?: boolean,
+): boolean {
   const now = AbsoluteTime.now();
   const start = AbsoluteTime.fromTimestamp(d.stampStart);
   const withdrawExpire = AbsoluteTime.fromTimestamp(d.stampExpireWithdraw);
   const started = AbsoluteTime.cmp(now, start) >= 0;
   let lastPossibleWithdraw: AbsoluteTime;
-  if (walletCoreDebugFlags.denomselAllowLate) {
+  if (denomselAllowLate) {
     lastPossibleWithdraw = start;
   } else {
     lastPossibleWithdraw = AbsoluteTime.subtractDuraction(
diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts 
b/packages/taler-wallet-core/src/wallet-api-types.ts
index 2ac649f59..94348f095 100644
--- a/packages/taler-wallet-core/src/wallet-api-types.ts
+++ b/packages/taler-wallet-core/src/wallet-api-types.ts
@@ -29,8 +29,6 @@ import {
   AcceptExchangeTosRequest,
   AcceptManualWithdrawalRequest,
   AcceptManualWithdrawalResult,
-  ConfirmPeerPullDebitRequest,
-  ConfirmPeerPushCreditRequest,
   AcceptTipRequest,
   AcceptTipResponse,
   AcceptWithdrawalResponse,
@@ -42,17 +40,18 @@ import {
   ApplyRefundResponse,
   BackupRecovery,
   BalancesResponse,
-  PreparePeerPullDebitRequest,
-  PreparePeerPullDebitResponse,
-  PreparePeerPushCredit,
-  PreparePeerPushCreditResponse,
+  CheckPeerPullCreditRequest,
+  CheckPeerPullCreditResponse,
+  CheckPeerPushDebitRequest,
+  CheckPeerPushDebitResponse,
   CoinDumpJson,
   ConfirmPayRequest,
   ConfirmPayResult,
+  ConfirmPeerPullDebitRequest,
+  ConfirmPeerPushCreditRequest,
   CreateDepositGroupRequest,
   CreateDepositGroupResponse,
   DeleteTransactionRequest,
-  DepositGroupFees,
   ExchangeDetailedResponse,
   ExchangesListResponse,
   ForceRefreshRequest,
@@ -63,12 +62,12 @@ import {
   GetExchangeTosResult,
   GetWithdrawalDetailsForAmountRequest,
   GetWithdrawalDetailsForUriRequest,
+  InitRequest,
+  InitResponse,
   InitiatePeerPullCreditRequest,
   InitiatePeerPullCreditResponse,
   InitiatePeerPushPaymentRequest,
   InitiatePeerPushPaymentResponse,
-  InitRequest,
-  InitResponse,
   IntegrationTestArgs,
   KnownBankAccounts,
   ListKnownBankAccountsRequest,
@@ -78,10 +77,10 @@ import {
   PreparePayRequest,
   PreparePayResult,
   PreparePayTemplateRequest,
-  CheckPeerPullCreditRequest,
-  CheckPeerPullCreditResponse,
-  CheckPeerPushDebitRequest,
-  CheckPeerPushDebitResponse,
+  PreparePeerPullDebitRequest,
+  PreparePeerPullDebitResponse,
+  PreparePeerPushCredit,
+  PreparePeerPushCreditResponse,
   PrepareRefundRequest,
   PrepareRefundResult,
   PrepareTipRequest,
@@ -89,7 +88,6 @@ import {
   RecoveryLoadRequest,
   RetryTransactionRequest,
   SetCoinSuspendedRequest,
-  SetDevModeRequest,
   SetWalletDeviceIdRequest,
   TestPayArgs,
   TestPayResult,
@@ -97,21 +95,21 @@ import {
   TransactionByIdRequest,
   TransactionsRequest,
   TransactionsResponse,
+  TxIdResponse,
   UserAttentionByIdRequest,
   UserAttentionsCountResponse,
   UserAttentionsRequest,
   UserAttentionsResponse,
+  ValidateIbanRequest,
+  ValidateIbanResponse,
   WalletBackupContentV1,
   WalletCoreVersion,
   WalletCurrencyInfo,
   WithdrawFakebankRequest,
   WithdrawTestBalanceRequest,
   WithdrawUriInfoResponse,
-  ValidateIbanRequest,
-  ValidateIbanResponse,
-  TxIdResponse,
 } from "@gnu-taler/taler-util";
-import { WalletContractData } from "./db.js";
+import { AuditorTrustRecord, WalletContractData } from "./db.js";
 import {
   AddBackupProviderRequest,
   AddBackupProviderResponse,
@@ -195,13 +193,11 @@ export enum WalletApiOperation {
   ConfirmPeerPullDebit = "confirmPeerPullDebit",
   ClearDb = "clearDb",
   Recycle = "recycle",
-  SetDevMode = "setDevMode",
   ApplyDevExperiment = "applyDevExperiment",
   ValidateIban = "validateIban",
 }
 
 // group: Initialization
-
 type EmptyObject = Record<string, never>;
 /**
  * Initialize wallet-core.
@@ -739,12 +735,6 @@ export type ApplyDevExperimentOp = {
   response: EmptyObject;
 };
 
-export type SetDevModeOp = {
-  op: WalletApiOperation.SetDevMode;
-  request: SetDevModeRequest;
-  response: EmptyObject;
-};
-
 /**
  * Run a simple integration test on a test deployment
  * of the exchange and merchant.
@@ -953,7 +943,6 @@ export type WalletOperations = {
   [WalletApiOperation.ClearDb]: ClearDbOp;
   [WalletApiOperation.Recycle]: RecycleOp;
   [WalletApiOperation.ApplyDevExperiment]: ApplyDevExperimentOp;
-  [WalletApiOperation.SetDevMode]: SetDevModeOp;
   [WalletApiOperation.ValidateIban]: ValidateIbanOp;
 };
 
@@ -973,3 +962,50 @@ export interface WalletCoreApiClient {
     payload: WalletCoreRequestType<Op>,
   ): Promise<WalletCoreResponseType<Op>>;
 }
+
+type Primitives = string | number | boolean;
+
+export type RecursivePartial<T extends object> = {
+  [P in keyof T]?: T[P] extends Array<infer U extends object>
+    ? Array<RecursivePartial<U>>
+    : T[P] extends Array<infer J extends Primitives>
+    ? Array<J>
+    : T[P] extends object
+    ? RecursivePartial<T[P]>
+    : T[P];
+} & object;
+
+export type WalletConfigParameter = RecursivePartial<WalletConfig>;
+
+export interface WalletConfig {
+  /**
+   * Initialization values useful for a complete startup.
+   *
+   * These are values may be overridden by different wallets
+   */
+  builtin: {
+    exchanges: string[];
+    auditors: AuditorTrustRecord[];
+  };
+
+  /**
+   * Unsafe options which it should only be used to create
+   * testing environment.
+   */
+  testing: {
+    /**
+     * Allow withdrawal of denominations even though they are about to expire.
+     */
+    denomselAllowLate: boolean;
+    devModeActive: boolean;
+    insecureTrustExchange: boolean;
+  };
+
+  /**
+   * Configurations values that may be safe to show to the user
+   */
+  features: {
+    batchWithdrawal: boolean;
+    allowHttp: boolean;
+  };
+}
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index d6d64b5c9..45b33ce45 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -25,12 +25,38 @@
 import {
   AbsoluteTime,
   Amounts,
+  CoinDumpJson,
+  CoinRefreshRequest,
+  CoinStatus,
+  CoreApiResponse,
+  DenomOperationMap,
+  DenominationInfo,
+  Duration,
+  ExchangeDetailedResponse,
+  ExchangeListItem,
+  ExchangeTosStatusDetails,
+  ExchangesListResponse,
+  FeeDescription,
+  GetExchangeTosResult,
+  InitResponse,
+  KnownBankAccounts,
+  KnownBankAccountsInfo,
+  Logger,
+  ManualWithdrawalDetails,
+  MerchantUsingTemplateDetails,
+  NotificationType,
+  RefreshReason,
+  TalerError,
+  TalerErrorCode,
+  URL,
+  ValidateIbanResponse,
+  WalletCoreVersion,
+  WalletNotification,
   codecForAbortTransaction,
   codecForAcceptBankIntegratedWithdrawalRequest,
   codecForAcceptExchangeTosRequest,
   codecForAcceptManualWithdrawalRequet,
   codecForAcceptPeerPullPaymentRequest,
-  codecForConfirmPeerPushPaymentRequest,
   codecForAcceptTipRequest,
   codecForAddExchangeRequest,
   codecForAddKnownBankAccounts,
@@ -39,8 +65,9 @@ import {
   codecForApplyRefundFromPurchaseIdRequest,
   codecForApplyRefundRequest,
   codecForCheckPeerPullPaymentRequest,
-  codecForPreparePeerPushCreditRequest,
+  codecForCheckPeerPushDebitRequest,
   codecForConfirmPayRequest,
+  codecForConfirmPeerPushPaymentRequest,
   codecForCreateDepositGroupRequest,
   codecForDeleteTransactionRequest,
   codecForForceRefreshRequest,
@@ -54,86 +81,58 @@ import {
   codecForInitiatePeerPullPaymentRequest,
   codecForInitiatePeerPushPaymentRequest,
   codecForIntegrationTestArgs,
+  codecForIntegrationTestV2Args,
   codecForListKnownBankAccounts,
   codecForMerchantPostOrderResponse,
   codecForPrepareDepositRequest,
   codecForPreparePayRequest,
   codecForPreparePayTemplateRequest,
   codecForPreparePeerPullPaymentRequest,
-  codecForCheckPeerPushDebitRequest,
+  codecForPreparePeerPushCreditRequest,
   codecForPrepareRefundRequest,
   codecForPrepareTipRequest,
+  codecForResumeTransaction,
   codecForRetryTransactionRequest,
   codecForSetCoinSuspendedRequest,
-  codecForSetDevModeRequest,
   codecForSetWalletDeviceIdRequest,
+  codecForSuspendTransaction,
   codecForTestPayArgs,
   codecForTransactionByIdRequest,
   codecForTransactionsRequest,
   codecForUserAttentionByIdRequest,
   codecForUserAttentionsRequest,
+  codecForValidateIbanRequest,
   codecForWithdrawFakebankRequest,
   codecForWithdrawTestBalance,
-  CoinDumpJson,
-  CoinRefreshRequest,
-  CoinStatus,
   constructPayUri,
-  CoreApiResponse,
-  DenominationInfo,
-  DenomOperationMap,
-  Duration,
   durationFromSpec,
   durationMin,
-  ExchangeDetailedResponse,
-  ExchangeListItem,
-  ExchangesListResponse,
-  ExchangeTosStatusDetails,
-  FeeDescription,
-  GetExchangeTosResult,
-  InitResponse,
+  getErrorDetailFromException,
   j2s,
-  KnownBankAccounts,
-  KnownBankAccountsInfo,
-  Logger,
-  ManualWithdrawalDetails,
-  MerchantUsingTemplateDetails,
-  NotificationType,
   parsePayTemplateUri,
   parsePaytoUri,
-  RefreshReason,
-  TalerErrorCode,
-  URL,
-  WalletCoreVersion,
-  WalletNotification,
-  codecForSuspendTransaction,
-  codecForResumeTransaction,
   validateIban,
-  codecForValidateIbanRequest,
-  ValidateIbanResponse,
-  codecForIntegrationTestV2Args,
 } from "@gnu-taler/taler-util";
+import {
+  HttpRequestLibrary,
+  readSuccessResponseJsonOrThrow,
+} from "@gnu-taler/taler-util/http";
 import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
 import {
   CryptoDispatcher,
   CryptoWorkerFactory,
 } from "./crypto/workers/crypto-dispatcher.js";
 import {
-  AuditorTrustRecord,
-  clearDatabase,
   CoinSourceType,
   ConfigRecordKey,
   DenominationRecord,
   ExchangeDetailsRecord,
+  WalletStoresV1,
+  clearDatabase,
   exportDb,
   importDb,
-  WalletStoresV1,
 } from "./db.js";
-import {
-  applyDevExperiment,
-  maybeInitDevMode,
-  setDevMode,
-} from "./dev-experiments.js";
-import { getErrorDetailFromException, TalerError } from 
"@gnu-taler/taler-util";
+import { DevExperimentHttpLib, applyDevExperiment } from 
"./dev-experiments.js";
 import {
   ActiveLongpollInfo,
   ExchangeOperations,
@@ -198,18 +197,18 @@ import {
   processPurchase,
 } from "./operations/pay-merchant.js";
 import {
+  checkPeerPullPaymentInitiation,
+  checkPeerPushDebit,
   confirmPeerPullDebit,
   confirmPeerPushCredit,
-  preparePeerPullDebit,
-  preparePeerPushCredit,
   initiatePeerPullPayment,
   initiatePeerPushPayment,
-  checkPeerPullPaymentInitiation,
-  checkPeerPushDebit,
+  preparePeerPullDebit,
+  preparePeerPushCredit,
   processPeerPullCredit,
-  processPeerPushInitiation,
   processPeerPullDebit,
   processPeerPushCredit,
+  processPeerPushInitiation,
 } from "./operations/pay-peer.js";
 import { getPendingOperations } from "./operations/pending.js";
 import {
@@ -252,10 +251,6 @@ import {
   selectBestForOverlappingDenominations,
   selectMinimumFee,
 } from "./util/denominations.js";
-import {
-  HttpRequestLibrary,
-  readSuccessResponseJsonOrThrow,
-} from "@gnu-taler/taler-util/http";
 import { checkDbInvariant } from "./util/invariants.js";
 import {
   AsyncCondition,
@@ -275,22 +270,14 @@ import {
   WALLET_MERCHANT_PROTOCOL_VERSION,
 } from "./versions.js";
 import {
+  RecursivePartial,
   WalletApiOperation,
+  WalletConfig,
+  WalletConfigParameter,
   WalletCoreApiClient,
   WalletCoreResponseType,
 } from "./wallet-api-types.js";
 
-const builtinAuditors: AuditorTrustRecord[] = [
-  {
-    currency: "KUDOS",
-    auditorPub: "BW9DC48PHQY4NH011SHHX36DZZ3Q22Y6X7FZ1VD1CMZ2PTFZ6PN0",
-    auditorBaseUrl: "https://auditor.demo.taler.net/";,
-    uids: ["5P25XF8TVQP9AW6VYGY2KV47WT5Y3ZXFSJAA570GJPX5SVJXKBVG"],
-  },
-];
-
-const builtinExchanges: string[] = ["https://exchange.demo.taler.net/";];
-
 const logger = new Logger("wallet.ts");
 
 /**
@@ -495,10 +482,10 @@ async function fillDefaults(ws: InternalWalletState): 
Promise<void> {
         return;
       }
       logger.info("importing default exchanges and auditors");
-      for (const c of builtinAuditors) {
+      for (const c of ws.config.builtin.auditors) {
         await tx.auditorTrust.put(c);
       }
-      for (const baseUrl of builtinExchanges) {
+      for (const baseUrl of ws.config.builtin.exchanges) {
         const now = AbsoluteTime.now();
         provideExchangeRecordInTx(ws, tx, baseUrl, now);
       }
@@ -1018,7 +1005,6 @@ async function dispatchRequestInternal<Op extends 
WalletApiOperation>(
         logger.trace("filling defaults");
         await fillDefaults(ws);
       }
-      await maybeInitDevMode(ws);
       const resp: InitResponse = {
         versionInfo: getVersion(ws),
       };
@@ -1482,15 +1468,10 @@ async function dispatchRequestInternal<Op extends 
WalletApiOperation>(
       await applyDevExperiment(ws, req.devExperimentUri);
       return {};
     }
-    case WalletApiOperation.SetDevMode: {
-      const req = codecForSetDevModeRequest().decode(payload);
-      await setDevMode(ws, req.devModeEnabled);
-      return {};
-    }
     case WalletApiOperation.GetVersion: {
       return getVersion(ws);
     }
-    //default:
+    // default:
     //  assertUnreachable(operation);
   }
   throw TalerError.fromDetail(
@@ -1509,7 +1490,7 @@ export function getVersion(ws: InternalWalletState): 
WalletCoreVersion {
     exchange: WALLET_EXCHANGE_PROTOCOL_VERSION,
     merchant: WALLET_MERCHANT_PROTOCOL_VERSION,
     bank: WALLET_BANK_INTEGRATION_PROTOCOL_VERSION,
-    devMode: ws.devModeActive,
+    devMode: false,
   };
   return version;
 }
@@ -1575,8 +1556,15 @@ export class Wallet {
     http: HttpRequestLibrary,
     timer: TimerAPI,
     cryptoWorkerFactory: CryptoWorkerFactory,
+    config?: WalletConfigParameter,
   ) {
-    this.ws = new InternalWalletStateImpl(db, http, timer, 
cryptoWorkerFactory);
+    this.ws = new InternalWalletStateImpl(
+      db,
+      http,
+      timer,
+      cryptoWorkerFactory,
+      config ?? {},
+    );
   }
 
   get client(): WalletCoreApiClient {
@@ -1586,29 +1574,22 @@ export class Wallet {
     return this._client;
   }
 
-  /**
-   * Trust the exchange, do not validate signatures.
-   * Only used to benchmark the exchange.
-   */
-  setInsecureTrustExchange(): void {
-    this.ws.insecureTrustExchange = true;
-  }
-
-  setBatchWithdrawal(enable: boolean): void {
-    this.ws.batchWithdrawal = enable;
-  }
-
   static async create(
     db: DbAccess<typeof WalletStoresV1>,
     http: HttpRequestLibrary,
     timer: TimerAPI,
     cryptoWorkerFactory: CryptoWorkerFactory,
+    config?: WalletConfigParameter,
   ): Promise<Wallet> {
-    const w = new Wallet(db, http, timer, cryptoWorkerFactory);
+    const w = new Wallet(db, http, timer, cryptoWorkerFactory, config);
     w._client = await getClientFromWalletState(w.ws);
     return w;
   }
 
+  static getDefaultConfig(): Readonly<WalletConfig> {
+    return InternalWalletStateImpl.defaultConfig;
+  }
+
   addNotificationListener(f: (n: WalletNotification) => void): void {
     return this.ws.addNotificationListener(f);
   }
@@ -1650,10 +1631,6 @@ class InternalWalletStateImpl implements 
InternalWalletState {
 
   merchantInfoCache: Record<string, MerchantInfo> = {};
 
-  insecureTrustExchange = false;
-
-  batchWithdrawal = false;
-
   readonly timerGroup: TimerGroup;
   latch = new AsyncCondition();
   stopped = false;
@@ -1662,8 +1639,6 @@ class InternalWalletStateImpl implements 
InternalWalletState {
 
   initCalled = false;
 
-  devModeActive = false;
-
   exchangeOps: ExchangeOperations = {
     getExchangeDetails,
     getExchangeTrust,
@@ -1696,6 +1671,31 @@ class InternalWalletStateImpl implements 
InternalWalletState {
    */
   private resourceLocks: Set<string> = new Set();
 
+  config: Readonly<WalletConfig>;
+
+  public static defaultConfig: Readonly<WalletConfig> = {
+    builtin: {
+      exchanges: ["https://exchange.demo.taler.net/";],
+      auditors: [
+        {
+          currency: "KUDOS",
+          auditorPub: "BW9DC48PHQY4NH011SHHX36DZZ3Q22Y6X7FZ1VD1CMZ2PTFZ6PN0",
+          auditorBaseUrl: "https://auditor.demo.taler.net/";,
+          uids: ["5P25XF8TVQP9AW6VYGY2KV47WT5Y3ZXFSJAA570GJPX5SVJXKBVG"],
+        },
+      ],
+    },
+    features: {
+      batchWithdrawal: false,
+      allowHttp: false,
+    },
+    testing: {
+      devModeActive: false,
+      insecureTrustExchange: false,
+      denomselAllowLate: false,
+    },
+  };
+
   constructor(
     // FIXME: Make this a getter and make
     // the actual value nullable.
@@ -1705,10 +1705,15 @@ class InternalWalletStateImpl implements 
InternalWalletState {
     public http: HttpRequestLibrary,
     public timer: TimerAPI,
     cryptoWorkerFactory: CryptoWorkerFactory,
+    config: WalletConfigParameter,
   ) {
     this.cryptoDispatcher = new CryptoDispatcher(cryptoWorkerFactory);
     this.cryptoApi = this.cryptoDispatcher.cryptoApi;
     this.timerGroup = new TimerGroup(timer);
+    this.config = deepMerge(InternalWalletStateImpl.defaultConfig, config);
+    if (this.config.testing.devModeActive) {
+      this.http = new DevExperimentHttpLib(this.http);
+    }
   }
 
   async getDenomInfo(
@@ -1808,3 +1813,29 @@ class InternalWalletStateImpl implements 
InternalWalletState {
     }
   }
 }
+
+/**
+ * Take the full object as template, create a new result with all the values.
+ * Use the override object to change the values in the result
+ * return result
+ * @param full
+ * @param override
+ * @returns
+ */
+function deepMerge<T extends object>(
+  full: T,
+  override: RecursivePartial<T>,
+): T {
+  const keys = Object.keys(full);
+  const result = { ...full };
+  for (const k of keys) {
+    // @ts-ignore
+    const newVal = override[k];
+    if (newVal === undefined) continue;
+    // @ts-ignore
+    result[k] =
+      // @ts-ignore
+      typeof newVal === "object" ? deepMerge(full[k], newVal) : newVal;
+  }
+  return result;
+}
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx 
b/packages/taler-wallet-webextension/src/NavigationBar.tsx
index d6b22ba28..806646a02 100644
--- a/packages/taler-wallet-webextension/src/NavigationBar.tsx
+++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx
@@ -26,7 +26,7 @@
  */
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
 import { Fragment, h, VNode } from "preact";
-import { JustInDevMode } from "./components/JustInDevMode.js";
+import { EnabledBySettings } from "./components/EnabledBySettings.js";
 import {
   NavigationHeader,
   NavigationHeaderHolder,
@@ -183,11 +183,11 @@ export function PopupNavBar({ path }: { path?: 
PopupNavBarOptions }): VNode {
       <a href={Pages.balance} class={path === "balance" ? "active" : ""}>
         <i18n.Translate>Balance</i18n.Translate>
       </a>
-      <JustInDevMode>
+      <EnabledBySettings name="backup">
         <a href={Pages.backup} class={path === "backup" ? "active" : ""}>
           <i18n.Translate>Backup</i18n.Translate>
         </a>
-      </JustInDevMode>
+      </EnabledBySettings>
       <div style={{ display: "flex", paddingTop: 4, justifyContent: "right" }}>
         {attentionCount > 0 ? (
           <a href={Pages.notifications}>
@@ -238,11 +238,11 @@ export function WalletNavBar({ path }: { path?: 
WalletNavBarOptions }): VNode {
         <a href={Pages.balance} class={path === "balance" ? "active" : ""}>
           <i18n.Translate>Balance</i18n.Translate>
         </a>
-        <JustInDevMode>
+        <EnabledBySettings name="backup">
           <a href={Pages.backup} class={path === "backup" ? "active" : ""}>
             <i18n.Translate>Backup</i18n.Translate>
           </a>
-        </JustInDevMode>
+        </EnabledBySettings>
 
         {attentionCount > 0 ? (
           <a href={Pages.notifications}>
@@ -252,11 +252,11 @@ export function WalletNavBar({ path }: { path?: 
WalletNavBarOptions }): VNode {
           <Fragment />
         )}
 
-        <JustInDevMode>
+        <EnabledBySettings name="advanceMode">
           <a href={Pages.dev} class={path === "dev" ? "active" : ""}>
-            <i18n.Translate>Dev</i18n.Translate>
+            <i18n.Translate>Dev tools</i18n.Translate>
           </a>
-        </JustInDevMode>
+        </EnabledBySettings>
 
         <div
           style={{ display: "flex", paddingTop: 4, justifyContent: "right" }}
diff --git a/packages/taler-wallet-webextension/src/background.dev.ts 
b/packages/taler-wallet-webextension/src/background.dev.ts
index 9ed0e1b8f..96cf63409 100644
--- a/packages/taler-wallet-webextension/src/background.dev.ts
+++ b/packages/taler-wallet-webextension/src/background.dev.ts
@@ -27,7 +27,6 @@ import { platform, setupPlatform } from 
"./platform/background.js";
 import devAPI from "./platform/dev.js";
 import { wxMain } from "./wxBackend.js";
 
-console.log("Wallet setup for Dev API");
 setupPlatform(devAPI);
 
 async function start() {
diff --git a/packages/taler-wallet-webextension/src/background.ts 
b/packages/taler-wallet-webextension/src/background.ts
index 0d5a186d2..7df66eff8 100644
--- a/packages/taler-wallet-webextension/src/background.ts
+++ b/packages/taler-wallet-webextension/src/background.ts
@@ -35,10 +35,8 @@ const isFirefox =
 // FIXME: create different entry point for any platform instead of
 // switching in runtime
 if (isFirefox) {
-  console.log("Wallet setup for Firefox API");
   setupPlatform(firefoxAPI);
 } else {
-  console.log("Wallet setup for Chrome API");
   setupPlatform(chromeAPI);
 }
 
diff --git 
a/packages/taler-wallet-webextension/src/components/JustInDevMode.tsx 
b/packages/taler-wallet-webextension/src/components/EnabledBySettings.tsx
similarity index 66%
rename from packages/taler-wallet-webextension/src/components/JustInDevMode.tsx
rename to 
packages/taler-wallet-webextension/src/components/EnabledBySettings.tsx
index a29bea791..6f666d301 100644
--- a/packages/taler-wallet-webextension/src/components/JustInDevMode.tsx
+++ b/packages/taler-wallet-webextension/src/components/EnabledBySettings.tsx
@@ -14,14 +14,25 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 import { ComponentChildren, Fragment, h, VNode } from "preact";
-import { useDevContext } from "../context/devContext.js";
+import { useSettings } from "../hooks/useSettings.js";
+import { Settings } from "../platform/api.js";
 
-export function JustInDevMode({
+export function EnabledBySettings<K extends keyof Settings>({
   children,
+  value,
+  name,
 }: {
+  name: K;
+  value?: Settings[K];
   children: ComponentChildren;
 }): VNode {
-  const { devMode } = useDevContext();
-  if (!devMode) return <Fragment />;
+  const [settings] = useSettings();
+  if (value === undefined) {
+    if (!settings[name]) return <Fragment />;
+    return <Fragment>{children}</Fragment>;
+  }
+  if (settings[name] !== value) {
+    return <Fragment />;
+  }
   return <Fragment>{children}</Fragment>;
 }
diff --git 
a/packages/taler-wallet-webextension/src/components/ErrorTalerOperation.tsx 
b/packages/taler-wallet-webextension/src/components/ErrorTalerOperation.tsx
index f8203f38a..2979c28e5 100644
--- a/packages/taler-wallet-webextension/src/components/ErrorTalerOperation.tsx
+++ b/packages/taler-wallet-webextension/src/components/ErrorTalerOperation.tsx
@@ -17,8 +17,8 @@ import { TalerErrorDetail, TranslatedString } from 
"@gnu-taler/taler-util";
 import { Fragment, h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import arrowDown from "../svg/chevron-down.svg";
-import { useDevContext } from "../context/devContext.js";
 import { ErrorBox } from "./styled/index.js";
+import { EnabledBySettings } from "./EnabledBySettings.js";
 
 export function ErrorTalerOperation({
   title,
@@ -27,7 +27,6 @@ export function ErrorTalerOperation({
   title?: TranslatedString;
   error?: TalerErrorDetail;
 }): VNode | null {
-  const { devMode } = useDevContext();
   const [showErrorDetail, setShowErrorDetail] = useState(false);
 
   if (!title || !error) return null;
@@ -62,11 +61,11 @@ export function ErrorTalerOperation({
               <b>{error.hint}</b> {!errorHint ? "" : `: ${errorHint}`}{" "}
             </div>
           </div>
-          {devMode && (
+          <EnabledBySettings name="showJsonOnError">
             <div style={{ textAlign: "left", overflowX: "auto" }}>
               <pre>{JSON.stringify(error, undefined, 2)}</pre>
             </div>
-          )}
+          </EnabledBySettings>
         </Fragment>
       )}
     </ErrorBox>
diff --git 
a/packages/taler-wallet-webextension/src/components/TermsOfService/utils.ts 
b/packages/taler-wallet-webextension/src/components/TermsOfService/utils.ts
index 391932574..fdca78ee5 100644
--- a/packages/taler-wallet-webextension/src/components/TermsOfService/utils.ts
+++ b/packages/taler-wallet-webextension/src/components/TermsOfService/utils.ts
@@ -14,7 +14,11 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { ExchangeTosStatus, GetExchangeTosResult } from 
"@gnu-taler/taler-util";
+import {
+  ExchangeTosStatus,
+  GetExchangeTosResult,
+  Logger,
+} from "@gnu-taler/taler-util";
 
 export function buildTermsOfServiceState(
   tos: GetExchangeTosResult,
@@ -27,6 +31,8 @@ export function buildTermsOfServiceState(
   return { content, status: tos.tosStatus, version: tos.currentEtag };
 }
 
+const logger = new Logger("termsofservice");
+
 function parseTermsOfServiceContent(
   type: string,
   text: string,
@@ -36,28 +42,28 @@ function parseTermsOfServiceContent(
       const document = new DOMParser().parseFromString(text, "text/xml");
       return { type: "xml", document };
     } catch (e) {
-      console.log(e);
+      logger.error("error parsing xml", e);
     }
   } else if (type === "text/html") {
     try {
       const href = new URL(text);
       return { type: "html", href };
     } catch (e) {
-      console.log(e);
+      logger.error("error parsing url", e);
     }
   } else if (type === "text/json") {
     try {
       const data = JSON.parse(text);
       return { type: "json", data };
     } catch (e) {
-      console.log(e);
+      logger.error("error parsing json", e);
     }
   } else if (type === "text/pdf") {
     try {
       const location = new URL(text);
       return { type: "pdf", location };
     } catch (e) {
-      console.log(e);
+      logger.error("error parsing url", e);
     }
   }
   const content = text;
diff --git a/packages/taler-wallet-webextension/src/context/devContext.ts 
b/packages/taler-wallet-webextension/src/context/devContext.ts
deleted file mode 100644
index e2ad2914b..000000000
--- a/packages/taler-wallet-webextension/src/context/devContext.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-
-import { createContext, h, VNode } from "preact";
-import { useContext } from "preact/hooks";
-import { useWalletDevMode } from "../hooks/useWalletDevMode.js";
-
-interface Type {
-  devMode: boolean;
-  toggle: () => Promise<void>;
-}
-const Context = createContext<Type>({
-  devMode: false,
-  toggle: async () => {
-    null;
-  },
-});
-
-export const useDevContext = (): Type => useContext(Context);
-
-export const DevContextProviderForTesting = ({
-  value,
-  children,
-}: {
-  value?: boolean;
-  children: any;
-}): VNode => {
-  return h(Context.Provider, {
-    value: {
-      devMode: !!value,
-      toggle: async () => {
-        null;
-      },
-    },
-    children,
-  });
-};
-
-export const DevContextProvider = ({ children }: { children: any }): VNode => {
-  const devModeToggle = useWalletDevMode();
-  const value: Type = {
-    devMode: !!devModeToggle.value,
-    toggle: devModeToggle.toggle,
-  };
-  //support for function as children, useful for getting the value right away
-  children =
-    children.length === 1 && typeof children === "function"
-      ? children(value)
-      : children;
-
-  return h(Context.Provider, { value, children });
-};
diff --git a/packages/taler-wallet-webextension/src/cta/Payment/state.ts 
b/packages/taler-wallet-webextension/src/cta/Payment/state.ts
index b3d2e6e81..5cd4686ce 100644
--- a/packages/taler-wallet-webextension/src/cta/Payment/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Payment/state.ts
@@ -167,8 +167,6 @@ export function useComponentState({
     if (fu) {
       if (typeof window !== "undefined") {
         document.location.href = fu;
-      } else {
-        console.log(`should d to ${fu}`);
       }
     }
     onSuccess(res.transactionId);
diff --git 
a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/views.tsx 
b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/views.tsx
index 42e51014f..bd265750f 100644
--- a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/views.tsx
+++ b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/views.tsx
@@ -30,7 +30,6 @@ export function ReadyView({
 }: State.FillTemplate): VNode {
   const { i18n } = useTranslationContext();
 
-  console.log("is summary", !!summary);
   return (
     <Fragment>
       <section style={{ textAlign: "left" }}>
diff --git 
a/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts 
b/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts
index 3255c90e5..35b7148cc 100644
--- a/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts
@@ -51,7 +51,6 @@ export function useClipboardPermissions(): ToggleHandler {
       //     .call("toggleHeaderListener", false)
       //     .then((r) => setEnabled(r.newValue));
       // } catch (e) {
-      //   console.log(e);
       // }
     }
     return;
diff --git a/packages/taler-wallet-webextension/src/hooks/useSettings.ts 
b/packages/taler-wallet-webextension/src/hooks/useSettings.ts
index 040fee424..1fa2b0539 100644
--- a/packages/taler-wallet-webextension/src/hooks/useSettings.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useSettings.ts
@@ -36,7 +36,6 @@ export function useSettings(): [
   function updateField<T extends keyof Settings>(k: T, v: Settings[T]) {
     const newValue = { ...parsed, [k]: v };
     const json = JSON.stringify(newValue);
-    console.log(json);
     update(json);
   }
   return [parsed, updateField];
diff --git a/packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts 
b/packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts
deleted file mode 100644
index db7effe96..000000000
--- a/packages/taler-wallet-webextension/src/hooks/useWalletDevMode.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { useEffect, useState } from "preact/hooks";
-import { useBackendContext } from "../context/backend.js";
-
-type Result = {
-  value: boolean | undefined;
-  toggle: () => Promise<void>;
-};
-
-export function useWalletDevMode(): Result {
-  const [enabled, setEnabled] = useState<undefined | boolean>(undefined);
-  const api = useBackendContext();
-  // const { pushAlertOnError } = useAlertContext();
-
-  async function handleOpen(): Promise<void> {
-    const nextValue = !enabled;
-    await api.wallet.call(WalletApiOperation.SetDevMode, {
-      devModeEnabled: nextValue,
-    });
-    setEnabled(nextValue);
-    return;
-  }
-
-  useEffect(() => {
-    async function getValue(): Promise<void> {
-      const res = await api.wallet.call(WalletApiOperation.GetVersion, {});
-      setEnabled(res.devMode);
-    }
-    getValue();
-  }, []);
-
-  return {
-    value: enabled,
-    toggle: handleOpen,
-  };
-}
diff --git a/packages/taler-wallet-webextension/src/platform/api.ts 
b/packages/taler-wallet-webextension/src/platform/api.ts
index f87500c4f..f8fa0a848 100644
--- a/packages/taler-wallet-webextension/src/platform/api.ts
+++ b/packages/taler-wallet-webextension/src/platform/api.ts
@@ -15,7 +15,11 @@
  */
 
 import { CoreApiResponse, NotificationType } from "@gnu-taler/taler-util";
-import { WalletOperations } from "@gnu-taler/taler-wallet-core";
+import {
+  WalletConfig,
+  WalletConfigParameter,
+  WalletOperations,
+} from "@gnu-taler/taler-wallet-core";
 import { BackgroundOperations } from "../wxApi.js";
 import {
   ExtensionOperations,
@@ -87,12 +91,35 @@ export interface WalletWebExVersion {
   version: string;
 }
 
-export interface Settings {
+type F = WalletConfig["features"];
+type kf = keyof F;
+type WebexWalletConfig = {
+  [P in keyof F as `wallet${Capitalize<P>}`]: F[P];
+};
+
+export interface Settings extends WebexWalletConfig {
   injectTalerSupport: boolean;
+  advanceMode: boolean;
+  backup: boolean;
+  langSelector: boolean;
+  showJsonOnError: boolean;
+  extendedAccountTypes: boolean;
+  //WORKAROUND
+  //Able to delete tx in dev mode
+  //FIXME: remove this when DD37 is implemented
+  deleteActiveTransactions: boolean;
 }
 
 export const defaultSettings: Settings = {
   injectTalerSupport: false,
+  advanceMode: false,
+  backup: false,
+  langSelector: false,
+  deleteActiveTransactions: false,
+  showJsonOnError: false,
+  extendedAccountTypes: false,
+  walletAllowHttp: false,
+  walletBatchWithdrawal: false,
 };
 
 /**
diff --git a/packages/taler-wallet-webextension/src/platform/firefox.ts 
b/packages/taler-wallet-webextension/src/platform/firefox.ts
index 01848e1ab..9f666e7ae 100644
--- a/packages/taler-wallet-webextension/src/platform/firefox.ts
+++ b/packages/taler-wallet-webextension/src/platform/firefox.ts
@@ -45,7 +45,7 @@ function isFirefox(): boolean {
 }
 
 function addPermissionsListener(callback: (p: Permissions) => void): void {
-  console.log("addPermissionListener is not supported for Firefox");
+  throw Error("addPermissionListener is not supported for Firefox");
 }
 
 function getPermissionsApi(): CrossBrowserPermissionsApi {
diff --git a/packages/taler-wallet-webextension/src/popup/Application.tsx 
b/packages/taler-wallet-webextension/src/popup/Application.tsx
index c03360486..e0cb840aa 100644
--- a/packages/taler-wallet-webextension/src/popup/Application.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Application.tsx
@@ -20,6 +20,10 @@
  * @author sebasjm
  */
 
+import {
+  TranslationProvider,
+  useTranslationContext,
+} from "@gnu-taler/web-util/lib/index.browser";
 import { createHashHistory } from "history";
 import { ComponentChildren, Fragment, h, VNode } from "preact";
 import { route, Route, Router } from "preact-router";
@@ -27,29 +31,22 @@ import { useEffect, useState } from "preact/hooks";
 import PendingTransactions from "../components/PendingTransactions.js";
 import { PopupBox } from "../components/styled/index.js";
 import { AlertProvider } from "../context/alert.js";
-import { DevContextProvider } from "../context/devContext.js";
 import { IoCProviderForRuntime } from "../context/iocContext.js";
-import {
-  TranslationProvider,
-  useTranslationContext,
-} from "@gnu-taler/web-util/lib/index.browser";
 import { useTalerActionURL } from "../hooks/useTalerActionURL.js";
+import { strings } from "../i18n/strings.js";
 import { Pages, PopupNavBar, PopupNavBarOptions } from "../NavigationBar.js";
 import { platform } from "../platform/foreground.js";
 import { BackupPage } from "../wallet/BackupPage.js";
 import { ProviderDetailPage } from "../wallet/ProviderDetailPage.js";
 import { BalancePage } from "./BalancePage.js";
 import { TalerActionFound } from "./TalerActionFound.js";
-import { strings } from "../i18n/strings.js";
 
 export function Application(): VNode {
   return (
     <TranslationProvider source={strings}>
-      <DevContextProvider>
-        <IoCProviderForRuntime>
-          <ApplicationView />
-        </IoCProviderForRuntime>
-      </DevContextProvider>
+      <IoCProviderForRuntime>
+        <ApplicationView />
+      </IoCProviderForRuntime>
     </TranslationProvider>
   );
 }
diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.dev.tsx 
b/packages/taler-wallet-webextension/src/popupEntryPoint.dev.tsx
index 6b42e5809..f0bc81399 100644
--- a/packages/taler-wallet-webextension/src/popupEntryPoint.dev.tsx
+++ b/packages/taler-wallet-webextension/src/popupEntryPoint.dev.tsx
@@ -27,7 +27,6 @@ import { setupPlatform } from "./platform/foreground.js";
 import devAPI from "./platform/dev.js";
 import { Application } from "./popup/Application.js";
 
-console.log("Wallet setup for Dev API");
 setupPlatform(devAPI);
 
 function main(): void {
diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx 
b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
index 22aba6c9d..08915ea96 100644
--- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
+++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
@@ -32,10 +32,8 @@ import { Application } from "./popup/Application.js";
 //switching in runtime
 const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
 if (isFirefox) {
-  console.log("Wallet setup for Firefox API");
   setupPlatform(firefoxAPI);
 } else {
-  console.log("Wallet setup for Chrome API");
   setupPlatform(chromeAPI);
 }
 
diff --git a/packages/taler-wallet-webextension/src/test-utils.ts 
b/packages/taler-wallet-webextension/src/test-utils.ts
index d85d992b1..1d2538703 100644
--- a/packages/taler-wallet-webextension/src/test-utils.ts
+++ b/packages/taler-wallet-webextension/src/test-utils.ts
@@ -41,7 +41,6 @@ import { strings } from "./i18n/strings.js";
 // When doing tests we want the requestAnimationFrame to be as fast as 
possible.
 // without this option the RAF will timeout after 100ms making the tests slower
 options.requestAnimationFrame = (fn: () => void) => {
-  // console.log("RAF called")
   return fn();
 };
 
diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx 
b/packages/taler-wallet-webextension/src/wallet/Application.tsx
index ff8cf0314..5c75b734b 100644
--- a/packages/taler-wallet-webextension/src/wallet/Application.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx
@@ -20,15 +20,21 @@
  * @author sebasjm
  */
 
+import { TranslatedString } from "@gnu-taler/taler-util";
 import {
-  TalerUriAction,
-  TranslatedString,
-  parseTalerUri,
-} from "@gnu-taler/taler-util";
+  TranslationProvider,
+  useTranslationContext,
+} from "@gnu-taler/web-util/lib/index.browser";
 import { createHashHistory } from "history";
-import { ComponentChildren, Fragment, h, VNode } from "preact";
-import { route, Route, Router } from "preact-router";
+import { ComponentChildren, Fragment, VNode, h } from "preact";
+import { Route, Router, route } from "preact-router";
 import { useEffect } from "preact/hooks";
+import {
+  Pages,
+  WalletNavBar,
+  WalletNavBarOptions,
+  getPathnameForTalerURI,
+} from "../NavigationBar.js";
 import { AlertView, CurrentAlerts } from "../components/CurrentAlerts.js";
 import { LogoHeader } from "../components/LogoHeader.js";
 import PendingTransactions from "../components/PendingTransactions.js";
@@ -39,12 +45,7 @@ import {
   WalletBox,
 } from "../components/styled/index.js";
 import { AlertProvider } from "../context/alert.js";
-import { DevContextProvider } from "../context/devContext.js";
 import { IoCProviderForRuntime } from "../context/iocContext.js";
-import {
-  TranslationProvider,
-  useTranslationContext,
-} from "@gnu-taler/web-util/lib/index.browser";
 import { DepositPage as DepositPageCTA } from "../cta/Deposit/index.js";
 import { InvoiceCreatePage } from "../cta/InvoiceCreate/index.js";
 import { InvoicePayPage } from "../cta/InvoicePay/index.js";
@@ -59,12 +60,7 @@ import {
   WithdrawPageFromParams,
   WithdrawPageFromURI,
 } from "../cta/Withdraw/index.js";
-import {
-  Pages,
-  WalletNavBar,
-  WalletNavBarOptions,
-  getPathnameForTalerURI,
-} from "../NavigationBar.js";
+import { strings } from "../i18n/strings.js";
 import { platform } from "../platform/foreground.js";
 import CloseIcon from "../svg/close_24px.svg";
 import { AddBackupProviderPage } from "./AddBackupProvider/index.js";
@@ -80,7 +76,6 @@ import { QrReaderPage } from "./QrReader.js";
 import { SettingsPage } from "./Settings.js";
 import { TransactionPage } from "./Transaction.js";
 import { WelcomePage } from "./Welcome.js";
-import { strings } from "../i18n/strings.js";
 
 export function Application(): VNode {
   const { i18n } = useTranslationContext();
@@ -91,433 +86,421 @@ export function Application(): VNode {
   }
   return (
     <TranslationProvider source={strings}>
-      <DevContextProvider>
-        <IoCProviderForRuntime>
-          <Router history={hash_history}>
-            <Route
-              path={Pages.welcome}
-              component={() => (
-                <WalletTemplate>
-                  <WelcomePage />
-                </WalletTemplate>
-              )}
-            />
+      <IoCProviderForRuntime>
+        <Router history={hash_history}>
+          <Route
+            path={Pages.welcome}
+            component={() => (
+              <WalletTemplate>
+                <WelcomePage />
+              </WalletTemplate>
+            )}
+          />
 
-            <Route
-              path={Pages.qr}
-              component={() => (
-                <WalletTemplate goToTransaction={redirectToTxInfo}>
-                  <QrReaderPage
-                    onDetected={(talerActionUrl: string) => {
-                      platform.openWalletURIFromPopup(talerActionUrl);
-                    }}
-                  />
-                </WalletTemplate>
-              )}
-            />
+          <Route
+            path={Pages.qr}
+            component={() => (
+              <WalletTemplate goToTransaction={redirectToTxInfo}>
+                <QrReaderPage
+                  onDetected={(talerActionUrl: string) => {
+                    platform.openWalletURIFromPopup(talerActionUrl);
+                  }}
+                />
+              </WalletTemplate>
+            )}
+          />
 
-            <Route
-              path={Pages.settings}
-              component={() => (
-                <WalletTemplate goToTransaction={redirectToTxInfo}>
-                  <SettingsPage />
-                </WalletTemplate>
-              )}
-            />
-            <Route
-              path={Pages.notifications}
-              component={() => (
-                <WalletTemplate>
-                  <NotificationsPage />
-                </WalletTemplate>
-              )}
-            />
-            {/**
-             * SETTINGS
-             */}
-            <Route
-              path={Pages.settingsExchangeAdd.pattern}
-              component={() => (
-                <WalletTemplate>
-                  <ExchangeAddPage onBack={() => redirectTo(Pages.balance)} />
-                </WalletTemplate>
-              )}
-            />
+          <Route
+            path={Pages.settings}
+            component={() => (
+              <WalletTemplate goToTransaction={redirectToTxInfo}>
+                <SettingsPage />
+              </WalletTemplate>
+            )}
+          />
+          <Route
+            path={Pages.notifications}
+            component={() => (
+              <WalletTemplate>
+                <NotificationsPage />
+              </WalletTemplate>
+            )}
+          />
+          {/**
+           * SETTINGS
+           */}
+          <Route
+            path={Pages.settingsExchangeAdd.pattern}
+            component={() => (
+              <WalletTemplate>
+                <ExchangeAddPage onBack={() => redirectTo(Pages.balance)} />
+              </WalletTemplate>
+            )}
+          />
 
-            <Route
-              path={Pages.balanceHistory.pattern}
-              component={({ currency }: { currency?: string }) => (
-                <WalletTemplate
-                  path="balance"
-                  goToTransaction={redirectToTxInfo}
-                >
-                  <HistoryPage
-                    currency={currency}
-                    goToWalletDeposit={(currency: string) =>
-                      redirectTo(Pages.sendCash({ amount: `${currency}:0` }))
-                    }
-                    goToWalletManualWithdraw={(currency?: string) =>
-                      redirectTo(
-                        Pages.receiveCash({
-                          amount: !currency ? undefined : `${currency}:0`,
-                        }),
-                      )
-                    }
-                  />
-                </WalletTemplate>
-              )}
-            />
-            <Route
-              path={Pages.sendCash.pattern}
-              component={({ amount }: { amount?: string }) => (
-                <WalletTemplate path="balance">
-                  <DestinationSelectionPage
-                    type="send"
-                    amount={amount}
-                    goToWalletBankDeposit={(amount: string) =>
-                      redirectTo(Pages.balanceDeposit({ amount }))
-                    }
-                    goToWalletWalletSend={(amount: string) =>
-                      redirectTo(Pages.ctaTransferCreate({ amount }))
-                    }
-                  />
-                </WalletTemplate>
-              )}
-            />
-            <Route
-              path={Pages.receiveCash.pattern}
-              component={({ amount }: { amount?: string }) => (
-                <WalletTemplate path="balance">
-                  <DestinationSelectionPage
-                    type="get"
-                    amount={amount}
-                    goToWalletManualWithdraw={(amount?: string) =>
-                      redirectTo(Pages.ctaWithdrawManual({ amount }))
-                    }
-                    goToWalletWalletInvoice={(amount?: string) =>
-                      redirectTo(Pages.ctaInvoiceCreate({ amount }))
-                    }
-                  />
-                </WalletTemplate>
-              )}
-            />
+          <Route
+            path={Pages.balanceHistory.pattern}
+            component={({ currency }: { currency?: string }) => (
+              <WalletTemplate path="balance" 
goToTransaction={redirectToTxInfo}>
+                <HistoryPage
+                  currency={currency}
+                  goToWalletDeposit={(currency: string) =>
+                    redirectTo(Pages.sendCash({ amount: `${currency}:0` }))
+                  }
+                  goToWalletManualWithdraw={(currency?: string) =>
+                    redirectTo(
+                      Pages.receiveCash({
+                        amount: !currency ? undefined : `${currency}:0`,
+                      }),
+                    )
+                  }
+                />
+              </WalletTemplate>
+            )}
+          />
+          <Route
+            path={Pages.sendCash.pattern}
+            component={({ amount }: { amount?: string }) => (
+              <WalletTemplate path="balance">
+                <DestinationSelectionPage
+                  type="send"
+                  amount={amount}
+                  goToWalletBankDeposit={(amount: string) =>
+                    redirectTo(Pages.balanceDeposit({ amount }))
+                  }
+                  goToWalletWalletSend={(amount: string) =>
+                    redirectTo(Pages.ctaTransferCreate({ amount }))
+                  }
+                />
+              </WalletTemplate>
+            )}
+          />
+          <Route
+            path={Pages.receiveCash.pattern}
+            component={({ amount }: { amount?: string }) => (
+              <WalletTemplate path="balance">
+                <DestinationSelectionPage
+                  type="get"
+                  amount={amount}
+                  goToWalletManualWithdraw={(amount?: string) =>
+                    redirectTo(Pages.ctaWithdrawManual({ amount }))
+                  }
+                  goToWalletWalletInvoice={(amount?: string) =>
+                    redirectTo(Pages.ctaInvoiceCreate({ amount }))
+                  }
+                />
+              </WalletTemplate>
+            )}
+          />
 
-            <Route
-              path={Pages.balanceTransaction.pattern}
-              component={({ tid }: { tid: string }) => (
-                <WalletTemplate path="balance">
-                  <TransactionPage
-                    tid={tid}
-                    goToWalletHistory={(currency?: string) =>
-                      redirectTo(Pages.balanceHistory({ currency }))
-                    }
-                  />
-                </WalletTemplate>
-              )}
-            />
+          <Route
+            path={Pages.balanceTransaction.pattern}
+            component={({ tid }: { tid: string }) => (
+              <WalletTemplate path="balance">
+                <TransactionPage
+                  tid={tid}
+                  goToWalletHistory={(currency?: string) =>
+                    redirectTo(Pages.balanceHistory({ currency }))
+                  }
+                />
+              </WalletTemplate>
+            )}
+          />
 
-            <Route
-              path={Pages.balanceDeposit.pattern}
-              component={({ amount }: { amount: string }) => (
-                <WalletTemplate path="balance">
-                  <DepositPage
-                    amount={amount}
-                    onCancel={(currency: string) => {
-                      redirectTo(Pages.balanceHistory({ currency }));
-                    }}
-                    onSuccess={(currency: string) => {
-                      redirectTo(Pages.balanceHistory({ currency }));
-                    }}
-                  />
-                </WalletTemplate>
-              )}
-            />
+          <Route
+            path={Pages.balanceDeposit.pattern}
+            component={({ amount }: { amount: string }) => (
+              <WalletTemplate path="balance">
+                <DepositPage
+                  amount={amount}
+                  onCancel={(currency: string) => {
+                    redirectTo(Pages.balanceHistory({ currency }));
+                  }}
+                  onSuccess={(currency: string) => {
+                    redirectTo(Pages.balanceHistory({ currency }));
+                  }}
+                />
+              </WalletTemplate>
+            )}
+          />
 
-            <Route
-              path={Pages.backup}
-              component={() => (
-                <WalletTemplate
-                  path="backup"
-                  goToTransaction={redirectToTxInfo}
-                >
-                  <BackupPage
-                    onAddProvider={() => redirectTo(Pages.backupProviderAdd)}
-                  />
-                </WalletTemplate>
-              )}
-            />
-            <Route
-              path={Pages.backupProviderDetail.pattern}
-              component={({ pid }: { pid: string }) => (
-                <WalletTemplate>
-                  <ProviderDetailPage
-                    pid={pid}
-                    onPayProvider={(uri: string) =>
-                      redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`)
-                    }
-                    onWithdraw={(amount: string) =>
-                      redirectTo(Pages.receiveCash({ amount }))
-                    }
-                    onBack={() => redirectTo(Pages.backup)}
-                  />
-                </WalletTemplate>
-              )}
-            />
-            <Route
-              path={Pages.backupProviderAdd}
-              component={() => (
-                <WalletTemplate>
-                  <AddBackupProviderPage
-                    onPaymentRequired={(uri: string) =>
-                      redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`)
-                    }
-                    onComplete={(pid: string) =>
-                      redirectTo(Pages.backupProviderDetail({ pid }))
-                    }
-                    onBack={() => redirectTo(Pages.backup)}
-                  />
-                </WalletTemplate>
-              )}
-            />
+          <Route
+            path={Pages.backup}
+            component={() => (
+              <WalletTemplate path="backup" goToTransaction={redirectToTxInfo}>
+                <BackupPage
+                  onAddProvider={() => redirectTo(Pages.backupProviderAdd)}
+                />
+              </WalletTemplate>
+            )}
+          />
+          <Route
+            path={Pages.backupProviderDetail.pattern}
+            component={({ pid }: { pid: string }) => (
+              <WalletTemplate>
+                <ProviderDetailPage
+                  pid={pid}
+                  onPayProvider={(uri: string) =>
+                    redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`)
+                  }
+                  onWithdraw={(amount: string) =>
+                    redirectTo(Pages.receiveCash({ amount }))
+                  }
+                  onBack={() => redirectTo(Pages.backup)}
+                />
+              </WalletTemplate>
+            )}
+          />
+          <Route
+            path={Pages.backupProviderAdd}
+            component={() => (
+              <WalletTemplate>
+                <AddBackupProviderPage
+                  onPaymentRequired={(uri: string) =>
+                    redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`)
+                  }
+                  onComplete={(pid: string) =>
+                    redirectTo(Pages.backupProviderDetail({ pid }))
+                  }
+                  onBack={() => redirectTo(Pages.backup)}
+                />
+              </WalletTemplate>
+            )}
+          />
 
-            {/**
-             * DEV
-             */}
-            <Route
-              path={Pages.dev}
-              component={() => (
-                <WalletTemplate path="dev" goToTransaction={redirectToTxInfo}>
-                  <DeveloperPage />
-                </WalletTemplate>
-              )}
-            />
+          {/**
+           * DEV
+           */}
+          <Route
+            path={Pages.dev}
+            component={() => (
+              <WalletTemplate path="dev" goToTransaction={redirectToTxInfo}>
+                <DeveloperPage />
+              </WalletTemplate>
+            )}
+          />
 
-            {/**
-             * CALL TO ACTION
-             */}
-            <Route
-              path={Pages.defaultCta.pattern}
-              component={({ uri }: { uri: string }) => {
-                const path = getPathnameForTalerURI(uri);
-                if (!path) {
-                  return (
-                    <CallToActionTemplate title={i18n.str`Taler URI handler`}>
-                      <AlertView
-                        alert={{
-                          type: "warning",
-                          message: i18n.str`Could not found a handler for the 
Taler URI`,
-                          description: i18n.str`The uri read in the path 
parameter is not valid: "${uri}"`,
-                        }}
-                      />
-                    </CallToActionTemplate>
-                  );
-                }
-                return <Redirect to={path} />;
-              }}
-            />
-            <Route
-              path={Pages.ctaPay}
-              component={({ talerUri }: { talerUri: string }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash payment`}>
-                  <PaymentPage
-                    talerPayUri={decodeURIComponent(talerUri)}
-                    goToWalletManualWithdraw={(amount?: string) =>
-                      redirectTo(Pages.receiveCash({ amount }))
-                    }
-                    cancel={() => redirectTo(Pages.balance)}
-                    onSuccess={(tid: string) =>
-                      redirectTo(Pages.balanceTransaction({ tid }))
-                    }
-                  />
-                </CallToActionTemplate>
-              )}
-            />
-            <Route
-              path={Pages.ctaPayTemplate}
-              component={({ talerUri }: { talerUri: string }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash payment`}>
-                  <PaymentTemplatePage
-                    talerTemplateUri={decodeURIComponent(talerUri)}
-                    goToWalletManualWithdraw={(amount?: string) =>
-                      redirectTo(Pages.receiveCash({ amount }))
-                    }
-                    cancel={() => redirectTo(Pages.balance)}
-                    onSuccess={(tid: string) =>
-                      redirectTo(Pages.balanceTransaction({ tid }))
-                    }
-                  />
-                </CallToActionTemplate>
-              )}
-            />
-            <Route
-              path={Pages.ctaRefund}
-              component={({ talerUri }: { talerUri: string }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash refund`}>
-                  <RefundPage
-                    talerRefundUri={decodeURIComponent(talerUri)}
-                    cancel={() => redirectTo(Pages.balance)}
-                    onSuccess={(tid: string) =>
-                      redirectTo(Pages.balanceTransaction({ tid }))
-                    }
-                  />
-                </CallToActionTemplate>
-              )}
-            />
-            <Route
-              path={Pages.ctaTips}
-              component={({ talerUri }: { talerUri: string }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash tip`}>
-                  <TipPage
-                    talerTipUri={decodeURIComponent(talerUri)}
-                    onCancel={() => redirectTo(Pages.balance)}
-                    onSuccess={(tid: string) =>
-                      redirectTo(Pages.balanceTransaction({ tid }))
-                    }
-                  />
-                </CallToActionTemplate>
-              )}
-            />
-            <Route
-              path={Pages.ctaWithdraw}
-              component={({ talerUri }: { talerUri: string }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash 
withdrawal`}>
-                  <WithdrawPageFromURI
-                    talerWithdrawUri={decodeURIComponent(talerUri)}
-                    cancel={() => redirectTo(Pages.balance)}
-                    onSuccess={(tid: string) =>
-                      redirectTo(Pages.balanceTransaction({ tid }))
-                    }
-                  />
-                </CallToActionTemplate>
-              )}
-            />
-            <Route
-              path={Pages.ctaWithdrawManual.pattern}
-              component={({ amount }: { amount: string }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash 
withdrawal`}>
-                  <WithdrawPageFromParams
-                    amount={amount}
-                    cancel={() => redirectTo(Pages.balance)}
-                    onSuccess={(tid: string) =>
-                      redirectTo(Pages.balanceTransaction({ tid }))
-                    }
-                  />
-                </CallToActionTemplate>
-              )}
-            />
-            <Route
-              path={Pages.ctaDeposit}
-              component={({
-                amount,
-                talerUri,
-              }: {
-                amount: string;
-                talerUri: string;
-              }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash deposit`}>
-                  <DepositPageCTA
-                    amountStr={amount}
-                    talerDepositUri={decodeURIComponent(talerUri)}
-                    cancel={() => redirectTo(Pages.balance)}
-                    onSuccess={(tid: string) =>
-                      redirectTo(Pages.balanceTransaction({ tid }))
-                    }
-                  />
-                </CallToActionTemplate>
-              )}
-            />
-            <Route
-              path={Pages.ctaInvoiceCreate.pattern}
-              component={({ amount }: { amount: string }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash invoice`}>
-                  <InvoiceCreatePage
-                    amount={amount}
-                    onClose={() => redirectTo(Pages.balance)}
-                    onSuccess={(tid: string) =>
-                      redirectTo(Pages.balanceTransaction({ tid }))
-                    }
-                  />
-                </CallToActionTemplate>
-              )}
-            />
-            <Route
-              path={Pages.ctaTransferCreate.pattern}
-              component={({ amount }: { amount: string }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash transfer`}>
-                  <TransferCreatePage
-                    amount={amount}
-                    onClose={() => redirectTo(Pages.balance)}
-                    onSuccess={(tid: string) =>
-                      redirectTo(Pages.balanceTransaction({ tid }))
-                    }
-                  />
-                </CallToActionTemplate>
-              )}
-            />
-            <Route
-              path={Pages.ctaInvoicePay}
-              component={({ talerUri }: { talerUri: string }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash invoice`}>
-                  <InvoicePayPage
-                    talerPayPullUri={decodeURIComponent(talerUri)}
-                    goToWalletManualWithdraw={(amount?: string) =>
-                      redirectTo(Pages.receiveCash({ amount }))
-                    }
-                    onClose={() => redirectTo(Pages.balance)}
-                    onSuccess={(tid: string) =>
-                      redirectTo(Pages.balanceTransaction({ tid }))
-                    }
-                  />
-                </CallToActionTemplate>
-              )}
-            />
-            <Route
-              path={Pages.ctaTransferPickup}
-              component={({ talerUri }: { talerUri: string }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash transfer`}>
-                  <TransferPickupPage
-                    talerPayPushUri={decodeURIComponent(talerUri)}
-                    onClose={() => redirectTo(Pages.balance)}
-                    onSuccess={(tid: string) =>
-                      redirectTo(Pages.balanceTransaction({ tid }))
-                    }
-                  />
-                </CallToActionTemplate>
-              )}
-            />
-            <Route
-              path={Pages.ctaRecovery}
-              component={({
-                talerRecoveryUri,
-              }: {
-                talerRecoveryUri: string;
-              }) => (
-                <CallToActionTemplate title={i18n.str`Digital cash recovery`}>
-                  <RecoveryPage
-                    talerRecoveryUri={decodeURIComponent(talerRecoveryUri)}
-                    onCancel={() => redirectTo(Pages.balance)}
-                    onSuccess={() => redirectTo(Pages.backup)}
-                  />
-                </CallToActionTemplate>
-              )}
-            />
+          {/**
+           * CALL TO ACTION
+           */}
+          <Route
+            path={Pages.defaultCta.pattern}
+            component={({ uri }: { uri: string }) => {
+              const path = getPathnameForTalerURI(uri);
+              if (!path) {
+                return (
+                  <CallToActionTemplate title={i18n.str`Taler URI handler`}>
+                    <AlertView
+                      alert={{
+                        type: "warning",
+                        message: i18n.str`Could not found a handler for the 
Taler URI`,
+                        description: i18n.str`The uri read in the path 
parameter is not valid: "${uri}"`,
+                      }}
+                    />
+                  </CallToActionTemplate>
+                );
+              }
+              return <Redirect to={path} />;
+            }}
+          />
+          <Route
+            path={Pages.ctaPay}
+            component={({ talerUri }: { talerUri: string }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash payment`}>
+                <PaymentPage
+                  talerPayUri={decodeURIComponent(talerUri)}
+                  goToWalletManualWithdraw={(amount?: string) =>
+                    redirectTo(Pages.receiveCash({ amount }))
+                  }
+                  cancel={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaPayTemplate}
+            component={({ talerUri }: { talerUri: string }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash payment`}>
+                <PaymentTemplatePage
+                  talerTemplateUri={decodeURIComponent(talerUri)}
+                  goToWalletManualWithdraw={(amount?: string) =>
+                    redirectTo(Pages.receiveCash({ amount }))
+                  }
+                  cancel={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaRefund}
+            component={({ talerUri }: { talerUri: string }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash refund`}>
+                <RefundPage
+                  talerRefundUri={decodeURIComponent(talerUri)}
+                  cancel={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaTips}
+            component={({ talerUri }: { talerUri: string }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash tip`}>
+                <TipPage
+                  talerTipUri={decodeURIComponent(talerUri)}
+                  onCancel={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaWithdraw}
+            component={({ talerUri }: { talerUri: string }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash withdrawal`}>
+                <WithdrawPageFromURI
+                  talerWithdrawUri={decodeURIComponent(talerUri)}
+                  cancel={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaWithdrawManual.pattern}
+            component={({ amount }: { amount: string }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash withdrawal`}>
+                <WithdrawPageFromParams
+                  amount={amount}
+                  cancel={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaDeposit}
+            component={({
+              amount,
+              talerUri,
+            }: {
+              amount: string;
+              talerUri: string;
+            }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash deposit`}>
+                <DepositPageCTA
+                  amountStr={amount}
+                  talerDepositUri={decodeURIComponent(talerUri)}
+                  cancel={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaInvoiceCreate.pattern}
+            component={({ amount }: { amount: string }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash invoice`}>
+                <InvoiceCreatePage
+                  amount={amount}
+                  onClose={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaTransferCreate.pattern}
+            component={({ amount }: { amount: string }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash transfer`}>
+                <TransferCreatePage
+                  amount={amount}
+                  onClose={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaInvoicePay}
+            component={({ talerUri }: { talerUri: string }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash invoice`}>
+                <InvoicePayPage
+                  talerPayPullUri={decodeURIComponent(talerUri)}
+                  goToWalletManualWithdraw={(amount?: string) =>
+                    redirectTo(Pages.receiveCash({ amount }))
+                  }
+                  onClose={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaTransferPickup}
+            component={({ talerUri }: { talerUri: string }) => (
+              <CallToActionTemplate title={i18n.str`Digital cash transfer`}>
+                <TransferPickupPage
+                  talerPayPushUri={decodeURIComponent(talerUri)}
+                  onClose={() => redirectTo(Pages.balance)}
+                  onSuccess={(tid: string) =>
+                    redirectTo(Pages.balanceTransaction({ tid }))
+                  }
+                />
+              </CallToActionTemplate>
+            )}
+          />
+          <Route
+            path={Pages.ctaRecovery}
+            component={({ talerRecoveryUri }: { talerRecoveryUri: string }) => 
(
+              <CallToActionTemplate title={i18n.str`Digital cash recovery`}>
+                <RecoveryPage
+                  talerRecoveryUri={decodeURIComponent(talerRecoveryUri)}
+                  onCancel={() => redirectTo(Pages.balance)}
+                  onSuccess={() => redirectTo(Pages.backup)}
+                />
+              </CallToActionTemplate>
+            )}
+          />
 
-            {/**
-             * NOT FOUND
-             * all redirects should be at the end
-             */}
-            <Route
-              path={Pages.balance}
-              component={() => <Redirect to={Pages.balanceHistory({})} />}
-            />
+          {/**
+           * NOT FOUND
+           * all redirects should be at the end
+           */}
+          <Route
+            path={Pages.balance}
+            component={() => <Redirect to={Pages.balanceHistory({})} />}
+          />
 
-            <Route
-              default
-              component={() => <Redirect to={Pages.balanceHistory({})} />}
-            />
-          </Router>
-        </IoCProviderForRuntime>
-      </DevContextProvider>
+          <Route
+            default
+            component={() => <Redirect to={Pages.balanceHistory({})} />}
+          />
+        </Router>
+      </IoCProviderForRuntime>
     </TranslationProvider>
   );
 }
diff --git 
a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx 
b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx
index 7f239f33d..8416e17e9 100644
--- 
a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx
+++ 
b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx
@@ -17,7 +17,7 @@
 import { styled } from "@linaria/react";
 import { Fragment, h, VNode } from "preact";
 import { AmountField } from "../../components/AmountField.js";
-import { JustInDevMode } from "../../components/JustInDevMode.js";
+import { EnabledBySettings } from "../../components/EnabledBySettings.js";
 import { SelectList } from "../../components/SelectList.js";
 import {
   Input,
@@ -300,11 +300,11 @@ export function ReadySendView({
           required
           handler={amountHandler}
         />
-        <JustInDevMode>
+        <EnabledBySettings name="advanceMode">
           <Button onClick={sendAll.onClick}>
             <i18n.Translate>Send all</i18n.Translate>
           </Button>
-        </JustInDevMode>
+        </EnabledBySettings>
       </Grid>
 
       <Grid container spacing={1} columns={1}>
diff --git 
a/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts 
b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
index 1f8ab4883..641b47cd7 100644
--- a/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
@@ -23,10 +23,10 @@ import { WalletApiOperation } from 
"@gnu-taler/taler-wallet-core";
 import { useState } from "preact/hooks";
 import { alertFromError, useAlertContext } from "../../context/alert.js";
 import { useBackendContext } from "../../context/backend.js";
-import { useDevContext } from "../../context/devContext.js";
 import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
 import { AccountByType, Props, State } from "./index.js";
+import { useSettings } from "../../hooks/useSettings.js";
 
 export function useComponentState({
   currency,
@@ -39,12 +39,11 @@ export function useComponentState({
   const hook = useAsyncAsHook(() =>
     api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency }),
   );
-  const { devMode } = useDevContext();
   const accountType: Record<string, string> = {
     iban: "IBAN",
-    // "x-taler-bank": "Taler Bank",
   };
-  if (devMode) {
+  const [settings] = useSettings();
+  if (settings.extendedAccountTypes) {
     accountType["bitcoin"] = "Bitcoin";
     accountType["x-taler-bank"] = "Taler Bank";
   }
diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
index 53bc577d4..89d92b82c 100644
--- a/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
@@ -47,27 +47,27 @@ const version = {
 
 export const AllOff = tests.createExample(TestedComponent, {
   deviceName: "this-is-the-device-name",
-  devModeToggle: { value: false, button: {} },
+  advanceToggle: { value: false, button: {} },
   autoOpenToggle: { value: false, button: {} },
-  clipboardToggle: { value: false, button: {} },
+  langToggle: { value: false, button: {} },
   setDeviceName: () => Promise.resolve(),
   ...version,
 });
 
 export const OneChecked = tests.createExample(TestedComponent, {
   deviceName: "this-is-the-device-name",
-  devModeToggle: { value: false, button: {} },
+  advanceToggle: { value: false, button: {} },
   autoOpenToggle: { value: false, button: {} },
-  clipboardToggle: { value: false, button: {} },
+  langToggle: { value: false, button: {} },
   setDeviceName: () => Promise.resolve(),
   ...version,
 });
 
 export const WithOneExchange = tests.createExample(TestedComponent, {
   deviceName: "this-is-the-device-name",
-  devModeToggle: { value: false, button: {} },
+  advanceToggle: { value: false, button: {} },
   autoOpenToggle: { value: false, button: {} },
-  clipboardToggle: { value: false, button: {} },
+  langToggle: { value: false, button: {} },
   setDeviceName: () => Promise.resolve(),
   knownExchanges: [
     {
@@ -89,9 +89,9 @@ export const WithExchangeInDifferentState = 
tests.createExample(
   TestedComponent,
   {
     deviceName: "this-is-the-device-name",
-    devModeToggle: { value: false, button: {} },
+    advanceToggle: { value: false, button: {} },
     autoOpenToggle: { value: false, button: {} },
-    clipboardToggle: { 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 ae3a6e688..62a6c55ff 100644
--- a/packages/taler-wallet-webextension/src/wallet/Settings.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
@@ -17,12 +17,15 @@
 import {
   ExchangeListItem,
   ExchangeTosStatus,
+  TranslatedString,
   WalletCoreVersion,
 } from "@gnu-taler/taler-util";
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { Fragment, h, VNode } from "preact";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
+import { Fragment, VNode, h } from "preact";
+import { Pages } from "../NavigationBar.js";
 import { Checkbox } from "../components/Checkbox.js";
-import { JustInDevMode } from "../components/JustInDevMode.js";
+import { EnabledBySettings } from "../components/EnabledBySettings.js";
 import { Part } from "../components/Part.js";
 import { SelectList } from "../components/SelectList.js";
 import {
@@ -35,25 +38,20 @@ import {
 } from "../components/styled/index.js";
 import { useAlertContext } from "../context/alert.js";
 import { useBackendContext } from "../context/backend.js";
-import { useDevContext } from "../context/devContext.js";
-import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
 import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
-import { useSettings } from "../hooks/useSettings.js";
 import { useBackupDeviceName } from "../hooks/useBackupDeviceName.js";
 import { useClipboardPermissions } from "../hooks/useClipboardPermissions.js";
+import { useSettings } from "../hooks/useSettings.js";
 import { ToggleHandler } from "../mui/handlers.js";
-import { Pages } from "../NavigationBar.js";
 import { platform } from "../platform/foreground.js";
+import { Settings } from "../platform/api.js";
 
 const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : 
undefined;
 
 export function SettingsPage(): VNode {
   const [settings, updateSettings] = useSettings();
-  const clipboardToggle = useClipboardPermissions();
-  const { devMode, toggle } = useDevContext();
   const { safely } = useAlertContext();
   const { name, update } = useBackupDeviceName();
-  const { pushAlertOnError } = useAlertContext();
   const webex = platform.getWalletWebExVersion();
   const api = useBackendContext();
 
@@ -76,16 +74,24 @@ export function SettingsPage(): VNode {
         value: settings.injectTalerSupport,
         button: {
           onClick: safely("update support injection", async () => {
-            console.log("click", settings.injectTalerSupport);
             updateSettings("injectTalerSupport", !settings.injectTalerSupport);
           }),
         },
       }}
-      clipboardToggle={clipboardToggle}
-      devModeToggle={{
-        value: devMode,
+      advanceToggle={{
+        value: settings.advanceMode,
         button: {
-          onClick: pushAlertOnError(toggle),
+          onClick: safely("update advance mode", async () => {
+            updateSettings("advanceMode", !settings.advanceMode);
+          }),
+        },
+      }}
+      langToggle={{
+        value: settings.langSelector,
+        button: {
+          onClick: safely("update lang selector", async () => {
+            updateSettings("langSelector", !settings.langSelector);
+          }),
         },
       }}
       webexVersion={{
@@ -101,8 +107,8 @@ export interface ViewProps {
   deviceName: string;
   setDeviceName: (s: string) => Promise<void>;
   autoOpenToggle: ToggleHandler;
-  clipboardToggle: ToggleHandler;
-  devModeToggle: ToggleHandler;
+  advanceToggle: ToggleHandler;
+  langToggle: ToggleHandler;
   knownExchanges: Array<ExchangeListItem>;
   coreVersion: WalletCoreVersion | undefined;
   webexVersion: {
@@ -114,8 +120,8 @@ export interface ViewProps {
 export function SettingsView({
   knownExchanges,
   autoOpenToggle,
-  clipboardToggle,
-  devModeToggle,
+  advanceToggle,
+  langToggle,
   coreVersion,
   webexVersion,
 }: ViewProps): VNode {
@@ -204,45 +210,19 @@ export function SettingsView({
           </LinkPrimary>
         </div>
 
-        <JustInDevMode>
-          <SubTitle>
-            <i18n.Translate>Display</i18n.Translate>
-          </SubTitle>
-          <Input>
-            <SelectList
-              label={<i18n.Translate>Current Language</i18n.Translate>}
-              list={supportedLang}
-              name="lang"
-              value={lang}
-              onChange={(v) => changeLanguage(v)}
-            />
-          </Input>
-        </JustInDevMode>
-        <SubTitle>
-          <i18n.Translate>Version</i18n.Translate>
-        </SubTitle>
-        {coreVersion && (
-          <Part
-            title={i18n.str`Wallet Core`}
-            text={
-              <span>
-                {coreVersion.version}{" "}
-                <JustInDevMode>{coreVersion.hash}</JustInDevMode>
-              </span>
-            }
-          />
-        )}
         <Part
           title={i18n.str`Web Extension`}
           text={
             <span>
               {webexVersion.version}{" "}
-              <JustInDevMode>{webexVersion.hash}</JustInDevMode>
+              <EnabledBySettings name="advanceMode">
+                {webexVersion.hash}
+              </EnabledBySettings>
             </span>
           }
         />
         {coreVersion && (
-          <JustInDevMode>
+          <EnabledBySettings name="advanceMode">
             <Part
               title={i18n.str`Exchange compatibility`}
               text={<span>{coreVersion.exchange}</span>}
@@ -255,18 +235,42 @@ export function SettingsView({
               title={i18n.str`Bank compatibility`}
               text={<span>{coreVersion.bank}</span>}
             />
-          </JustInDevMode>
+          </EnabledBySettings>
         )}
         <SubTitle>
-          <i18n.Translate>Troubleshooting</i18n.Translate>
+          <i18n.Translate>Advance mode</i18n.Translate>
         </SubTitle>
         <Checkbox
-          label={i18n.str`Developer mode`}
+          label={i18n.str`Enable advance mode`}
           name="devMode"
-          description={i18n.str`More options and information useful for 
debugging`}
-          enabled={devModeToggle.value!}
-          onToggle={devModeToggle.button.onClick!}
+          description={i18n.str`Show more information and options in the UI`}
+          enabled={advanceToggle.value!}
+          onToggle={advanceToggle.button.onClick!}
+        />
+        <EnabledBySettings name="advanceMode">
+          <AdvanceSettings />
+        </EnabledBySettings>
+        <Checkbox
+          label={i18n.str`Lang selector`}
+          name="langSelector"
+          description={i18n.str`Allows to manually change the language of the 
UI. Otherwise it will be automatically selected by your browser configuration.`}
+          enabled={langToggle.value!}
+          onToggle={langToggle.button.onClick!}
         />
+        <EnabledBySettings name="langSelector">
+          <SubTitle>
+            <i18n.Translate>Display</i18n.Translate>
+          </SubTitle>
+          <Input>
+            <SelectList
+              label={<i18n.Translate>Current Language</i18n.Translate>}
+              list={supportedLang}
+              name="lang"
+              value={lang}
+              onChange={(v) => changeLanguage(v)}
+            />
+          </Input>
+        </EnabledBySettings>
         <SubTitle>
           <i18n.Translate>Navigator</i18n.Translate>
         </SubTitle>
@@ -283,6 +287,77 @@ export function SettingsView({
           enabled={autoOpenToggle.value!}
           onToggle={autoOpenToggle.button.onClick!}
         />
+        <SubTitle>
+          <i18n.Translate>Version</i18n.Translate>
+        </SubTitle>
+        {coreVersion && (
+          <Part
+            title={i18n.str`Wallet Core`}
+            text={
+              <span>
+                {coreVersion.version}{" "}
+                <EnabledBySettings name="advanceMode">
+                  {coreVersion.hash}
+                </EnabledBySettings>
+              </span>
+            }
+          />
+        )}
+      </section>
+    </Fragment>
+  );
+}
+
+type Info = { label: TranslatedString; description: TranslatedString };
+type Options = {
+  [k in keyof Settings]?: Info;
+};
+function AdvanceSettings(): VNode {
+  const [settings, updateSettings] = useSettings();
+  const { i18n } = useTranslationContext();
+  const o: Options = {
+    backup: {
+      label: i18n.str`Show backup feature`,
+      description: i18n.str`Backup integration still in beta.`,
+    },
+    deleteActiveTransactions: {
+      label: i18n.str`Show delete active transaction`,
+      description: i18n.str`Deleting active transaction is not safe and you 
may loose your coins.`,
+    },
+    extendedAccountTypes: {
+      label: i18n.str`Show more account types on deposit`,
+      description: i18n.str`Extends the UI to more payment target types.`,
+    },
+    showJsonOnError: {
+      label: i18n.str`Show JSON on error`,
+      description: i18n.str`Print more information about the error. Useful for 
debugging.`,
+    },
+    walletAllowHttp: {
+      label: i18n.str`Allow HTTP connections`,
+      description: i18n.str`Using HTTP connection may be faster but unsafe 
(wallet restart required)`,
+    },
+    walletBatchWithdrawal: {
+      label: i18n.str`Allow batch withdrawals`,
+      description: i18n.str`Using the batch withdrawal API allows faster 
withdrawals (wallet restart required)`,
+    },
+  };
+  return (
+    <Fragment>
+      <section>
+        {Object.entries(o).map(([name, { label, description }]) => {
+          const settingsName = name as keyof Settings;
+          return (
+            <Checkbox
+              label={label}
+              name={name}
+              description={description}
+              enabled={settings[settingsName]}
+              onToggle={async () => {
+                updateSettings(settingsName, !settings[settingsName]);
+              }}
+            />
+          );
+        })}
       </section>
     </Fragment>
   );
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx 
b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index 1ef0f0b79..9bcae8997 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -34,6 +34,7 @@ import {
   WithdrawalType,
 } from "@gnu-taler/taler-util";
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
 import { styled } from "@linaria/react";
 import { differenceInSeconds, isPast } from "date-fns";
 import { ComponentChildren, Fragment, h, VNode } from "preact";
@@ -43,7 +44,6 @@ import { Amount } from "../components/Amount.js";
 import { BankDetailsByPaytoType } from 
"../components/BankDetailsByPaytoType.js";
 import { CopyButton } from "../components/CopyButton.js";
 import { AlertView, ErrorAlertView } from "../components/CurrentAlerts.js";
-import { JustInDevMode } from "../components/JustInDevMode.js";
 import { Loading } from "../components/Loading.js";
 import { Kind, Part, PartCollapsible, PartPayto } from "../components/Part.js";
 import { QR } from "../components/QR.js";
@@ -61,12 +61,12 @@ import {
 import { Time } from "../components/Time.js";
 import { alertFromError, useAlertContext } from "../context/alert.js";
 import { useBackendContext } from "../context/backend.js";
-import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
 import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
 import { Button } from "../mui/Button.js";
 import { SafeHandler } from "../mui/handlers.js";
 import { Pages } from "../NavigationBar.js";
 import { assertUnreachable } from "../utils/index.js";
+import { EnabledBySettings } from "../components/EnabledBySettings.js";
 
 interface Props {
   tid: string;
@@ -359,18 +359,15 @@ function TransactionTemplate({
                 <i18n.Translate>Cancel</i18n.Translate>
               </Button>
             ) : (
-              //WORKAROUND
-              //Able to delete tx in dev mode
-              //FIXME: remove this when DD37 is implemented
-              <JustInDevMode>
+              <EnabledBySettings name="deleteActiveTransactions">
                 <Button
                   variant="contained"
                   color="error"
                   onClick={doCheckBeforeForget as SafeHandler<void>}
                 >
-                  <i18n.Translate>Forget</i18n.Translate>
+                  <i18n.Translate>Delete</i18n.Translate>
                 </Button>
-              </JustInDevMode>
+              </EnabledBySettings>
             )
           ) : (
             <Button
@@ -378,7 +375,7 @@ function TransactionTemplate({
               color="error"
               onClick={doCheckBeforeForget as SafeHandler<void>}
             >
-              <i18n.Translate>Forget</i18n.Translate>
+              <i18n.Translate>Delete</i18n.Translate>
             </Button>
           )}
         </div>
diff --git a/packages/taler-wallet-webextension/src/walletEntryPoint.dev.tsx 
b/packages/taler-wallet-webextension/src/walletEntryPoint.dev.tsx
index c2906373c..60a5970e4 100644
--- a/packages/taler-wallet-webextension/src/walletEntryPoint.dev.tsx
+++ b/packages/taler-wallet-webextension/src/walletEntryPoint.dev.tsx
@@ -27,7 +27,6 @@ import { setupPlatform } from "./platform/foreground.js";
 import devAPI from "./platform/dev.js";
 import { Application } from "./wallet/Application.js";
 
-console.log("Wallet setup for Dev API");
 setupPlatform(devAPI);
 
 function main(): void {
diff --git a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx 
b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
index 84822b8e6..1bd42796b 100644
--- a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
+++ b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
@@ -33,10 +33,8 @@ const isFirefox = typeof (window as any)["InstallTrigger"] 
!== "undefined";
 //FIXME: create different entry point for any platform instead of
 //switching in runtime
 if (isFirefox) {
-  console.log("Wallet setup for Firefox API");
   setupPlatform(firefoxAPI);
 } else {
-  console.log("Wallet setup for Chrome API");
   setupPlatform(chromeAPI);
 }
 
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts 
b/packages/taler-wallet-webextension/src/wxApi.ts
index d15528699..ce1dac14f 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -156,7 +156,7 @@ class WalletApiClientImpl implements WalletCoreApiClient {
       };
       response = await platform.sendMessageToBackground(message);
     } catch (e) {
-      console.log("Error calling backend");
+      logger.error("Error calling backend", e);
       throw new Error(`Error contacting backend: ${e}`);
     }
     if (response.type === "error") {
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts 
b/packages/taler-wallet-webextension/src/wxBackend.ts
index bf91e8521..8acc41247 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -319,12 +319,19 @@ async function reinitWallet(): Promise<void> {
     timer = new SetTimeoutTimerAPI();
   }
 
+  const settings = await platform.getSettingsFromStorage();
   logger.info("Setting up wallet");
   const wallet = await Wallet.create(
     currentDatabase,
     httpLib,
     timer,
     cryptoWorker,
+    {
+      features: {
+        allowHttp: settings.walletAllowHttp,
+        batchWithdrawal: settings.walletBatchWithdrawal,
+      },
+    },
   );
   try {
     await wallet.handleCoreApiRequest("initWallet", "native-init", {});

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