gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: remove dead code


From: gnunet
Subject: [taler-wallet-core] branch master updated: remove dead code
Date: Fri, 08 Mar 2024 13:20:25 +0100

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 2a4dbc67e remove dead code
2a4dbc67e is described below

commit 2a4dbc67e8d1e6a256431e34f0b2e0e19d204f70
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Mar 8 09:20:02 2024 -0300

    remove dead code
---
 packages/demobank-ui/src/Routing.tsx               |  22 +--
 packages/demobank-ui/src/{components => }/app.tsx  |  89 +++++----
 .../demobank-ui/src/components/Cashouts/state.ts   |   2 +-
 .../demobank-ui/src/components/Cashouts/test.ts    |  17 +-
 .../demobank-ui/src/components/Cashouts/views.tsx  |   2 +-
 .../src/components/Transactions/state.ts           |   2 +-
 .../src/components/Transactions/test.ts            | 129 +++++++------
 packages/demobank-ui/src/context/backend.ts        |  79 --------
 packages/demobank-ui/src/context/config.ts         |   8 +-
 packages/demobank-ui/src/endpoints.ts              |  48 -----
 .../src/hooks/{access.ts => account.ts}            |   8 +-
 packages/demobank-ui/src/hooks/async.ts            |  80 ---------
 packages/demobank-ui/src/hooks/bank-state.ts       |  11 ++
 packages/demobank-ui/src/hooks/form.ts             | 100 +++++++++++
 packages/demobank-ui/src/hooks/index.ts            |  60 -------
 packages/demobank-ui/src/hooks/preferences.ts      |  67 +++----
 .../src/hooks/{circuit.ts => regional.ts}          |  12 +-
 .../src/hooks/{backend.ts => session.ts}           |  42 ++---
 packages/demobank-ui/src/index.tsx                 |   2 +-
 .../demobank-ui/src/pages/AccountPage/state.ts     |   2 +-
 packages/demobank-ui/src/pages/BankFrame.tsx       |  10 +-
 packages/demobank-ui/src/pages/LoginForm.tsx       |  12 +-
 .../demobank-ui/src/pages/OperationState/state.ts  |   6 +-
 packages/demobank-ui/src/pages/PaymentOptions.tsx  |   6 +-
 .../src/pages/PaytoWireTransferForm.tsx            |   4 +-
 .../demobank-ui/src/pages/ProfileNavigation.tsx    |   4 +-
 .../demobank-ui/src/pages/PublicHistoriesPage.tsx  |   2 +-
 packages/demobank-ui/src/pages/QrCodeSection.tsx   |   4 +-
 .../demobank-ui/src/pages/SolveChallengePage.tsx   |   8 +-
 .../demobank-ui/src/pages/WalletWithdrawForm.tsx   |   4 +-
 packages/demobank-ui/src/pages/WireTransfer.tsx    |   6 +-
 .../src/pages/WithdrawalConfirmationQuestion.tsx   |   6 +-
 .../demobank-ui/src/pages/WithdrawalQRCode.tsx     |   2 +-
 .../src/pages/account/CashoutListForAccount.tsx    |   6 +-
 .../src/pages/account/ShowAccountDetails.tsx       |   6 +-
 .../src/pages/account/UpdateAccountPassword.tsx    |   4 +-
 .../demobank-ui/src/pages/admin/AccountForm.tsx    |   4 +-
 .../demobank-ui/src/pages/admin/AccountList.tsx    |   2 +-
 packages/demobank-ui/src/pages/admin/AdminHome.tsx |   2 +-
 .../src/pages/admin/CreateNewAccount.tsx           |   4 +-
 .../src/pages/{ => admin}/DownloadStats.tsx        |  10 +-
 .../demobank-ui/src/pages/admin/RemoveAccount.tsx  |   6 +-
 .../src/pages/{ => regional}/ConversionConfig.tsx  | 200 +++++++++------------
 .../pages/{business => regional}/CreateCashout.tsx |   8 +-
 .../{business => regional}/ShowCashoutDetails.tsx  |   2 +-
 packages/demobank-ui/src/stories.test.ts           |  12 +-
 46 files changed, 460 insertions(+), 662 deletions(-)

diff --git a/packages/demobank-ui/src/Routing.tsx 
b/packages/demobank-ui/src/Routing.tsx
index a8ed58db1..c85d74e17 100644
--- a/packages/demobank-ui/src/Routing.tsx
+++ b/packages/demobank-ui/src/Routing.tsx
@@ -27,12 +27,13 @@ import {
   TranslatedString,
   assertUnreachable,
 } from "@gnu-taler/taler-util";
+import { useEffect } from "preact/hooks";
 import { useBankCoreApiContext } from "./context/config.js";
+import { useNavigationContext } from "./context/navigation.js";
 import { useSettingsContext } from "./context/settings.js";
-import { useBackendState } from "./hooks/backend.js";
+import { useSessionState } from "./hooks/session.js";
 import { AccountPage } from "./pages/AccountPage/index.js";
 import { BankFrame } from "./pages/BankFrame.js";
-import { DownloadStats } from "./pages/DownloadStats.js";
 import { LoginForm } from "./pages/LoginForm.js";
 import { PublicHistoriesPage } from "./pages/PublicHistoriesPage.js";
 import { RegistrationPage } from "./pages/RegistrationPage.js";
@@ -44,19 +45,18 @@ import { ShowAccountDetails } from 
"./pages/account/ShowAccountDetails.js";
 import { UpdateAccountPassword } from 
"./pages/account/UpdateAccountPassword.js";
 import { AdminHome } from "./pages/admin/AdminHome.js";
 import { CreateNewAccount } from "./pages/admin/CreateNewAccount.js";
+import { DownloadStats } from "./pages/admin/DownloadStats.js";
 import { RemoveAccount } from "./pages/admin/RemoveAccount.js";
-import { CreateCashout } from "./pages/business/CreateCashout.js";
-import { ShowCashoutDetails } from "./pages/business/ShowCashoutDetails.js";
+import { ConversionConfig } from "./pages/regional/ConversionConfig.js";
+import { CreateCashout } from "./pages/regional/CreateCashout.js";
+import { ShowCashoutDetails } from "./pages/regional/ShowCashoutDetails.js";
 import { urlPattern, useCurrentLocation } from "./route.js";
-import { useNavigationContext } from "./context/navigation.js";
-import { useEffect } from "preact/hooks";
-import { ConversionConfig } from "./pages/ConversionConfig.js";
 
 export function Routing(): VNode {
-  const backend = useBackendState();
+  const session = useSessionState();
 
-  if (backend.state.status === "loggedIn") {
-    const { isUserAdministrator, username } = backend.state;
+  if (session.state.status === "loggedIn") {
+    const { isUserAdministrator, username } = session.state;
     return (
       <BankFrame account={username} 
routeAccountDetails={privatePages.myAccountDetails}>
         <PrivateRouting username={username} isAdmin={isUserAdministrator} />
@@ -67,7 +67,7 @@ export function Routing(): VNode {
     <BankFrame>
       <PublicRounting
         onLoggedUser={(username, token) => {
-          backend.logIn({ username, token: token });
+          session.logIn({ username, token: token });
         }}
       />
     </BankFrame>
diff --git a/packages/demobank-ui/src/components/app.tsx 
b/packages/demobank-ui/src/app.tsx
similarity index 58%
rename from packages/demobank-ui/src/components/app.tsx
rename to packages/demobank-ui/src/app.tsx
index 97778e6d7..3a7fafccf 100644
--- a/packages/demobank-ui/src/components/app.tsx
+++ b/packages/demobank-ui/src/app.tsx
@@ -20,21 +20,20 @@ import {
   setGlobalLogLevelFromString,
 } from "@gnu-taler/taler-util";
 import { Loading, TranslationProvider } from "@gnu-taler/web-util/browser";
-import { FunctionalComponent, h } from "preact";
+import { h } from "preact";
 import { useEffect, useState } from "preact/hooks";
 import { SWRConfig } from "swr";
-import { Routing } from "../Routing.js";
-import { BackendStateProvider } from "../context/backend.js";
-import { BankCoreApiProvider } from "../context/config.js";
-import { SettingsProvider } from "../context/settings.js";
-import { strings } from "../i18n/strings.js";
-import { BankFrame } from "../pages/BankFrame.js";
-import { BankUiSettings, fetchSettings } from "../settings.js";
-import { TalerWalletIntegrationBrowserProvider } from 
"../context/wallet-integration.js";
-import { BrowserHashNavigationProvider } from "../context/navigation.js";
+import { Routing } from "./Routing.js";
+import { BankCoreApiProvider } from "./context/config.js";
+import { BrowserHashNavigationProvider } from "./context/navigation.js";
+import { SettingsProvider } from "./context/settings.js";
+import { TalerWalletIntegrationBrowserProvider } from 
"./context/wallet-integration.js";
+import { strings } from "./i18n/strings.js";
+import { BankFrame } from "./pages/BankFrame.js";
+import { BankUiSettings, fetchSettings } from "./settings.js";
 const WITH_LOCAL_STORAGE_CACHE = false;
 
-const App: FunctionalComponent = () => {
+export function App() {
   const [settings, setSettings] = useState<BankUiSettings>();
   useEffect(() => {
     fetchSettings(setSettings);
@@ -51,43 +50,41 @@ const App: FunctionalComponent = () => {
           de: strings["de"].completeness,
         }}
       >
-        <BackendStateProvider>
-          <BankCoreApiProvider baseUrl={baseUrl} frameOnError={BankFrame}>
-            <SWRConfig
-              value={{
-                provider: WITH_LOCAL_STORAGE_CACHE
-                  ? localStorageProvider
-                  : undefined,
-                // normally, do not revalidate
-                revalidateOnFocus: false,
-                revalidateOnReconnect: false,
-                revalidateIfStale: false,
-                revalidateOnMount: undefined,
-                focusThrottleInterval: undefined,
+        <BankCoreApiProvider baseUrl={baseUrl} frameOnError={BankFrame}>
+          <SWRConfig
+            value={{
+              provider: WITH_LOCAL_STORAGE_CACHE
+                ? localStorageProvider
+                : undefined,
+              // normally, do not revalidate
+              revalidateOnFocus: false,
+              revalidateOnReconnect: false,
+              revalidateIfStale: false,
+              revalidateOnMount: undefined,
+              focusThrottleInterval: undefined,
 
-                // normally, do not refresh
-                refreshInterval: undefined,
-                dedupingInterval: 2000,
-                refreshWhenHidden: false,
-                refreshWhenOffline: false,
+              // normally, do not refresh
+              refreshInterval: undefined,
+              dedupingInterval: 2000,
+              refreshWhenHidden: false,
+              refreshWhenOffline: false,
 
-                // ignore errors
-                shouldRetryOnError: false,
-                errorRetryCount: 0,
-                errorRetryInterval: undefined,
+              // ignore errors
+              shouldRetryOnError: false,
+              errorRetryCount: 0,
+              errorRetryInterval: undefined,
 
-                // do not go to loading again if already has data
-                keepPreviousData: true,
-              }}
-            >
-              <TalerWalletIntegrationBrowserProvider>
-                <BrowserHashNavigationProvider>
-                  <Routing />
-                </BrowserHashNavigationProvider>
-              </TalerWalletIntegrationBrowserProvider>
-            </SWRConfig>
-          </BankCoreApiProvider>
-        </BackendStateProvider>
+              // do not go to loading again if already has data
+              keepPreviousData: true,
+            }}
+          >
+            <TalerWalletIntegrationBrowserProvider>
+              <BrowserHashNavigationProvider>
+                <Routing />
+              </BrowserHashNavigationProvider>
+            </TalerWalletIntegrationBrowserProvider>
+          </SWRConfig>
+        </BankCoreApiProvider>
       </TranslationProvider>
     </SettingsProvider>
   );
@@ -108,8 +105,6 @@ function localStorageProvider(): Map<unknown, unknown> {
   return map;
 }
 
-export default App;
-
 function getInitialBackendBaseURL(
   backendFromSettings: string | undefined,
 ): string {
diff --git a/packages/demobank-ui/src/components/Cashouts/state.ts 
b/packages/demobank-ui/src/components/Cashouts/state.ts
index 344b93e14..8616faa1b 100644
--- a/packages/demobank-ui/src/components/Cashouts/state.ts
+++ b/packages/demobank-ui/src/components/Cashouts/state.ts
@@ -15,7 +15,7 @@
  */
 
 import { TalerError } from "@gnu-taler/taler-util";
-import { useCashouts } from "../../hooks/circuit.js";
+import { useCashouts } from "../../hooks/regional.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState({
diff --git a/packages/demobank-ui/src/components/Cashouts/test.ts 
b/packages/demobank-ui/src/components/Cashouts/test.ts
index 569cbc6f0..4bd6b5eac 100644
--- a/packages/demobank-ui/src/components/Cashouts/test.ts
+++ b/packages/demobank-ui/src/components/Cashouts/test.ts
@@ -22,7 +22,6 @@
 import * as tests from "@gnu-taler/web-util/testing";
 import { SwrMockEnvironment } from "@gnu-taler/web-util/testing";
 import { expect } from "chai";
-import { CASHOUT_API_EXAMPLE } from "../../endpoints.js";
 import { Props } from "./index.js";
 import { useComponentState } from "./state.js";
 import { buildNullRoutDefinition } from "../../route.js";
@@ -36,15 +35,15 @@ describe("Cashout states", () => {
       routeCashoutDetails: buildNullRoutDefinition(),
     };
 
-    env.addRequestExpectation(CASHOUT_API_EXAMPLE.LIST_FIRST_PAGE, {
-      response: {
-        cashouts: [],
-      },
-    });
+    // env.addRequestExpectation(CASHOUT_API_EXAMPLE.LIST_FIRST_PAGE, {
+    //   response: {
+    //     cashouts: [],
+    //   },
+    // });
 
-    env.addRequestExpectation(CASHOUT_API_EXAMPLE.MULTI_GET_EMPTY_FIRST_PAGE, {
-      response: [],
-    });
+    // 
env.addRequestExpectation(CASHOUT_API_EXAMPLE.MULTI_GET_EMPTY_FIRST_PAGE, {
+    //   response: [],
+    // });
 
     const hookBehavior = await tests.hookBehaveLikeThis(
       useComponentState,
diff --git a/packages/demobank-ui/src/components/Cashouts/views.tsx 
b/packages/demobank-ui/src/components/Cashouts/views.tsx
index 09e986dd4..7f16d5840 100644
--- a/packages/demobank-ui/src/components/Cashouts/views.tsx
+++ b/packages/demobank-ui/src/components/Cashouts/views.tsx
@@ -29,7 +29,7 @@ import {
 } from "@gnu-taler/web-util/browser";
 import { format } from "date-fns";
 import { Fragment, VNode, h } from "preact";
-import { useConversionInfo } from "../../hooks/circuit.js";
+import { useConversionInfo } from "../../hooks/regional.js";
 import { RenderAmount } from "../../pages/PaytoWireTransferForm.js";
 import { ErrorLoadingWithDebug } from "../ErrorLoadingWithDebug.js";
 import { State } from "./index.js";
diff --git a/packages/demobank-ui/src/components/Transactions/state.ts 
b/packages/demobank-ui/src/components/Transactions/state.ts
index 40e1b0ced..3e9103b59 100644
--- a/packages/demobank-ui/src/components/Transactions/state.ts
+++ b/packages/demobank-ui/src/components/Transactions/state.ts
@@ -20,7 +20,7 @@ import {
   TalerError,
   parsePaytoUri,
 } from "@gnu-taler/taler-util";
-import { useTransactions } from "../../hooks/access.js";
+import { useTransactions } from "../../hooks/account.js";
 import { Props, State, Transaction } from "./index.js";
 
 export function useComponentState({ account, routeCreateWireTransfer }: 
Props): State {
diff --git a/packages/demobank-ui/src/components/Transactions/test.ts 
b/packages/demobank-ui/src/components/Transactions/test.ts
index 9ded218c1..d9442c742 100644
--- a/packages/demobank-ui/src/components/Transactions/test.ts
+++ b/packages/demobank-ui/src/components/Transactions/test.ts
@@ -23,7 +23,6 @@ import { TalerErrorCode } from "@gnu-taler/taler-util";
 import * as tests from "@gnu-taler/web-util/testing";
 import { SwrMockEnvironment } from "@gnu-taler/web-util/testing";
 import { expect } from "chai";
-import { TRANSACTION_API_EXAMPLE } from "../../endpoints.js";
 import { Props } from "./index.js";
 import { useComponentState } from "./state.js";
 
@@ -36,63 +35,63 @@ describe("Transaction states", () => {
       routeCreateWireTransfer: undefined,
     };
 
-    env.addRequestExpectation(TRANSACTION_API_EXAMPLE.LIST_FIRST_PAGE, {
-      response: {
-        data: {
-          transactions: [
-            {
-              creditorIban: "DE159593",
-              creditorBic: "SANDBOXX",
-              creditorName: "exchange company",
-              debtorIban: "DE118695",
-              debtorBic: "SANDBOXX",
-              debtorName: "Name unknown",
-              amount: "1",
-              currency: "KUDOS",
-              subject:
-                "Taler Withdrawal 
N588V8XE9TR49HKAXFQ20P0EQ0EYW2AC9NNANV8ZP5P59N6N0410",
-              date: "2022-12-12Z",
-              uid: "8PPFR9EM",
-              direction: "DBIT",
-              pmtInfId: null,
-              msgId: null,
-            },
-            {
-              creditorIban: "DE159593",
-              creditorBic: "SANDBOXX",
-              creditorName: "exchange company",
-              debtorIban: "DE118695",
-              debtorBic: "SANDBOXX",
-              debtorName: "Name unknown",
-              amount: "5.00",
-              currency: "KUDOS",
-              subject: "HNEWWT679TQC5P1BVXJS48FX9NW18FWM6PTK2N80Z8GVT0ACGNK0",
-              date: "2022-12-07Z",
-              uid: "7FZJC3RJ",
-              direction: "DBIT",
-              pmtInfId: null,
-              msgId: null,
-            },
-            {
-              creditorIban: "DE118695",
-              creditorBic: "SANDBOXX",
-              creditorName: "Name unknown",
-              debtorIban: "DE579516",
-              debtorBic: "SANDBOXX",
-              debtorName: "The Bank",
-              amount: "100",
-              currency: "KUDOS",
-              subject: "Sign-up bonus",
-              date: "2022-12-07Z",
-              uid: "I31A06J8",
-              direction: "CRDT",
-              pmtInfId: null,
-              msgId: null,
-            },
-          ],
-        },
-      },
-    });
+    // env.addRequestExpectation(TRANSACTION_API_EXAMPLE.LIST_FIRST_PAGE, {
+    //   response: {
+    //     data: {
+    //       transactions: [
+    //         {
+    //           creditorIban: "DE159593",
+    //           creditorBic: "SANDBOXX",
+    //           creditorName: "exchange company",
+    //           debtorIban: "DE118695",
+    //           debtorBic: "SANDBOXX",
+    //           debtorName: "Name unknown",
+    //           amount: "1",
+    //           currency: "KUDOS",
+    //           subject:
+    //             "Taler Withdrawal 
N588V8XE9TR49HKAXFQ20P0EQ0EYW2AC9NNANV8ZP5P59N6N0410",
+    //           date: "2022-12-12Z",
+    //           uid: "8PPFR9EM",
+    //           direction: "DBIT",
+    //           pmtInfId: null,
+    //           msgId: null,
+    //         },
+    //         {
+    //           creditorIban: "DE159593",
+    //           creditorBic: "SANDBOXX",
+    //           creditorName: "exchange company",
+    //           debtorIban: "DE118695",
+    //           debtorBic: "SANDBOXX",
+    //           debtorName: "Name unknown",
+    //           amount: "5.00",
+    //           currency: "KUDOS",
+    //           subject: 
"HNEWWT679TQC5P1BVXJS48FX9NW18FWM6PTK2N80Z8GVT0ACGNK0",
+    //           date: "2022-12-07Z",
+    //           uid: "7FZJC3RJ",
+    //           direction: "DBIT",
+    //           pmtInfId: null,
+    //           msgId: null,
+    //         },
+    //         {
+    //           creditorIban: "DE118695",
+    //           creditorBic: "SANDBOXX",
+    //           creditorName: "Name unknown",
+    //           debtorIban: "DE579516",
+    //           debtorBic: "SANDBOXX",
+    //           debtorName: "The Bank",
+    //           amount: "100",
+    //           currency: "KUDOS",
+    //           subject: "Sign-up bonus",
+    //           date: "2022-12-07Z",
+    //           uid: "I31A06J8",
+    //           direction: "CRDT",
+    //           pmtInfId: null,
+    //           msgId: null,
+    //         },
+    //       ],
+    //     },
+    //   },
+    // });
 
     const hookBehavior = await tests.hookBehaveLikeThis(
       useComponentState,
@@ -165,13 +164,13 @@ describe("Transaction states", () => {
       routeCreateWireTransfer: undefined,
     };
 
-    env.addRequestExpectation(TRANSACTION_API_EXAMPLE.LIST_ERROR, {
-      response: {
-        error: {
-          code: TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED,
-        },
-      },
-    });
+    // env.addRequestExpectation(TRANSACTION_API_EXAMPLE.LIST_ERROR, {
+    //   response: {
+    //     error: {
+    //       code: TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED,
+    //     },
+    //   },
+    // });
 
     const hookBehavior = await tests.hookBehaveLikeThis(
       useComponentState,
diff --git a/packages/demobank-ui/src/context/backend.ts 
b/packages/demobank-ui/src/context/backend.ts
deleted file mode 100644
index 18b4a1f03..000000000
--- a/packages/demobank-ui/src/context/backend.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022-2024 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-import { ComponentChildren, createContext, h, VNode } from "preact";
-import { useContext } from "preact/hooks";
-import {
-  BackendStateHandler,
-  defaultState,
-  useBackendState,
-} from "../hooks/backend.js";
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-
-export type Type = BackendStateHandler;
-
-const initial: Type = {
-  state: defaultState,
-  logOut() {
-    null;
-  },
-  expired() {
-    null;
-  },
-  logIn(_info) {
-    null;
-  },
-};
-const Context = createContext<Type>(initial);
-
-export const useBackendContext = (): Type => useContext(Context);
-
-export const BackendStateProvider = ({
-  children,
-}: {
-  children: ComponentChildren;
-}): VNode => {
-  const value = useBackendState();
-
-  return h(Context.Provider, {
-    value,
-    children,
-  });
-};
-
-export const BackendStateProviderTesting = ({
-  children,
-  state,
-}: {
-  children: ComponentChildren;
-  state: typeof defaultState;
-}): VNode => {
-  const value: BackendStateHandler = {
-    state,
-    logIn: () => {},
-    expired: () => {},
-    logOut: () => {},
-  };
-
-  return h(Context.Provider, {
-    value,
-    children,
-  });
-};
diff --git a/packages/demobank-ui/src/context/config.ts 
b/packages/demobank-ui/src/context/config.ts
index e968b7ff4..72c176679 100644
--- a/packages/demobank-ui/src/context/config.ts
+++ b/packages/demobank-ui/src/context/config.ts
@@ -46,12 +46,12 @@ import {
   revalidateAccountDetails,
   revalidatePublicAccounts,
   revalidateTransactions,
-} from "../hooks/access.js";
+} from "../hooks/account.js";
 import {
   revalidateBusinessAccounts,
   revalidateCashouts,
   revalidateConversionInfo,
-} from "../hooks/circuit.js";
+} from "../hooks/regional.js";
 
 /**
  *
@@ -156,6 +156,10 @@ export const BankCoreApiProvider = ({
     children,
   });
 };
+
+/**
+ * 
+ */
 class CacheAwareTalerBankConversionHttpClient extends 
TalerBankConversionHttpClient {
   constructor(baseUrl: string, httpClient?: HttpRequestLibrary) {
     super(baseUrl, httpClient);
diff --git a/packages/demobank-ui/src/endpoints.ts 
b/packages/demobank-ui/src/endpoints.ts
deleted file mode 100644
index b68a36529..000000000
--- a/packages/demobank-ui/src/endpoints.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022-2024 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-
-export const TRANSACTION_API_EXAMPLE = {
-  LIST_FIRST_PAGE: {
-    method: "get" as const,
-    url: '["access-api/accounts/myAccount/transactions",null,20]',
-  },
-  LIST_ERROR: {
-    method: "get" as const,
-    url: '["access-api/accounts/myAccount/transactions",null,20]',
-    code: 500,
-  },
-  LIST_NOT_FOUND: {
-    method: "get" as const,
-    url: '["access-api/accounts/myAccount/transactions",null,20]',
-    code: 404,
-  },
-};
-
-export const CASHOUT_API_EXAMPLE = {
-  LIST_FIRST_PAGE: {
-    method: "get" as const,
-    url: '["circuit-api/cashouts","123"]',
-  },
-  MULTI_GET_EMPTY_FIRST_PAGE: {
-    method: "get" as const,
-    url: "[[]]",
-  },
-};
diff --git a/packages/demobank-ui/src/hooks/access.ts 
b/packages/demobank-ui/src/hooks/account.ts
similarity index 97%
rename from packages/demobank-ui/src/hooks/access.ts
rename to packages/demobank-ui/src/hooks/account.ts
index a101dc83e..61a11b1a5 100644
--- a/packages/demobank-ui/src/hooks/access.ts
+++ b/packages/demobank-ui/src/hooks/account.ts
@@ -22,7 +22,7 @@ import {
 } from "@gnu-taler/taler-util";
 import { useEffect, useState } from "preact/hooks";
 import { PAGE_SIZE } from "../utils.js";
-import { useBackendState } from "./backend.js";
+import { useSessionState } from "./session.js";
 
 // FIX default import https://github.com/microsoft/TypeScript/issues/49189
 import _useSWR, { SWRHook, mutate } from "swr";
@@ -43,7 +43,7 @@ export function revalidateAccountDetails() {
 }
 
 export function useAccountDetails(account: string) {
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const { api } = useBankCoreApiContext();
 
   async function fetcher([username, token]: [string, AccessToken]) {
@@ -114,7 +114,7 @@ export function revalidateTransactionDetails() {
   );
 }
 export function useTransactionDetails(account: string, tid: number) {
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const token =
     credentials.status !== "loggedIn" ? undefined : credentials.token;
   const { api } = useBankCoreApiContext();
@@ -228,7 +228,7 @@ export function revalidateTransactions() {
   );
 }
 export function useTransactions(account: string, initial?: number) {
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const token =
     credentials.status !== "loggedIn" ? undefined : credentials.token;
 
diff --git a/packages/demobank-ui/src/hooks/async.ts 
b/packages/demobank-ui/src/hooks/async.ts
deleted file mode 100644
index 556673992..000000000
--- a/packages/demobank-ui/src/hooks/async.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022-2024 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-import { useState } from "preact/hooks";
-
-export interface Options {
-  slowTolerance: number;
-}
-
-export interface AsyncOperationApi<T> {
-  request: (...a: Array<unknown>) => void;
-  cancel: () => void;
-  data: T | undefined;
-  isSlow: boolean;
-  isLoading: boolean;
-  error: string | undefined;
-}
-
-export function useAsync<T>(
-  fn?: (...args: Array<unknown>) => Promise<T>,
-  { slowTolerance: tooLong }: Options = { slowTolerance: 1000 },
-): AsyncOperationApi<T> {
-  const [data, setData] = useState<T | undefined>(undefined);
-  const [isLoading, setLoading] = useState<boolean>(false);
-  const [error, setError] = useState<string | undefined>(undefined);
-  const [isSlow, setSlow] = useState(false);
-
-  const request = async (...args: Array<unknown>) => {
-    if (!fn) return;
-    setLoading(true);
-    const handler = setTimeout(() => {
-      setSlow(true);
-    }, tooLong);
-
-    try {
-      const result = await fn(...args);
-      setData(result);
-    } catch (error) {
-      if (error instanceof Error) {
-        setError(error.message);
-      } else {
-        setError(`Unknown error: ${error}`);
-      }
-    }
-    setLoading(false);
-    setSlow(false);
-    clearTimeout(handler);
-  };
-
-  function cancel() {
-    setLoading(false);
-    setSlow(false);
-  }
-
-  return {
-    request,
-    cancel,
-    data,
-    isSlow,
-    isLoading,
-    error,
-  };
-}
diff --git a/packages/demobank-ui/src/hooks/bank-state.ts 
b/packages/demobank-ui/src/hooks/bank-state.ts
index 15daf9180..83bb009cf 100644
--- a/packages/demobank-ui/src/hooks/bank-state.ts
+++ b/packages/demobank-ui/src/hooks/bank-state.ts
@@ -141,6 +141,8 @@ const codecForChallenge = (): Codec<ChallengeInProgess> =>
     .alternative("update-password", codecForChallengeUpdatePassword())
     .build("ChallengeInProgess");
 
+
+    
 interface BankState {
   currentWithdrawalOperationId: string | undefined;
   currentChallenge: ChallengeInProgess | undefined;
@@ -159,6 +161,14 @@ const defaultBankState: BankState = {
 
 const BANK_STATE_KEY = buildStorageKey("bank-app-state", codecForBankState());
 
+/**
+ * Client state saved in local storage.
+ * 
+ * This information is saved in the client because
+ * the backend server session API is not enough.
+ * 
+ * @returns tuple of [state, update(), reset()]
+ */
 export function useBankState(): [
   Readonly<BankState>,
   <T extends keyof BankState>(key: T, value: BankState[T]) => void,
@@ -175,3 +185,4 @@ export function useBankState(): [
   }
   return [value, updateField, reset];
 }
+
diff --git a/packages/demobank-ui/src/hooks/form.ts 
b/packages/demobank-ui/src/hooks/form.ts
new file mode 100644
index 000000000..26354b108
--- /dev/null
+++ b/packages/demobank-ui/src/hooks/form.ts
@@ -0,0 +1,100 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { AmountJson, TalerBankConversionApi, TranslatedString } from 
"@gnu-taler/taler-util";
+import { useState } from "preact/hooks";
+
+export type UIField = {
+  value: string | undefined;
+  onUpdate: (s: string) => void;
+  error: TranslatedString | undefined;
+}
+
+type FormHandler<T> = {
+  [k in keyof T]?:
+  T[k] extends string ? UIField :
+  T[k] extends AmountJson ? UIField :
+  FormHandler<T[k]>;
+}
+
+export type FormValues<T> = {
+  [k in keyof T]:
+  T[k] extends string ? (string | undefined) :
+  T[k] extends AmountJson ? (string | undefined) :
+  FormValues<T[k]>;
+}
+
+export type RecursivePartial<T> = {
+  [k in keyof T]?:
+  T[k] extends string ? (string) :
+  T[k] extends AmountJson ? (AmountJson) :
+  RecursivePartial<T[k]>;
+}
+
+export type FormErrors<T> = {
+  [k in keyof T]?:
+  T[k] extends string ? (TranslatedString) :
+  T[k] extends AmountJson ? (TranslatedString) :
+  FormErrors<T[k]>;
+}
+
+export type FormStatus<T> = {
+  status: "ok",
+  result: T,
+  errors: undefined,
+} | {
+  status: "fail",
+  result: RecursivePartial<T>,
+  errors: FormErrors<T>,
+}
+
+
+function constructFormHandler<T>(form: FormValues<T>, updateForm: (d: 
FormValues<T>) => void, errors: FormErrors<T> | undefined): FormHandler<T> {
+  const keys = (Object.keys(form) as Array<keyof T>)
+
+  const handler = keys.reduce((prev, fieldName) => {
+    const currentValue: any = form[fieldName];
+    const currentError: any = errors ? errors[fieldName] : undefined;
+    function updater(newValue: any) {
+      updateForm({ ...form, [fieldName]: newValue })
+    }
+    if (typeof currentValue === "object") {
+      const group = constructFormHandler(currentValue, updater, currentError)
+      // @ts-expect-error asdasd
+      prev[fieldName] = group
+      return prev;
+    }
+    const field: UIField = {
+      error: currentError,
+      value: currentValue,
+      onUpdate: updater
+    }
+    // @ts-expect-error asdasd
+    prev[fieldName] = field
+    return prev
+  }, {} as FormHandler<T>)
+
+  return handler;
+}
+
+export function useFormState<T>(defaultValue: FormValues<T>, check: (f: 
FormValues<T>) => FormStatus<T>): [FormHandler<T>, FormStatus<T>] {
+  const [form, updateForm] = useState<FormValues<T>>(defaultValue)
+
+  const status = check(form)
+  const handler = constructFormHandler(form, updateForm, status.errors)
+
+  return [handler, status]
+}
\ No newline at end of file
diff --git a/packages/demobank-ui/src/hooks/index.ts 
b/packages/demobank-ui/src/hooks/index.ts
deleted file mode 100644
index 2620f4697..000000000
--- a/packages/demobank-ui/src/hooks/index.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2022-2024 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-
-import { StateUpdater } from "preact/hooks";
-import { buildStorageKey, useLocalStorage } from "@gnu-taler/web-util/browser";
-import { codecForBoolean } from "@gnu-taler/taler-util";
-export type ValueOrFunction<T> = T | ((p: T) => T);
-
-const calculateRootPath = () => {
-  const rootPath =
-    typeof window !== "undefined"
-      ? window.location.origin + window.location.pathname
-      : "/";
-  return rootPath;
-};
-
-const BACKEND_URL_KEY = buildStorageKey("backend-url");
-const TRIED_LOGIN_KEY = buildStorageKey("tried-login", codecForBoolean());
-
-export function useBackendURL(
-  url?: string,
-): [string, boolean, StateUpdater<string>, () => void] {
-  const { value, update: setter } = useLocalStorage(
-    BACKEND_URL_KEY,
-    url || calculateRootPath(),
-  );
-
-  const {
-    value: triedToLog,
-    update: setTriedToLog,
-    reset: resetBackend,
-  } = useLocalStorage(TRIED_LOGIN_KEY);
-
-  const checkedSetter = (v: ValueOrFunction<string>) => {
-    setTriedToLog(true);
-    const computedValue =
-      v instanceof Function ? v(value) : v.replace(/\/$/, "");
-    return setter(computedValue);
-  };
-
-  return [value, !!triedToLog, checkedSetter, resetBackend];
-}
diff --git a/packages/demobank-ui/src/hooks/preferences.ts 
b/packages/demobank-ui/src/hooks/preferences.ts
index 454d840b2..454dc8d80 100644
--- a/packages/demobank-ui/src/hooks/preferences.ts
+++ b/packages/demobank-ui/src/hooks/preferences.ts
@@ -36,36 +36,6 @@ interface Preferences {
   showDebugInfo: boolean;
 }
 
-export function getAllBooleanPreferences(): Array<keyof Preferences> {
-  return [
-    "fastWithdrawal",
-    "showDebugInfo",
-    "showDemoDescription",
-    "showInstallWallet",
-    "showWithdrawalSuccess",
-  ];
-}
-
-export function getLabelForPreferences(
-  k: keyof Preferences,
-  i18n: ReturnType<typeof useTranslationContext>["i18n"],
-): TranslatedString {
-  switch (k) {
-    case "maxWithdrawalAmount":
-      return i18n.str`Max withdrawal amount`;
-    case "showWithdrawalSuccess":
-      return i18n.str`Show withdrawal confirmation`;
-    case "showDemoDescription":
-      return i18n.str`Show demo description`;
-    case "showInstallWallet":
-      return i18n.str`Show install wallet first`;
-    case "fastWithdrawal":
-      return i18n.str`Use fast withdrawal form`;
-    case "showDebugInfo":
-      return i18n.str`Show debug info`;
-  }
-}
-
 export const codecForPreferences = (): Codec<Preferences> =>
   buildCodecForObject<Preferences>()
     .property("showWithdrawalSuccess", codecForBoolean())
@@ -89,7 +59,11 @@ const BANK_PREFERENCES_KEY = buildStorageKey(
   "bank-preferences",
   codecForPreferences(),
 );
-
+/**
+ * User preferences.
+ * 
+ * @returns tuple of [state, update()]
+ */
 export function usePreferences(): [
   Readonly<Preferences>,
   <T extends keyof Preferences>(key: T, value: Preferences[T]) => void,
@@ -105,3 +79,34 @@ export function usePreferences(): [
   }
   return [value, updateField];
 }
+
+export function getAllBooleanPreferences(): Array<keyof Preferences> {
+  return [
+    "fastWithdrawal",
+    "showDebugInfo",
+    "showDemoDescription",
+    "showInstallWallet",
+    "showWithdrawalSuccess",
+  ];
+}
+
+export function getLabelForPreferences(
+  k: keyof Preferences,
+  i18n: ReturnType<typeof useTranslationContext>["i18n"],
+): TranslatedString {
+  switch (k) {
+    case "maxWithdrawalAmount":
+      return i18n.str`Max withdrawal amount`;
+    case "showWithdrawalSuccess":
+      return i18n.str`Show withdrawal confirmation`;
+    case "showDemoDescription":
+      return i18n.str`Show demo description`;
+    case "showInstallWallet":
+      return i18n.str`Show install wallet first`;
+    case "fastWithdrawal":
+      return i18n.str`Use fast withdrawal form`;
+    case "showDebugInfo":
+      return i18n.str`Show debug info`;
+  }
+}
+
diff --git a/packages/demobank-ui/src/hooks/circuit.ts 
b/packages/demobank-ui/src/hooks/regional.ts
similarity index 97%
rename from packages/demobank-ui/src/hooks/circuit.ts
rename to packages/demobank-ui/src/hooks/regional.ts
index f87cbd843..a9ebb30a2 100644
--- a/packages/demobank-ui/src/hooks/circuit.ts
+++ b/packages/demobank-ui/src/hooks/regional.ts
@@ -15,7 +15,7 @@
  */
 
 import { PAGE_SIZE } from "../utils.js";
-import { useBackendState } from "./backend.js";
+import { useSessionState } from "./session.js";
 
 import {
   AccessToken,
@@ -208,7 +208,7 @@ export function revalidateBusinessAccounts() {
   return mutate((key) => Array.isArray(key) && key[key.length - 1] === 
"getAccounts", undefined, { revalidate: true });
 }
 export function useBusinessAccounts() {
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const token =
     credentials.status !== "loggedIn" ? undefined : credentials.token;
   const { api } = useBankCoreApiContext();
@@ -280,7 +280,7 @@ export function revalidateOnePendingCashouts() {
   );
 }
 export function useOnePendingCashouts(account: string) {
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const { api, config } = useBankCoreApiContext();
   const token =
     credentials.status !== "loggedIn" ? undefined : credentials.token;
@@ -337,7 +337,7 @@ export function revalidateCashouts() {
   return mutate((key) => Array.isArray(key) && key[key.length - 1] === 
"useCashouts");
 }
 export function useCashouts(account: string) {
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const { api, config } = useBankCoreApiContext();
   const token =
     credentials.status !== "loggedIn" ? undefined : credentials.token;
@@ -390,7 +390,7 @@ export function revalidateCashoutDetails() {
   );
 }
 export function useCashoutDetails(cashoutId: number | undefined) {
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const creds = credentials.status !== "loggedIn" ? undefined : credentials;
   const { api } = useBankCoreApiContext();
 
@@ -444,7 +444,7 @@ export function useLastMonitorInfo(
   timeframe: TalerCorebankApi.MonitorTimeframeParam,
 ) {
   const { api } = useBankCoreApiContext();
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const token =
     credentials.status !== "loggedIn" ? undefined : credentials.token;
 
diff --git a/packages/demobank-ui/src/hooks/backend.ts 
b/packages/demobank-ui/src/hooks/session.ts
similarity index 73%
rename from packages/demobank-ui/src/hooks/backend.ts
rename to packages/demobank-ui/src/hooks/session.ts
index 8e9af533b..35f87e1be 100644
--- a/packages/demobank-ui/src/hooks/backend.ts
+++ b/packages/demobank-ui/src/hooks/session.ts
@@ -30,7 +30,7 @@ import { mutate } from "swr";
  * Has the information to reach and
  * authenticate at the bank's backend.
  */
-export type BackendState = LoggedIn | LoggedOut | Expired;
+export type SessionState = LoggedIn | LoggedOut | Expired;
 
 interface LoggedIn {
   status: "loggedIn";
@@ -47,55 +47,55 @@ interface LoggedOut {
   status: "loggedOut";
 }
 
-export const codecForBackendStateLoggedIn = (): Codec<LoggedIn> =>
+export const codecForSessionStateLoggedIn = (): Codec<LoggedIn> =>
   buildCodecForObject<LoggedIn>()
     .property("status", codecForConstString("loggedIn"))
     .property("username", codecForString())
     .property("token", codecForString() as Codec<AccessToken>)
     .property("isUserAdministrator", codecForBoolean())
-    .build("BackendState.LoggedIn");
+    .build("SessionState.LoggedIn");
 
-export const codecForBackendStateExpired = (): Codec<Expired> =>
+export const codecForSessionStateExpired = (): Codec<Expired> =>
   buildCodecForObject<Expired>()
     .property("status", codecForConstString("expired"))
     .property("username", codecForString())
     .property("isUserAdministrator", codecForBoolean())
-    .build("BackendState.Expired");
+    .build("SessionState.Expired");
 
-export const codecForBackendStateLoggedOut = (): Codec<LoggedOut> =>
+export const codecForSessionStateLoggedOut = (): Codec<LoggedOut> =>
   buildCodecForObject<LoggedOut>()
     .property("status", codecForConstString("loggedOut"))
-    .build("BackendState.LoggedOut");
+    .build("SessionState.LoggedOut");
 
-export const codecForBackendState = (): Codec<BackendState> =>
-  buildCodecForUnion<BackendState>()
+export const codecForSessionState = (): Codec<SessionState> =>
+  buildCodecForUnion<SessionState>()
     .discriminateOn("status")
-    .alternative("loggedIn", codecForBackendStateLoggedIn())
-    .alternative("loggedOut", codecForBackendStateLoggedOut())
-    .alternative("expired", codecForBackendStateExpired())
-    .build("BackendState");
+    .alternative("loggedIn", codecForSessionStateLoggedIn())
+    .alternative("loggedOut", codecForSessionStateLoggedOut())
+    .alternative("expired", codecForSessionStateExpired())
+    .build("SessionState");
 
-export const defaultState: BackendState = {
+export const defaultState: SessionState = {
   status: "loggedOut",
 };
 
-export interface BackendStateHandler {
-  state: BackendState;
+export interface SessionStateHandler {
+  state: SessionState;
   logOut(): void;
   expired(): void;
   logIn(info: { username: string; token: AccessToken }): void;
 }
 
-const BACKEND_STATE_KEY = buildStorageKey("bank-state", 
codecForBackendState());
+const SESSION_STATE_KEY = buildStorageKey("bank-state", 
codecForSessionState());
 
 /**
  * Return getters and setters for
  * login credentials and backend's
  * base URL.
  */
-export function useBackendState(): BackendStateHandler {
+export function useSessionState(): SessionStateHandler {
   const { value: state, update } = useLocalStorage(
-    BACKEND_STATE_KEY,
+    SESSION_STATE_KEY,
     defaultState,
   );
 
@@ -106,7 +106,7 @@ export function useBackendState(): BackendStateHandler {
     },
     expired() {
       if (state.status === "loggedOut") return;
-      const nextState: BackendState = {
+      const nextState: SessionState = {
         status: "expired",
         username: state.username,
         isUserAdministrator: state.username === "admin",
@@ -115,7 +115,7 @@ export function useBackendState(): BackendStateHandler {
     },
     logIn(info) {
       // admin is defined by the username
-      const nextState: BackendState = {
+      const nextState: SessionState = {
         status: "loggedIn",
         ...info,
         isUserAdministrator: info.username === "admin",
diff --git a/packages/demobank-ui/src/index.tsx 
b/packages/demobank-ui/src/index.tsx
index 5f00f1b68..f559288a3 100644
--- a/packages/demobank-ui/src/index.tsx
+++ b/packages/demobank-ui/src/index.tsx
@@ -14,7 +14,7 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import App from "./components/app.js";
+import { App } from "./app.js";
 import { h, render } from "preact";
 import "./scss/main.css";
 
diff --git a/packages/demobank-ui/src/pages/AccountPage/state.ts 
b/packages/demobank-ui/src/pages/AccountPage/state.ts
index b531ac757..e84fef025 100644
--- a/packages/demobank-ui/src/pages/AccountPage/state.ts
+++ b/packages/demobank-ui/src/pages/AccountPage/state.ts
@@ -21,7 +21,7 @@ import {
   assertUnreachable,
   parsePaytoUri,
 } from "@gnu-taler/taler-util";
-import { useAccountDetails } from "../../hooks/access.js";
+import { useAccountDetails } from "../../hooks/account.js";
 import { Props, State } from "./index.js";
 
 export function useComponentState({
diff --git a/packages/demobank-ui/src/pages/BankFrame.tsx 
b/packages/demobank-ui/src/pages/BankFrame.tsx
index e1b8d6b83..427e9a156 100644
--- a/packages/demobank-ui/src/pages/BankFrame.tsx
+++ b/packages/demobank-ui/src/pages/BankFrame.tsx
@@ -28,8 +28,8 @@ import { ComponentChildren, VNode, h } from "preact";
 import { useEffect, useErrorBoundary } from "preact/hooks";
 import { useBankCoreApiContext } from "../context/config.js";
 import { useSettingsContext } from "../context/settings.js";
-import { useAccountDetails } from "../hooks/access.js";
-import { useBackendState } from "../hooks/backend.js";
+import { useAccountDetails } from "../hooks/account.js";
+import { useSessionState } from "../hooks/session.js";
 import { useBankState } from "../hooks/bank-state.js";
 import {
   getAllBooleanPreferences,
@@ -52,7 +52,7 @@ export function BankFrame({
   children: ComponentChildren;
 }): VNode {
   const { i18n } = useTranslationContext();
-  const backend = useBackendState();
+  const session = useSessionState();
   const settings = useSettingsContext();
   const [preferences, updatePreferences] = usePreferences();
   const [, , resetBankState] = useBankState();
@@ -86,10 +86,10 @@ export function BankFrame({
           iconLinkURL={settings.iconLinkURL ?? "#"}
           profileURL={routeAccountDetails?.url({})}
           onLogout={
-            backend.state.status !== "loggedIn"
+            session.state.status !== "loggedIn"
               ? undefined
               : () => {
-                backend.logOut();
+                session.logOut();
                 resetBankState();
               }
           }
diff --git a/packages/demobank-ui/src/pages/LoginForm.tsx 
b/packages/demobank-ui/src/pages/LoginForm.tsx
index f0ca447e1..e62759415 100644
--- a/packages/demobank-ui/src/pages/LoginForm.tsx
+++ b/packages/demobank-ui/src/pages/LoginForm.tsx
@@ -27,7 +27,7 @@ import {
 import { VNode, h } from "preact";
 import { useEffect, useRef, useState } from "preact/hooks";
 import { useBankCoreApiContext } from "../context/config.js";
-import { useBackendState } from "../hooks/backend.js";
+import { useSessionState } from "../hooks/session.js";
 import { RouteDefinition } from "../route.js";
 import { undefinedIfEmpty } from "../utils.js";
 import { doAutoFocus } from "./PaytoWireTransferForm.js";
@@ -44,10 +44,10 @@ export function LoginForm({
   currentUser?: string;
   routeRegister?: RouteDefinition;
 }): VNode {
-  const backend = useBackendState();
+  const session = useSessionState();
 
   const sessionUser =
-    backend.state.status !== "loggedOut" ? backend.state.username : undefined;
+    session.state.status !== "loggedOut" ? session.state.username : undefined;
   const [username, setUsername] = useState<string | undefined>(
     currentUser ?? sessionUser,
   );
@@ -73,7 +73,7 @@ export function LoginForm({
     });
 
   async function doLogout() {
-    backend.logOut();
+    session.logOut();
   }
 
   const loginHandler = !username || !password ? undefined : withErrorHandler(
@@ -86,7 +86,7 @@ export function LoginForm({
         refreshable: true,
       }),
     (result) => {
-      backend.logIn({ username, token: result.body.access_token })
+      session.logIn({ username, token: result.body.access_token })
     },
     (fail) => {
       switch (fail.case) {
@@ -173,7 +173,7 @@ export function LoginForm({
             </div>
           </div>
 
-          {backend.state.status !== "loggedOut" ? (
+          {session.state.status !== "loggedOut" ? (
             <div class="flex justify-between">
               <button
                 type="submit"
diff --git a/packages/demobank-ui/src/pages/OperationState/state.ts 
b/packages/demobank-ui/src/pages/OperationState/state.ts
index ad2d91ee4..693179d40 100644
--- a/packages/demobank-ui/src/pages/OperationState/state.ts
+++ b/packages/demobank-ui/src/pages/OperationState/state.ts
@@ -28,8 +28,8 @@ import { utils } from "@gnu-taler/web-util/browser";
 import { useEffect, useState } from "preact/hooks";
 import { mutate } from "swr";
 import { useBankCoreApiContext } from "../../context/config.js";
-import { useWithdrawalDetails } from "../../hooks/access.js";
-import { useBackendState } from "../../hooks/backend.js";
+import { useWithdrawalDetails } from "../../hooks/account.js";
+import { useSessionState } from "../../hooks/session.js";
 import { useBankState } from "../../hooks/bank-state.js";
 import { usePreferences } from "../../hooks/preferences.js";
 import { Props, State } from "./index.js";
@@ -43,7 +43,7 @@ export function useComponentState({
 }: Props): utils.RecursiveState<State> {
   const [settings] = usePreferences();
   const [bankState, updateBankState] = useBankState();
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const creds = credentials.status !== "loggedIn" ? undefined : credentials;
   const { api } = useBankCoreApiContext();
 
diff --git a/packages/demobank-ui/src/pages/PaymentOptions.tsx 
b/packages/demobank-ui/src/pages/PaymentOptions.tsx
index ac7118697..48ecc7525 100644
--- a/packages/demobank-ui/src/pages/PaymentOptions.tsx
+++ b/packages/demobank-ui/src/pages/PaymentOptions.tsx
@@ -21,9 +21,9 @@ import { PaytoWireTransferForm } from 
"./PaytoWireTransferForm.js";
 import { WalletWithdrawForm } from "./WalletWithdrawForm.js";
 import { EmptyObject, RouteDefinition } from "../route.js";
 import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { useWithdrawalDetails } from "../hooks/access.js";
+import { useWithdrawalDetails } from "../hooks/account.js";
 import { useEffect } from "preact/hooks";
-import { useBackendState } from "../hooks/backend.js";
+import { useSessionState } from "../hooks/session.js";
 
 function ShowOperationPendingTag({
   woid,
@@ -33,7 +33,7 @@ function ShowOperationPendingTag({
   onOperationAlreadyCompleted?: () => void;
 }): VNode {
   const { i18n } = useTranslationContext();
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const result = useWithdrawalDetails(woid);
   const loading = !result
   const error =
diff --git a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx 
b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
index aeb5dc0c9..f746094ce 100644
--- a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
+++ b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
@@ -43,7 +43,7 @@ import { ComponentChildren, Fragment, Ref, VNode, h } from 
"preact";
 import { useState } from "preact/hooks";
 import { mutate } from "swr";
 import { useBankCoreApiContext } from "../context/config.js";
-import { useBackendState } from "../hooks/backend.js";
+import { useSessionState } from "../hooks/session.js";
 import { useBankState } from "../hooks/bank-state.js";
 import { EmptyObject, RouteDefinition } from "../route.js";
 import { undefinedIfEmpty, validateIBAN, validateTalerBank } from 
"../utils.js";
@@ -80,7 +80,7 @@ export function PaytoWireTransferForm({
   limit,
 }: Props): VNode {
   const [isRawPayto, setIsRawPayto] = useState(false);
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const { api, config, url } = useBankCoreApiContext();
 
   const sendingToFixedAccount = withAccount !== undefined;
diff --git a/packages/demobank-ui/src/pages/ProfileNavigation.tsx 
b/packages/demobank-ui/src/pages/ProfileNavigation.tsx
index 8b7a8205f..10497f015 100644
--- a/packages/demobank-ui/src/pages/ProfileNavigation.tsx
+++ b/packages/demobank-ui/src/pages/ProfileNavigation.tsx
@@ -18,7 +18,7 @@ import { useTranslationContext } from 
"@gnu-taler/web-util/browser";
 import { Fragment, VNode, h } from "preact";
 import { useBankCoreApiContext } from "../context/config.js";
 import { useNavigationContext } from "../context/navigation.js";
-import { useBackendState } from "../hooks/backend.js";
+import { useSessionState } from "../hooks/session.js";
 import { RouteDefinition } from "../route.js";
 
 export function ProfileNavigation({
@@ -38,7 +38,7 @@ export function ProfileNavigation({
 }): VNode {
   const { i18n } = useTranslationContext();
   const { config } = useBankCoreApiContext();
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const isAdminUser =
     credentials.status !== "loggedIn"
       ? false
diff --git a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx 
b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
index f330cbc74..84d703cbe 100644
--- a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
+++ b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
@@ -19,7 +19,7 @@ import { Loading, useTranslationContext } from 
"@gnu-taler/web-util/browser";
 import { Fragment, VNode, h } from "preact";
 import { useState } from "preact/hooks";
 import { Transactions } from "../components/Transactions/index.js";
-import { usePublicAccounts } from "../hooks/access.js";
+import { usePublicAccounts } from "../hooks/account.js";
 
 /**
  * Show histories of public accounts.
diff --git a/packages/demobank-ui/src/pages/QrCodeSection.tsx 
b/packages/demobank-ui/src/pages/QrCodeSection.tsx
index 7091214e0..d4f5a5455 100644
--- a/packages/demobank-ui/src/pages/QrCodeSection.tsx
+++ b/packages/demobank-ui/src/pages/QrCodeSection.tsx
@@ -30,7 +30,7 @@ import { useEffect } from "preact/hooks";
 import { QR } from "../components/QR.js";
 import { useBankCoreApiContext } from "../context/config.js";
 import { useTalerWalletIntegrationAPI } from 
"../context/wallet-integration.js";
-import { useBackendState } from "../hooks/backend.js";
+import { useSessionState } from "../hooks/session.js";
 
 export function QrCodeSection({
   withdrawUri,
@@ -42,7 +42,7 @@ export function QrCodeSection({
   const { i18n } = useTranslationContext();
   const walletInegrationApi = useTalerWalletIntegrationAPI();
   const talerWithdrawUri = stringifyWithdrawUri(withdrawUri);
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const creds = credentials.status !== "loggedIn" ? undefined : credentials;
 
   useEffect(() => {
diff --git a/packages/demobank-ui/src/pages/SolveChallengePage.tsx 
b/packages/demobank-ui/src/pages/SolveChallengePage.tsx
index 1bafbc3eb..7e117f535 100644
--- a/packages/demobank-ui/src/pages/SolveChallengePage.tsx
+++ b/packages/demobank-ui/src/pages/SolveChallengePage.tsx
@@ -39,10 +39,10 @@ import { Fragment, VNode, h } from "preact";
 import { useEffect, useState } from "preact/hooks";
 import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js";
 import { useBankCoreApiContext } from "../context/config.js";
-import { useWithdrawalDetails } from "../hooks/access.js";
-import { useBackendState } from "../hooks/backend.js";
+import { useWithdrawalDetails } from "../hooks/account.js";
+import { useSessionState } from "../hooks/session.js";
 import { ChallengeInProgess, useBankState } from "../hooks/bank-state.js";
-import { useConversionInfo } from "../hooks/circuit.js";
+import { useConversionInfo } from "../hooks/regional.js";
 import { RouteDefinition } from "../route.js";
 import { undefinedIfEmpty } from "../utils.js";
 import { RenderAmount } from "./PaytoWireTransferForm.js";
@@ -62,7 +62,7 @@ export function SolveChallengePage({
   const [bankState, updateBankState] = useBankState();
   const [code, setCode] = useState<string | undefined>(undefined);
   const [notification, notify, handleError] = useLocalNotification();
-  const { state } = useBackendState();
+  const { state } = useSessionState();
   const creds = state.status !== "loggedIn" ? undefined : state;
   const { navigateTo } = useNavigationContext();
 
diff --git a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx 
b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
index 078f4e5f5..caf205f31 100644
--- a/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
+++ b/packages/demobank-ui/src/pages/WalletWithdrawForm.tsx
@@ -33,7 +33,7 @@ import { VNode, h } from "preact";
 import { forwardRef } from "preact/compat";
 import { useState } from "preact/hooks";
 import { useBankCoreApiContext } from "../context/config.js";
-import { useBackendState } from "../hooks/backend.js";
+import { useSessionState } from "../hooks/session.js";
 import { useBankState } from "../hooks/bank-state.js";
 import { usePreferences } from "../hooks/preferences.js";
 import { RouteDefinition } from "../route.js";
@@ -65,7 +65,7 @@ function OldWithdrawalForm({
   const [bankState, updateBankState] = useBankState();
   const { api } = useBankCoreApiContext();
 
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const creds = credentials.status !== "loggedIn" ? undefined : credentials;
 
   const [amountStr, setAmountStr] = useState<string | undefined>(
diff --git a/packages/demobank-ui/src/pages/WireTransfer.tsx 
b/packages/demobank-ui/src/pages/WireTransfer.tsx
index 927968304..33f067e63 100644
--- a/packages/demobank-ui/src/pages/WireTransfer.tsx
+++ b/packages/demobank-ui/src/pages/WireTransfer.tsx
@@ -26,8 +26,8 @@ import {
 } from "@gnu-taler/web-util/browser";
 import { Fragment, VNode, h } from "preact";
 import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js";
-import { useAccountDetails } from "../hooks/access.js";
-import { useBackendState } from "../hooks/backend.js";
+import { useAccountDetails } from "../hooks/account.js";
+import { useSessionState } from "../hooks/session.js";
 import { LoginForm } from "./LoginForm.js";
 import { PaytoWireTransferForm } from "./PaytoWireTransferForm.js";
 import { RouteDefinition } from "../route.js";
@@ -54,7 +54,7 @@ export function WireTransfer({
   onAuthorizationRequired: () => void;
 }): VNode {
   const { i18n } = useTranslationContext();
-  const r = useBackendState();
+  const r = useSessionState();
   const account = r.state.status !== "loggedOut" ? r.state.username : "admin";
   const result = useAccountDetails(account);
 
diff --git a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx 
b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
index 39b94b349..4efc82017 100644
--- a/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalConfirmationQuestion.tsx
@@ -36,9 +36,9 @@ import {
 import { ComponentChildren, Fragment, VNode, h } from "preact";
 import { mutate } from "swr";
 import { useBankCoreApiContext } from "../context/config.js";
-import { useBackendState } from "../hooks/backend.js";
 import { useBankState } from "../hooks/bank-state.js";
 import { usePreferences } from "../hooks/preferences.js";
+import { useSessionState } from "../hooks/session.js";
 import { RouteDefinition } from "../route.js";
 import { LoginForm } from "./LoginForm.js";
 import { RenderAmount } from "./PaytoWireTransferForm.js";
@@ -68,7 +68,7 @@ export function WithdrawalConfirmationQuestion({
 }: Props): VNode {
   const { i18n } = useTranslationContext();
   const [settings] = usePreferences();
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const creds = credentials.status !== "loggedIn" ? undefined : credentials;
   const [, updateBankState] = useBankState();
 
@@ -330,7 +330,7 @@ export function ShouldBeSameUser({
   username: string;
   children: ComponentChildren;
 }): VNode {
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const { i18n } = useTranslationContext();
   if (credentials.status === "loggedOut") {
     return (
diff --git a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx 
b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
index b128bd99f..9765147d1 100644
--- a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
@@ -30,7 +30,7 @@ import {
 } from "@gnu-taler/web-util/browser";
 import { VNode, h } from "preact";
 import { ErrorLoadingWithDebug } from "../components/ErrorLoadingWithDebug.js";
-import { useWithdrawalDetails } from "../hooks/access.js";
+import { useWithdrawalDetails } from "../hooks/account.js";
 import { RouteDefinition } from "../route.js";
 import { QrCodeSection } from "./QrCodeSection.js";
 import { WithdrawalConfirmationQuestion } from 
"./WithdrawalConfirmationQuestion.js";
diff --git a/packages/demobank-ui/src/pages/account/CashoutListForAccount.tsx 
b/packages/demobank-ui/src/pages/account/CashoutListForAccount.tsx
index fe64778dd..2216b96fc 100644
--- a/packages/demobank-ui/src/pages/account/CashoutListForAccount.tsx
+++ b/packages/demobank-ui/src/pages/account/CashoutListForAccount.tsx
@@ -16,9 +16,9 @@
 import { useTranslationContext } from "@gnu-taler/web-util/browser";
 import { Fragment, VNode, h } from "preact";
 import { Cashouts } from "../../components/Cashouts/index.js";
-import { useBackendState } from "../../hooks/backend.js";
+import { useSessionState } from "../../hooks/session.js";
 import { ProfileNavigation } from "../ProfileNavigation.js";
-import { CreateCashout } from "../business/CreateCashout.js";
+import { CreateCashout } from "../regional/CreateCashout.js";
 import { RouteDefinition } from "../../route.js";
 
 interface Props {
@@ -48,7 +48,7 @@ export function CashoutListForAccount({
 }: Props): VNode {
   const { i18n } = useTranslationContext();
 
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
 
   const accountIsTheCurrentUser =
     credentials.status === "loggedIn"
diff --git a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx 
b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
index 6aad8997a..8ab3998ad 100644
--- a/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
+++ b/packages/demobank-ui/src/pages/account/ShowAccountDetails.tsx
@@ -33,8 +33,8 @@ import { Fragment, VNode, h } from "preact";
 import { useState } from "preact/hooks";
 import { ErrorLoadingWithDebug } from 
"../../components/ErrorLoadingWithDebug.js";
 import { useBankCoreApiContext } from "../../context/config.js";
-import { useAccountDetails } from "../../hooks/access.js";
-import { useBackendState } from "../../hooks/backend.js";
+import { useAccountDetails } from "../../hooks/account.js";
+import { useSessionState } from "../../hooks/session.js";
 import { useBankState } from "../../hooks/bank-state.js";
 import { RouteDefinition } from "../../route.js";
 import { LoginForm } from "../LoginForm.js";
@@ -65,7 +65,7 @@ export function ShowAccountDetails({
   account: string;
 }): VNode {
   const { i18n } = useTranslationContext();
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const creds = credentials.status !== "loggedIn" ? undefined : credentials;
   const { api } = useBankCoreApiContext();
   const accountIsTheCurrentUser =
diff --git a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx 
b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
index 305f041ec..b9a334088 100644
--- a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
+++ b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
@@ -29,7 +29,7 @@ import {
 import { Fragment, VNode, h } from "preact";
 import { useState } from "preact/hooks";
 import { useBankCoreApiContext } from "../../context/config.js";
-import { useBackendState } from "../../hooks/backend.js";
+import { useSessionState } from "../../hooks/session.js";
 import { useBankState } from "../../hooks/bank-state.js";
 import { RouteDefinition } from "../../route.js";
 import { undefinedIfEmpty } from "../../utils.js";
@@ -62,7 +62,7 @@ export function UpdateAccountPassword({
   account: string;
 }): VNode {
   const { i18n } = useTranslationContext();
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const token =
     credentials.status !== "loggedIn" ? undefined : credentials.token;
   const { api } = useBankCoreApiContext();
diff --git a/packages/demobank-ui/src/pages/admin/AccountForm.tsx 
b/packages/demobank-ui/src/pages/admin/AccountForm.tsx
index 5a5ce8c32..bce7afe11 100644
--- a/packages/demobank-ui/src/pages/admin/AccountForm.tsx
+++ b/packages/demobank-ui/src/pages/admin/AccountForm.tsx
@@ -33,7 +33,7 @@ import {
 import { ComponentChildren, VNode, h } from "preact";
 import { useState } from "preact/hooks";
 import { VersionHint, useBankCoreApiContext } from "../../context/config.js";
-import { useBackendState } from "../../hooks/backend.js";
+import { useSessionState } from "../../hooks/session.js";
 import {
   ErrorMessageMappingFor,
   TanChannel,
@@ -92,7 +92,7 @@ export function AccountForm<PurposeType extends keyof 
ChangeByPurposeType>({
 }): VNode {
   const { config, hints, url } = useBankCoreApiContext();
   const { i18n } = useTranslationContext();
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const [form, setForm] = useState<AccountFormData>({});
 
   const [errors, setErrors] = useState<
diff --git a/packages/demobank-ui/src/pages/admin/AccountList.tsx 
b/packages/demobank-ui/src/pages/admin/AccountList.tsx
index e0d368f04..4e465d4b5 100644
--- a/packages/demobank-ui/src/pages/admin/AccountList.tsx
+++ b/packages/demobank-ui/src/pages/admin/AccountList.tsx
@@ -23,7 +23,7 @@ import { Loading, useTranslationContext } from 
"@gnu-taler/web-util/browser";
 import { Fragment, VNode, h } from "preact";
 import { ErrorLoadingWithDebug } from 
"../../components/ErrorLoadingWithDebug.js";
 import { useBankCoreApiContext } from "../../context/config.js";
-import { useBusinessAccounts } from "../../hooks/circuit.js";
+import { useBusinessAccounts } from "../../hooks/regional.js";
 import { RenderAmount } from "../PaytoWireTransferForm.js";
 import { RouteDefinition } from "../../route.js";
 
diff --git a/packages/demobank-ui/src/pages/admin/AdminHome.tsx 
b/packages/demobank-ui/src/pages/admin/AdminHome.tsx
index 2cdc39261..752d86aa6 100644
--- a/packages/demobank-ui/src/pages/admin/AdminHome.tsx
+++ b/packages/demobank-ui/src/pages/admin/AdminHome.tsx
@@ -40,7 +40,7 @@ import { useState } from "preact/hooks";
 import { ErrorLoadingWithDebug } from 
"../../components/ErrorLoadingWithDebug.js";
 import { Transactions } from "../../components/Transactions/index.js";
 import { useBankCoreApiContext } from "../../context/config.js";
-import { useConversionInfo, useLastMonitorInfo } from "../../hooks/circuit.js";
+import { useConversionInfo, useLastMonitorInfo } from 
"../../hooks/regional.js";
 import { RouteDefinition } from "../../route.js";
 import { RenderAmount } from "../PaytoWireTransferForm.js";
 import { WireTransfer } from "../WireTransfer.js";
diff --git a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx 
b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
index e09164ffb..3ae2b636c 100644
--- a/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
+++ b/packages/demobank-ui/src/pages/admin/CreateNewAccount.tsx
@@ -30,7 +30,7 @@ import {
 import { Fragment, VNode, h } from "preact";
 import { useState } from "preact/hooks";
 import { useBankCoreApiContext } from "../../context/config.js";
-import { useBackendState } from "../../hooks/backend.js";
+import { useSessionState } from "../../hooks/session.js";
 import { RouteDefinition } from "../../route.js";
 import { AccountForm } from "./AccountForm.js";
 
@@ -42,7 +42,7 @@ export function CreateNewAccount({
   onCreateSuccess: () => void;
 }): VNode {
   const { i18n } = useTranslationContext();
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const token =
     credentials.status !== "loggedIn" ? undefined : credentials.token;
   const { api } = useBankCoreApiContext();
diff --git a/packages/demobank-ui/src/pages/DownloadStats.tsx 
b/packages/demobank-ui/src/pages/admin/DownloadStats.tsx
similarity index 98%
rename from packages/demobank-ui/src/pages/DownloadStats.tsx
rename to packages/demobank-ui/src/pages/admin/DownloadStats.tsx
index 353238c13..66ef73d19 100644
--- a/packages/demobank-ui/src/pages/DownloadStats.tsx
+++ b/packages/demobank-ui/src/pages/admin/DownloadStats.tsx
@@ -29,10 +29,10 @@ import {
 } from "@gnu-taler/web-util/browser";
 import { VNode, h } from "preact";
 import { useState } from "preact/hooks";
-import { useBankCoreApiContext } from "../context/config.js";
-import { useBackendState } from "../hooks/backend.js";
-import { EmptyObject, RouteDefinition } from "../route.js";
-import { getTimeframesForDate } from "./admin/AdminHome.js";
+import { useBankCoreApiContext } from "../../context/config.js";
+import { useSessionState } from "../../hooks/session.js";
+import { EmptyObject, RouteDefinition } from "../../route.js";
+import { getTimeframesForDate } from "./AdminHome.js";
 
 interface Props {
   routeCancel: RouteDefinition;
@@ -54,7 +54,7 @@ type Options = {
 export function DownloadStats({ routeCancel }: Props): VNode {
   const { i18n } = useTranslationContext();
 
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const creds =
     credentials.status !== "loggedIn" || !credentials.isUserAdministrator
       ? undefined
diff --git a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx 
b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
index 6f02eae8f..6039db326 100644
--- a/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
+++ b/packages/demobank-ui/src/pages/admin/RemoveAccount.tsx
@@ -35,8 +35,8 @@ import { Fragment, VNode, h } from "preact";
 import { useState } from "preact/hooks";
 import { ErrorLoadingWithDebug } from 
"../../components/ErrorLoadingWithDebug.js";
 import { useBankCoreApiContext } from "../../context/config.js";
-import { useAccountDetails } from "../../hooks/access.js";
-import { useBackendState } from "../../hooks/backend.js";
+import { useAccountDetails } from "../../hooks/account.js";
+import { useSessionState } from "../../hooks/session.js";
 import { undefinedIfEmpty } from "../../utils.js";
 import { LoginForm } from "../LoginForm.js";
 import { doAutoFocus } from "../PaytoWireTransferForm.js";
@@ -62,7 +62,7 @@ export function RemoveAccount({
   const result = useAccountDetails(account);
   const [accountName, setAccountName] = useState<string | undefined>();
 
-  const { state } = useBackendState();
+  const { state } = useSessionState();
   const token = state.status !== "loggedIn" ? undefined : state.token;
   const { api } = useBankCoreApiContext();
   const [notification, notify, handleError] = useLocalNotification();
diff --git a/packages/demobank-ui/src/pages/ConversionConfig.tsx 
b/packages/demobank-ui/src/pages/regional/ConversionConfig.tsx
similarity index 89%
rename from packages/demobank-ui/src/pages/ConversionConfig.tsx
rename to packages/demobank-ui/src/pages/regional/ConversionConfig.tsx
index 2d52cd99f..63423353b 100644
--- a/packages/demobank-ui/src/pages/ConversionConfig.tsx
+++ b/packages/demobank-ui/src/pages/regional/ConversionConfig.tsx
@@ -34,13 +34,14 @@ import {
 } from "@gnu-taler/web-util/browser";
 import { Fragment, VNode, h } from "preact";
 import { useEffect, useState } from "preact/hooks";
-import { useBankCoreApiContext } from "../context/config.js";
-import { useBackendState } from "../hooks/backend.js";
-import { TransferCalculation, useCashinEstimator, useCashoutEstimator, 
useConversionInfo } from "../hooks/circuit.js";
-import { RouteDefinition } from "../route.js";
-import { undefinedIfEmpty } from "../utils.js";
-import { InputAmount, RenderAmount } from "./PaytoWireTransferForm.js";
-import { ProfileNavigation } from "./ProfileNavigation.js";
+import { useBankCoreApiContext } from "../../context/config.js";
+import { useSessionState } from "../../hooks/session.js";
+import { TransferCalculation, useCashinEstimator, useCashoutEstimator, 
useConversionInfo } from "../../hooks/regional.js";
+import { RouteDefinition } from "../../route.js";
+import { undefinedIfEmpty } from "../../utils.js";
+import { InputAmount, RenderAmount } from "../PaytoWireTransferForm.js";
+import { ProfileNavigation } from "../ProfileNavigation.js";
+import { FormErrors, FormStatus, FormValues, RecursivePartial, UIField, 
useFormState } from "../../hooks/form.js";
 
 interface Props {
   routeMyAccountDetails: RouteDefinition;
@@ -52,87 +53,8 @@ interface Props {
   onUpdateSuccess: () => void;
 }
 
-type UIField = {
-  value: string | undefined;
-  onUpdate: (s: string) => void;
-  error: TranslatedString | undefined;
-}
-
-type FormHandler<T> = {
-  [k in keyof T]?:
-  T[k] extends string ? UIField :
-  T[k] extends AmountJson ? UIField :
-  FormHandler<T[k]>;
-}
-
-type FormValues<T> = {
-  [k in keyof T]:
-  T[k] extends string ? (string | undefined) :
-  T[k] extends AmountJson ? (string | undefined) :
-  FormValues<T[k]>;
-}
-
-type RecursivePartial<T> = {
-  [k in keyof T]?:
-  T[k] extends string ? (string) :
-  T[k] extends AmountJson ? (AmountJson) :
-  RecursivePartial<T[k]>;
-}
-
-type FormErrors<T> = {
-  [k in keyof T]?:
-  T[k] extends string ? (TranslatedString) :
-  T[k] extends AmountJson ? (TranslatedString) :
-  FormErrors<T[k]>;
-}
-
-type FormStatus<T> = {
-  status: "ok",
-  result: T,
-  errors: undefined,
-} | {
-  status: "fail",
-  result: RecursivePartial<T>,
-  errors: FormErrors<T>,
-}
 type FormType = { amount: AmountJson, conv: 
TalerBankConversionApi.ConversionRate }
 
-function constructFormHandler<T>(form: FormValues<T>, updateForm: (d: 
FormValues<T>) => void, errors: FormErrors<T> | undefined): FormHandler<T> {
-  const keys = (Object.keys(form) as Array<keyof T>)
-
-  const handler = keys.reduce((prev, fieldName) => {
-    const currentValue: any = form[fieldName];
-    const currentError: any = errors ? errors[fieldName] : undefined;
-    function updater(newValue: any) {
-      updateForm({ ...form, [fieldName]: newValue })
-    }
-    if (typeof currentValue === "object") {
-      const group = constructFormHandler(currentValue, updater, currentError)
-      // @ts-expect-error asdasd
-      prev[fieldName] = group
-      return prev;
-    }
-    const field: UIField = {
-      error: currentError,
-      value: currentValue,
-      onUpdate: updater
-    }
-    // @ts-expect-error asdasd
-    prev[fieldName] = field
-    return prev
-  }, {} as FormHandler<T>)
-
-  return handler;
-}
-
-function useFormState<T>(defaultValue: FormValues<T>, check: (f: 
FormValues<T>) => FormStatus<T>): [FormHandler<T>, FormStatus<T>] {
-  const [form, updateForm] = useState<FormValues<T>>(defaultValue)
-
-  const status = check(form)
-  const handler = constructFormHandler(form, updateForm, status.errors)
-
-  return [handler, status]
-}
 
 function useComponentState({
   onUpdateSuccess,
@@ -143,23 +65,24 @@ function useComponentState({
   routeMyAccountDetails,
   routeMyAccountPassword,
 }: Props): utils.RecursiveState<VNode> {
+  const { i18n } = useTranslationContext();
 
   const result = useConversionInfo()
   const info = result && !(result instanceof TalerError) && result.type === 
"ok" ?
     result.body : undefined;
 
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const creds =
     credentials.status !== "loggedIn" || !credentials.isUserAdministrator
       ? undefined
       : credentials;
 
   if (!info) {
-    return <div>waiting...</div>
+    return <i18n.Translate>loading...</i18n.Translate>
   }
 
   if (!creds) {
-    return <div>only admin can setup conversion</div>;
+    return <i18n.Translate>only admin can setup conversion</i18n.Translate>
   }
 
   return () => {
@@ -187,7 +110,7 @@ function useComponentState({
 
     const [form, status] = useFormState<FormType>(
       initalState,
-      checkConversionForm(i18n, info.regional_currency, info.fiat_currency)
+      createFormValidator(i18n, info.regional_currency, info.fiat_currency)
     )
 
     const {
@@ -378,8 +301,6 @@ function useComponentState({
                 tiny={form?.conv?.cashin_tiny_amount}
               />}
 
-
-
             {section == "cashout" && <Fragment>
               <ConversionForm id="cashout"
                 inputCurrency={info.regional_currency}
@@ -392,9 +313,6 @@ function useComponentState({
               />
             </Fragment>}
 
-
-
-
             {section == "detail" && <Fragment>
               <div class="px-6 pt-6">
                 <div class="justify-between items-center flex ">
@@ -587,12 +505,16 @@ function useComponentState({
   }
 }
 
-/**
- * Show histories of public accounts.
- */
 export const ConversionConfig = utils.recursive(useComponentState);
 
-function checkConversionForm(i18n: InternationalizationAPI, regional: string, 
fiat: string) {
+/**
+ * 
+ * @param i18n 
+ * @param regional 
+ * @param fiat 
+ * @returns form validator
+ */
+function createFormValidator(i18n: InternationalizationAPI, regional: string, 
fiat: string) {
   return function check(state: FormValues<FormType>): FormStatus<FormType> {
 
     const cashin_min_amount = 
Amounts.parse(`${fiat}:${state.conv.cashin_min_amount}`)
@@ -905,82 +827,122 @@ function ConversionForm({ id, inputCurrency, 
outputCurrency, fee, minimum, ratio
         <section class="grid grid-cols-1 gap-y-3  text-gray-600">
           <details class="group  text-sm">
             <summary class="flex cursor-pointer flex-row items-center 
justify-between  ">
-              Rounding an amount of 1.24 with rounding value 0.1
+              <i18n.Translate>
+                Rounding an amount of 1.24 with rounding value 0.1
+              </i18n.Translate>
               <svg class="h-6 w-6 rotate-0 transform  group-open:rotate-180" 
xmlns="http://www.w3.org/2000/svg"; fill="none" viewBox="0 0 24 24" 
stroke-width="2" stroke="currentColor" aria-hidden="true">
                 <path stroke-linecap="round" stroke-linejoin="round" d="M19 
9l-7 7-7-7"></path>
               </svg>
             </summary>
             <p class="text-gray-900 my-4">
-              Given the rounding value of 0.1 the possible values closest to 
1.24 are: 1.1, 1.2, 1.3, 1.4.
+              <i18n.Translate>
+                Given the rounding value of 0.1 the possible values closest to 
1.24 are: 1.1, 1.2, 1.3, 1.4.
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 my-4">
-              With the "zero" mode the value will be rounded to 1.2
+              <i18n.Translate>
+                With the "zero" mode the value will be rounded to 1.2
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 my-4">
-              With the "nearest" mode the value will be rounded to 1.2
+              <i18n.Translate>
+                With the "nearest" mode the value will be rounded to 1.2
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 mt-4">
-              With the "up" mode the value will be rounded to 1.3
+              <i18n.Translate>
+                With the "up" mode the value will be rounded to 1.3
+              </i18n.Translate>
             </p>
           </details>
           <details class="group ">
             <summary class="flex cursor-pointer flex-row items-center 
justify-between  ">
-              Rounding an amount of 1.26 with rounding value 0.1
+              <i18n.Translate>
+                Rounding an amount of 1.26 with rounding value 0.1
+              </i18n.Translate>
               <svg class="h-6 w-6 rotate-0 transform  group-open:rotate-180" 
xmlns="http://www.w3.org/2000/svg"; fill="none" viewBox="0 0 24 24" 
stroke-width="2" stroke="currentColor" aria-hidden="true">
                 <path stroke-linecap="round" stroke-linejoin="round" d="M19 
9l-7 7-7-7"></path>
               </svg>
             </summary>
             <p class="text-gray-900 my-4">
-              Given the rounding value of 0.1 the possible values closest to 
1.24 are: 1.1, 1.2, 1.3, 1.4.
+              <i18n.Translate>
+                Given the rounding value of 0.1 the possible values closest to 
1.24 are: 1.1, 1.2, 1.3, 1.4.
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 my-4">
-              With the "zero" mode the value will be rounded to 1.2
+              <i18n.Translate>
+                With the "zero" mode the value will be rounded to 1.2
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 my-4">
-              With the "nearest" mode the value will be rounded to 1.3
+              <i18n.Translate>
+                With the "nearest" mode the value will be rounded to 1.3
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 my-4">
-              With the "up" mode the value will be rounded to 1.3
+              <i18n.Translate>
+                With the "up" mode the value will be rounded to 1.3
+              </i18n.Translate>
             </p>
           </details>
           <details class="group ">
             <summary class="flex cursor-pointer flex-row items-center 
justify-between  ">
-              Rounding an amount of 1.24 with rounding value 0.3
+              <i18n.Translate>
+                Rounding an amount of 1.24 with rounding value 0.3
+              </i18n.Translate>
               <svg class="h-6 w-6 rotate-0 transform  group-open:rotate-180" 
xmlns="http://www.w3.org/2000/svg"; fill="none" viewBox="0 0 24 24" 
stroke-width="2" stroke="currentColor" aria-hidden="true">
                 <path stroke-linecap="round" stroke-linejoin="round" d="M19 
9l-7 7-7-7"></path>
               </svg>
             </summary>
             <p class="text-gray-900 my-4">
-              Given the rounding value of 0.3 the possible values closest to 
1.24 are: 0.9, 1.2, 1.5, 1.8.
+              <i18n.Translate>
+                Given the rounding value of 0.3 the possible values closest to 
1.24 are: 0.9, 1.2, 1.5, 1.8.
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 my-4">
-              With the "zero" mode the value will be rounded to 1.2
+              <i18n.Translate>
+                With the "zero" mode the value will be rounded to 1.2
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 my-4">
-              With the "nearest" mode the value will be rounded to 1.2
+              <i18n.Translate>
+                With the "nearest" mode the value will be rounded to 1.2
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 my-4">
-              With the "up" mode the value will be rounded to 1.5
+              <i18n.Translate>
+                With the "up" mode the value will be rounded to 1.5
+              </i18n.Translate>
             </p>
           </details>
           <details class="group ">
             <summary class="flex cursor-pointer flex-row items-center 
justify-between  ">
-              Rounding an amount of 1.26 with rounding value 0.3
+              <i18n.Translate>
+                Rounding an amount of 1.26 with rounding value 0.3
+              </i18n.Translate>
               <svg class="h-6 w-6 rotate-0 transform  group-open:rotate-180" 
xmlns="http://www.w3.org/2000/svg"; fill="none" viewBox="0 0 24 24" 
stroke-width="2" stroke="currentColor" aria-hidden="true">
                 <path stroke-linecap="round" stroke-linejoin="round" d="M19 
9l-7 7-7-7"></path>
               </svg>
             </summary>
             <p class="text-gray-900 my-4">
-              Given the rounding value of 0.3 the possible values closest to 
1.24 are: 0.9, 1.2, 1.5, 1.8.
+              <i18n.Translate>
+                Given the rounding value of 0.3 the possible values closest to 
1.24 are: 0.9, 1.2, 1.5, 1.8.
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 my-4">
-              With the "zero" mode the value will be rounded to 1.2
+              <i18n.Translate>
+                With the "zero" mode the value will be rounded to 1.2
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 my-4">
-              With the "nearest" mode the value will be rounded to 1.3
+              <i18n.Translate>
+                With the "nearest" mode the value will be rounded to 1.3
+              </i18n.Translate>
             </p>
             <p class="text-gray-900 my-4">
-              With the "up" mode the value will be rounded to 1.3
+              <i18n.Translate>
+                With the "up" mode the value will be rounded to 1.3
+              </i18n.Translate>
             </p>
           </details>
         </section>
diff --git a/packages/demobank-ui/src/pages/business/CreateCashout.tsx 
b/packages/demobank-ui/src/pages/regional/CreateCashout.tsx
similarity index 99%
rename from packages/demobank-ui/src/pages/business/CreateCashout.tsx
rename to packages/demobank-ui/src/pages/regional/CreateCashout.tsx
index 1a5fad1b1..a5b8f774a 100644
--- a/packages/demobank-ui/src/pages/business/CreateCashout.tsx
+++ b/packages/demobank-ui/src/pages/regional/CreateCashout.tsx
@@ -38,10 +38,10 @@ import { Fragment, VNode, h } from "preact";
 import { useEffect, useState } from "preact/hooks";
 import { ErrorLoadingWithDebug } from 
"../../components/ErrorLoadingWithDebug.js";
 import { VersionHint, useBankCoreApiContext } from "../../context/config.js";
-import { useAccountDetails } from "../../hooks/access.js";
-import { useBackendState } from "../../hooks/backend.js";
+import { useAccountDetails } from "../../hooks/account.js";
+import { useSessionState } from "../../hooks/session.js";
 import { useBankState } from "../../hooks/bank-state.js";
-import { TransferCalculation, useCashoutEstimator, useConversionInfo, 
useEstimator } from "../../hooks/circuit.js";
+import { TransferCalculation, useCashoutEstimator, useConversionInfo, 
useEstimator } from "../../hooks/regional.js";
 import { RouteDefinition } from "../../route.js";
 import { TanChannel, undefinedIfEmpty } from "../../utils.js";
 import { LoginForm } from "../LoginForm.js";
@@ -82,7 +82,7 @@ export function CreateCashout({
     estimateByCredit: calculateFromCredit,
     estimateByDebit: calculateFromDebit,
   } = useCashoutEstimator();
-  const { state: credentials } = useBackendState();
+  const { state: credentials } = useSessionState();
   const creds = credentials.status !== "loggedIn" ? undefined : credentials;
   const [, updateBankState] = useBankState();
 
diff --git a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx 
b/packages/demobank-ui/src/pages/regional/ShowCashoutDetails.tsx
similarity index 99%
rename from packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
rename to packages/demobank-ui/src/pages/regional/ShowCashoutDetails.tsx
index 33115c16a..415f88868 100644
--- a/packages/demobank-ui/src/pages/business/ShowCashoutDetails.tsx
+++ b/packages/demobank-ui/src/pages/regional/ShowCashoutDetails.tsx
@@ -29,7 +29,7 @@ import {
 import { format } from "date-fns";
 import { VNode, h } from "preact";
 import { ErrorLoadingWithDebug } from 
"../../components/ErrorLoadingWithDebug.js";
-import { useCashoutDetails, useConversionInfo } from "../../hooks/circuit.js";
+import { useCashoutDetails, useConversionInfo } from "../../hooks/regional.js";
 import { RouteDefinition } from "../../route.js";
 import { RenderAmount } from "../PaytoWireTransferForm.js";
 import { Time } from "../../components/Time.js";
diff --git a/packages/demobank-ui/src/stories.test.ts 
b/packages/demobank-ui/src/stories.test.ts
index 747bf4083..8171c6d8f 100644
--- a/packages/demobank-ui/src/stories.test.ts
+++ b/packages/demobank-ui/src/stories.test.ts
@@ -30,7 +30,6 @@ import * as components from "./components/index.examples.js";
 import * as pages from "./pages/index.stories.js";
 
 import { ComponentChildren, VNode, h as create } from "preact";
-import { BackendStateProviderTesting } from "./context/backend.js";
 import { BankCoreApiProviderTesting } from "./context/config.js";
 
 setupI18n("en", { en: {} });
@@ -57,15 +56,6 @@ function DefaultTestingContext({
 }: {
   children: ComponentChildren;
 }): VNode {
-  const ctx1 = create(BackendStateProviderTesting, {
-    children,
-    state: {
-      status: "loggedIn",
-      username: "test",
-      token: "pwd" as AccessToken,
-      isUserAdministrator: false,
-    },
-  });
   const cfg: TalerCorebankApi.Config = {
     name: "libeufin-bank",
     allow_deletions: true,
@@ -86,7 +76,7 @@ function DefaultTestingContext({
     version: "1:0:0",
   };
   const ctx2 = create(BankCoreApiProviderTesting, {
-    children: ctx1,
+    children: [],
     state: cfg,
     url: "http://localhost";,
   });

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