gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated (7a591c39d -> ba8b40c91)


From: gnunet
Subject: [taler-wallet-core] branch master updated (7a591c39d -> ba8b40c91)
Date: Fri, 10 Feb 2023 13:55:02 +0100

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

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

    from 7a591c39d -clarification
     new 53af8b486 fix: request error is whats being thrown
     new ba8b40c91 business account

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


Summary of changes:
 .../demobank-ui/src/components/Cashouts/index.ts   |   2 +-
 .../demobank-ui/src/components/Cashouts/state.ts   |  17 +-
 .../src/components/Cashouts/stories.tsx            |  18 +-
 .../demobank-ui/src/components/Cashouts/views.tsx  |   5 +-
 .../src/components/Transactions/state.ts           | 108 +++++------
 packages/demobank-ui/src/context/pageState.ts      |   3 +-
 packages/demobank-ui/src/declaration.d.ts          |  22 +--
 packages/demobank-ui/src/hooks/access.ts           | 210 +++++++++++++--------
 packages/demobank-ui/src/hooks/backend.ts          | 125 ++++++++----
 packages/demobank-ui/src/hooks/circuit.ts          | 151 +++++++++------
 packages/demobank-ui/src/pages/AccountPage.tsx     |  81 ++++----
 packages/demobank-ui/src/pages/AdminPage.tsx       | 117 +++++++-----
 packages/demobank-ui/src/pages/BankFrame.tsx       |  81 +++++---
 packages/demobank-ui/src/pages/BusinessAccount.tsx |  90 +++++++++
 packages/demobank-ui/src/pages/HomePage.tsx        |   4 +-
 packages/demobank-ui/src/pages/Routing.tsx         |  23 ++-
 packages/demobank-ui/src/scss/bank.scss            |   5 +-
 packages/demobank-ui/src/utils.ts                  |   6 +-
 .../merchant-backoffice-ui/src/hooks/backend.ts    |   3 +-
 .../merchant-backoffice-ui/src/hooks/instance.ts   |  24 +--
 packages/merchant-backoffice-ui/src/hooks/order.ts |  22 +--
 .../merchant-backoffice-ui/src/hooks/product.ts    |  18 +-
 .../merchant-backoffice-ui/src/hooks/reserves.ts   |  18 +-
 .../merchant-backoffice-ui/src/hooks/templates.ts  |  20 +-
 .../merchant-backoffice-ui/src/hooks/transfer.ts   |  18 +-
 .../merchant-backoffice-ui/src/hooks/webhooks.ts   |  20 +-
 26 files changed, 740 insertions(+), 471 deletions(-)
 create mode 100644 packages/demobank-ui/src/pages/BusinessAccount.tsx

diff --git a/packages/demobank-ui/src/components/Cashouts/index.ts 
b/packages/demobank-ui/src/components/Cashouts/index.ts
index db39ba7e4..1410267be 100644
--- a/packages/demobank-ui/src/components/Cashouts/index.ts
+++ b/packages/demobank-ui/src/components/Cashouts/index.ts
@@ -23,7 +23,7 @@ import { useComponentState } from "./state.js";
 import { LoadingUriView, ReadyView } from "./views.js";
 
 export interface Props {
-  account: string;
+  empty?: boolean;
 }
 
 export type State = State.Loading | State.LoadingUriError | State.Ready;
diff --git a/packages/demobank-ui/src/components/Cashouts/state.ts 
b/packages/demobank-ui/src/components/Cashouts/state.ts
index 7e420940f..178a1e815 100644
--- a/packages/demobank-ui/src/components/Cashouts/state.ts
+++ b/packages/demobank-ui/src/components/Cashouts/state.ts
@@ -18,27 +18,24 @@ import { AbsoluteTime, Amounts } from 
"@gnu-taler/taler-util";
 import { useCashouts } from "../../hooks/circuit.js";
 import { Props, State, Transaction } from "./index.js";
 
-export function useComponentState({
-  account,
-}: Props): State {
-  const result = useCashouts()
+export function useComponentState({ empty }: Props): State {
+  const result = useCashouts();
   if (result.loading) {
     return {
       status: "loading",
-      error: undefined
-    }
+      error: undefined,
+    };
   }
   if (!result.ok) {
     return {
       status: "loading-error",
-      error: result
-    }
+      error: result,
+    };
   }
 
-
   return {
     status: "ready",
     error: undefined,
-    cashout: result.data,
+    cashouts: result.data,
   };
 }
diff --git a/packages/demobank-ui/src/components/Cashouts/stories.tsx 
b/packages/demobank-ui/src/components/Cashouts/stories.tsx
index 77fdde092..05439780c 100644
--- a/packages/demobank-ui/src/components/Cashouts/stories.tsx
+++ b/packages/demobank-ui/src/components/Cashouts/stories.tsx
@@ -26,20 +26,4 @@ export default {
   title: "transaction list",
 };
 
-export const Ready = tests.createExample(ReadyView, {
-  transactions: [
-    {
-      amount: {
-        currency: "USD",
-        fraction: 0,
-        value: 1,
-      },
-      counterpart: "ASD",
-      negative: false,
-      subject: "Some",
-      when: {
-        t_ms: new Date().getTime(),
-      },
-    },
-  ],
-});
+export const Ready = tests.createExample(ReadyView, {});
diff --git a/packages/demobank-ui/src/components/Cashouts/views.tsx 
b/packages/demobank-ui/src/components/Cashouts/views.tsx
index 30803d4d1..16ae8a58f 100644
--- a/packages/demobank-ui/src/components/Cashouts/views.tsx
+++ b/packages/demobank-ui/src/components/Cashouts/views.tsx
@@ -39,7 +39,7 @@ export function ReadyView({ cashouts }: State.Ready): VNode {
           <tr>
             <th>{i18n.str`Created`}</th>
             <th>{i18n.str`Confirmed`}</th>
-            <th>{i18n.str`Counterpart`}</th>
+            <th>{i18n.str`Status`}</th>
             <th>{i18n.str`Subject`}</th>
           </tr>
         </thead>
@@ -53,8 +53,9 @@ export function ReadyView({ cashouts }: State.Ready): VNode {
                     ? format(item.confirmation_time, "dd/MM/yyyy HH:mm:ss")
                     : "-"}
                 </td>
+                <td>{Amounts.stringifyValue(item.amount_debit)}</td>
                 <td>{Amounts.stringifyValue(item.amount_credit)}</td>
-                <td>{item.counterpart}</td>
+                <td>{item.status}</td>
                 <td>{item.subject}</td>
               </tr>
             );
diff --git a/packages/demobank-ui/src/components/Transactions/state.ts 
b/packages/demobank-ui/src/components/Transactions/state.ts
index 9e1bce39b..198ef6c5f 100644
--- a/packages/demobank-ui/src/components/Transactions/state.ts
+++ b/packages/demobank-ui/src/components/Transactions/state.ts
@@ -18,21 +18,19 @@ import { AbsoluteTime, Amounts } from 
"@gnu-taler/taler-util";
 import { useTransactions } from "../../hooks/access.js";
 import { Props, State, Transaction } from "./index.js";
 
-export function useComponentState({
-  account,
-}: Props): State {
-  const result = useTransactions(account)
+export function useComponentState({ account }: Props): State {
+  const result = useTransactions(account);
   if (result.loading) {
     return {
       status: "loading",
-      error: undefined
-    }
+      error: undefined,
+    };
   }
   if (!result.ok) {
     return {
       status: "loading-error",
-      error: result
-    }
+      error: result,
+    };
   }
   // if (error) {
   //   switch (error.status) {
@@ -73,53 +71,57 @@ export function useComponentState({
   //   };
   // }
 
-  const transactions = result.data.transactions.map((item: unknown) => {
-    if (
-      !item ||
-      typeof item !== "object" ||
-      !("direction" in item) ||
-      !("creditorIban" in item) ||
-      !("debtorIban" in item) ||
-      !("date" in item) ||
-      !("subject" in item) ||
-      !("currency" in item) ||
-      !("amount" in item)
-    ) {
-      //not valid
-      return;
-    }
-    const anyItem = item as any;
-    if (
-      !(typeof anyItem.creditorIban === "string") ||
-      !(typeof anyItem.debtorIban === "string") ||
-      !(typeof anyItem.date === "string") ||
-      !(typeof anyItem.subject === "string") ||
-      !(typeof anyItem.currency === "string") ||
-      !(typeof anyItem.amount === "string")
-    ) {
-      return;
-    }
+  const transactions = result.data.transactions
+    .map((item: unknown) => {
+      if (
+        !item ||
+        typeof item !== "object" ||
+        !("direction" in item) ||
+        !("creditorIban" in item) ||
+        !("debtorIban" in item) ||
+        !("date" in item) ||
+        !("subject" in item) ||
+        !("currency" in item) ||
+        !("amount" in item)
+      ) {
+        //not valid
+        return;
+      }
+      const anyItem = item as any;
+      if (
+        !(typeof anyItem.creditorIban === "string") ||
+        !(typeof anyItem.debtorIban === "string") ||
+        !(typeof anyItem.date === "string") ||
+        !(typeof anyItem.subject === "string") ||
+        !(typeof anyItem.currency === "string") ||
+        !(typeof anyItem.amount === "string")
+      ) {
+        return;
+      }
 
-    const negative = anyItem.direction === "DBIT";
-    const counterpart = negative ? anyItem.creditorIban : anyItem.debtorIban;
+      const negative = anyItem.direction === "DBIT";
+      const counterpart = negative ? anyItem.creditorIban : anyItem.debtorIban;
 
-    let date = anyItem.date ? parseInt(anyItem.date, 10) : 0
-    if (isNaN(date) || !isFinite(date)) {
-      date = 0
-    }
-    const when: AbsoluteTime = !date ? AbsoluteTime.never() : {
-      t_ms: date,
-    };
-    const amount = Amounts.parse(`${anyItem.currency}:${anyItem.amount}`);
-    const subject = anyItem.subject;
-    return {
-      negative,
-      counterpart,
-      when,
-      amount,
-      subject,
-    };
-  }).filter((x): x is Transaction => x !== undefined);
+      let date = anyItem.date ? parseInt(anyItem.date, 10) : 0;
+      if (isNaN(date) || !isFinite(date)) {
+        date = 0;
+      }
+      const when: AbsoluteTime = !date
+        ? AbsoluteTime.never()
+        : {
+            t_ms: date,
+          };
+      const amount = Amounts.parse(`${anyItem.currency}:${anyItem.amount}`);
+      const subject = anyItem.subject;
+      return {
+        negative,
+        counterpart,
+        when,
+        amount,
+        subject,
+      };
+    })
+    .filter((x): x is Transaction => x !== undefined);
 
   return {
     status: "ready",
diff --git a/packages/demobank-ui/src/context/pageState.ts 
b/packages/demobank-ui/src/context/pageState.ts
index d5428b9b7..247297c7b 100644
--- a/packages/demobank-ui/src/context/pageState.ts
+++ b/packages/demobank-ui/src/context/pageState.ts
@@ -95,7 +95,7 @@ export type ErrorMessage = {
   description?: string;
   title: TranslatedString;
   debug?: string;
-}
+};
 /**
  * Track page state.
  */
@@ -110,5 +110,4 @@ export interface PageStateType {
    * be moved in a future "withdrawal state" object.
    */
   withdrawalId?: string;
-
 }
diff --git a/packages/demobank-ui/src/declaration.d.ts 
b/packages/demobank-ui/src/declaration.d.ts
index cf3eb5774..c46fcc9ed 100644
--- a/packages/demobank-ui/src/declaration.d.ts
+++ b/packages/demobank-ui/src/declaration.d.ts
@@ -70,7 +70,6 @@ interface WireTransferRequestType {
   amount?: string;
 }
 
-
 type HashCode = string;
 type EddsaPublicKey = string;
 type EddsaSignature = string;
@@ -101,7 +100,6 @@ type UUID = string;
 type Integer = number;
 
 namespace SandboxBackend {
-
   export interface Config {
     // Name of this API, always "circuit".
     name: string;
@@ -126,7 +124,6 @@ namespace SandboxBackend {
     error: SandboxErrorDetail;
   }
   interface SandboxErrorDetail {
-
     // String enum classifying the error.
     type: ErrorType;
 
@@ -147,13 +144,12 @@ namespace SandboxBackend {
      * Sandbox and Nexus, therefore the actual meaning
      * must be carried by the error 'message' field.
      */
-    UtilError = "util-error"
+    UtilError = "util-error",
   }
 
   namespace Access {
-
     interface PublicAccountsResponse {
-      publicAccounts: PublicAccount[]
+      publicAccounts: PublicAccount[];
     }
     interface PublicAccount {
       iban: string;
@@ -213,7 +209,6 @@ namespace SandboxBackend {
     }
 
     interface BankAccountTransactionInfo {
-
       creditorIban: string;
       creditorBic: string; // Optional
       creditorName: string;
@@ -233,7 +228,6 @@ namespace SandboxBackend {
       date: string; // milliseconds since the Unix epoch
     }
     interface CreateBankAccountTransactionCreate {
-
       // Address in the Payto format of the wire transfer receiver.
       // It needs at least the 'message' query string parameter.
       paytoUri: string;
@@ -250,7 +244,6 @@ namespace SandboxBackend {
 
       password: string;
     }
-
   }
 
   namespace Circuit {
@@ -281,7 +274,6 @@ namespace SandboxBackend {
       internal_iban?: string;
     }
     interface CircuitContactData {
-
       // E-Mail address
       email?: string;
 
@@ -289,7 +281,6 @@ namespace SandboxBackend {
       phone?: string;
     }
     interface CircuitAccountReconfiguration {
-
       // Addresses where to send the TAN.
       contact_data: CircuitContactData;
 
@@ -300,7 +291,6 @@ namespace SandboxBackend {
       cashout_address: string;
     }
     interface AccountPasswordChange {
-
       // New password.
       new_password: string;
     }
@@ -314,7 +304,6 @@ namespace SandboxBackend {
 
       // Legal subject owning the account.
       name: string;
-
     }
 
     interface CircuitAccountData {
@@ -336,10 +325,9 @@ namespace SandboxBackend {
     enum TanChannel {
       SMS = "sms",
       EMAIL = "email",
-      FILE = "file"
+      FILE = "file",
     }
     interface CashoutRequest {
-
       // Optional subject to associate to the
       // cashout operation.  This data will appear
       // as the incoming wire transfer subject in
@@ -370,7 +358,6 @@ namespace SandboxBackend {
       uuid: string;
     }
     interface CashoutConfirm {
-
       // the TAN that confirms $cashoutId.
       tan: string;
     }
@@ -398,7 +385,6 @@ namespace SandboxBackend {
       cashouts: string[];
     }
     interface CashoutStatusResponse {
-
       status: CashoutStatus;
       // Amount debited to the circuit bank account.
       amount_debit: Amount;
@@ -415,7 +401,6 @@ namespace SandboxBackend {
       confirmation_time?: number | null; // milliseconds since the Unix epoch
     }
     enum CashoutStatus {
-
       // The payment was initiated after a valid
       // TAN was received by the bank.
       CONFIRMED = "confirmed",
@@ -425,5 +410,4 @@ namespace SandboxBackend {
       PENDING = "pending",
     }
   }
-
 }
diff --git a/packages/demobank-ui/src/hooks/access.ts 
b/packages/demobank-ui/src/hooks/access.ts
index 4d4574dac..9c162acfe 100644
--- a/packages/demobank-ui/src/hooks/access.ts
+++ b/packages/demobank-ui/src/hooks/access.ts
@@ -14,91 +14,113 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import useSWR from "swr";
-import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils.js";
-import { useEffect, useState } from "preact/hooks";
 import {
-  HttpError,
   HttpResponse,
   HttpResponseOk,
   HttpResponsePaginated,
+  RequestError,
 } from "@gnu-taler/web-util/lib/index.browser";
-import { useAuthenticatedBackend, useMatchMutate, usePublicBackend } from 
"./backend.js";
+import { useEffect, useState } from "preact/hooks";
+import useSWR from "swr";
 import { useBackendContext } from "../context/backend.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils.js";
+import {
+  useAuthenticatedBackend,
+  useMatchMutate,
+  usePublicBackend,
+} from "./backend.js";
 
 export function useAccessAPI(): AccessAPI {
   const mutateAll = useMatchMutate();
   const { request } = useAuthenticatedBackend();
-  const { state } = useBackendContext()
+  const { state } = useBackendContext();
   if (state.status === "loggedOut") {
-    throw Error("access-api can't be used when the user is not logged In")
+    throw Error("access-api can't be used when the user is not logged In");
   }
-  const account = state.username
+  const account = state.username;
 
   const createWithdrawal = async (
     data: SandboxBackend.Access.BankAccountCreateWithdrawalRequest,
-  ): 
Promise<HttpResponseOk<SandboxBackend.Access.BankAccountCreateWithdrawalResponse>>
 => {
-    const res = await 
request<SandboxBackend.Access.BankAccountCreateWithdrawalResponse>(`access-api/accounts/${account}/withdrawals`,
 {
-      method: "POST",
-      data,
-      contentType: "json"
-    });
+  ): Promise<
+    HttpResponseOk<SandboxBackend.Access.BankAccountCreateWithdrawalResponse>
+  > => {
+    const res =
+      await request<SandboxBackend.Access.BankAccountCreateWithdrawalResponse>(
+        `access-api/accounts/${account}/withdrawals`,
+        {
+          method: "POST",
+          data,
+          contentType: "json",
+        },
+      );
     return res;
   };
-  const abortWithdrawal = async (
-    id: string,
-  ): Promise<HttpResponseOk<void>> => {
-    const res = await 
request<void>(`access-api/accounts/${account}/withdrawals/${id}`, {
-      method: "POST",
-      contentType: "json"
-    });
+  const abortWithdrawal = async (id: string): Promise<HttpResponseOk<void>> => 
{
+    const res = await request<void>(
+      `access-api/accounts/${account}/withdrawals/${id}`,
+      {
+        method: "POST",
+        contentType: "json",
+      },
+    );
     await mutateAll(/.*accounts\/.*\/withdrawals\/.*/);
     return res;
   };
   const confirmWithdrawal = async (
     id: string,
   ): Promise<HttpResponseOk<void>> => {
-    const res = await 
request<void>(`access-api/accounts/${account}/withdrawals/${id}`, {
-      method: "POST",
-      contentType: "json"
-    });
+    const res = await request<void>(
+      `access-api/accounts/${account}/withdrawals/${id}`,
+      {
+        method: "POST",
+        contentType: "json",
+      },
+    );
     await mutateAll(/.*accounts\/.*\/withdrawals\/.*/);
     return res;
   };
   const createTransaction = async (
-    data: SandboxBackend.Access.CreateBankAccountTransactionCreate
+    data: SandboxBackend.Access.CreateBankAccountTransactionCreate,
   ): Promise<HttpResponseOk<void>> => {
-    const res = await 
request<void>(`access-api/accounts/${account}/transactions`, {
-      method: "POST",
-      data,
-      contentType: "json"
-    });
+    const res = await request<void>(
+      `access-api/accounts/${account}/transactions`,
+      {
+        method: "POST",
+        data,
+        contentType: "json",
+      },
+    );
     await mutateAll(/.*accounts\/.*\/transactions.*/);
     return res;
   };
-  const deleteAccount = async (
-  ): Promise<HttpResponseOk<void>> => {
+  const deleteAccount = async (): Promise<HttpResponseOk<void>> => {
     const res = await request<void>(`access-api/accounts/${account}`, {
       method: "DELETE",
-      contentType: "json"
+      contentType: "json",
     });
     await mutateAll(/.*accounts\/.*/);
     return res;
   };
 
-  return { abortWithdrawal, confirmWithdrawal, createWithdrawal, 
createTransaction, deleteAccount };
+  return {
+    abortWithdrawal,
+    confirmWithdrawal,
+    createWithdrawal,
+    createTransaction,
+    deleteAccount,
+  };
 }
 
 export function useTestingAPI(): TestingAPI {
   const mutateAll = useMatchMutate();
   const { request: noAuthRequest } = usePublicBackend();
   const register = async (
-    data: SandboxBackend.Access.BankRegistrationRequest
+    data: SandboxBackend.Access.BankRegistrationRequest,
   ): Promise<HttpResponseOk<void>> => {
     const res = await noAuthRequest<void>(`access-api/testing/register`, {
       method: "POST",
       data,
-      contentType: "json"
+      contentType: "json",
     });
     await mutateAll(/.*accounts\/.*/);
     return res;
@@ -107,25 +129,22 @@ export function useTestingAPI(): TestingAPI {
   return { register };
 }
 
-
 export interface TestingAPI {
   register: (
-    data: SandboxBackend.Access.BankRegistrationRequest
+    data: SandboxBackend.Access.BankRegistrationRequest,
   ) => Promise<HttpResponseOk<void>>;
 }
 
 export interface AccessAPI {
   createWithdrawal: (
     data: SandboxBackend.Access.BankAccountCreateWithdrawalRequest,
-  ) => 
Promise<HttpResponseOk<SandboxBackend.Access.BankAccountCreateWithdrawalResponse>>;
-  abortWithdrawal: (
-    wid: string,
-  ) => Promise<HttpResponseOk<void>>;
-  confirmWithdrawal: (
-    wid: string
-  ) => Promise<HttpResponseOk<void>>;
+  ) => Promise<
+    HttpResponseOk<SandboxBackend.Access.BankAccountCreateWithdrawalResponse>
+  >;
+  abortWithdrawal: (wid: string) => Promise<HttpResponseOk<void>>;
+  confirmWithdrawal: (wid: string) => Promise<HttpResponseOk<void>>;
   createTransaction: (
-    data: SandboxBackend.Access.CreateBankAccountTransactionCreate
+    data: SandboxBackend.Access.CreateBankAccountTransactionCreate,
   ) => Promise<HttpResponseOk<void>>;
   deleteAccount: () => Promise<HttpResponseOk<void>>;
 }
@@ -135,13 +154,17 @@ export interface InstanceTemplateFilter {
   position?: string;
 }
 
-
-export function useAccountDetails(account: string): 
HttpResponse<SandboxBackend.Access.BankAccountBalanceResponse, 
SandboxBackend.SandboxError> {
+export function useAccountDetails(
+  account: string,
+): HttpResponse<
+  SandboxBackend.Access.BankAccountBalanceResponse,
+  SandboxBackend.SandboxError
+> {
   const { fetcher } = useAuthenticatedBackend();
 
   const { data, error } = useSWR<
     HttpResponseOk<SandboxBackend.Access.BankAccountBalanceResponse>,
-    HttpError<SandboxBackend.SandboxError>
+    RequestError<SandboxBackend.SandboxError>
   >([`access-api/accounts/${account}`], fetcher, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -155,17 +178,23 @@ export function useAccountDetails(account: string): 
HttpResponse<SandboxBackend.
   });
 
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
 
 // FIXME: should poll
-export function useWithdrawalDetails(account: string, wid: string): 
HttpResponse<SandboxBackend.Access.BankAccountGetWithdrawalResponse, 
SandboxBackend.SandboxError> {
+export function useWithdrawalDetails(
+  account: string,
+  wid: string,
+): HttpResponse<
+  SandboxBackend.Access.BankAccountGetWithdrawalResponse,
+  SandboxBackend.SandboxError
+> {
   const { fetcher } = useAuthenticatedBackend();
 
   const { data, error } = useSWR<
     HttpResponseOk<SandboxBackend.Access.BankAccountGetWithdrawalResponse>,
-    HttpError<SandboxBackend.SandboxError>
+    RequestError<SandboxBackend.SandboxError>
   >([`access-api/accounts/${account}/withdrawals/${wid}`], fetcher, {
     refreshInterval: 1000,
     refreshWhenHidden: false,
@@ -176,21 +205,26 @@ export function useWithdrawalDetails(account: string, 
wid: string): HttpResponse
     errorRetryInterval: 1,
     shouldRetryOnError: false,
     keepPreviousData: true,
-
   });
 
   // if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
 
-export function useTransactionDetails(account: string, tid: string): 
HttpResponse<SandboxBackend.Access.BankAccountTransactionInfo, 
SandboxBackend.SandboxError> {
+export function useTransactionDetails(
+  account: string,
+  tid: string,
+): HttpResponse<
+  SandboxBackend.Access.BankAccountTransactionInfo,
+  SandboxBackend.SandboxError
+> {
   const { fetcher } = useAuthenticatedBackend();
 
   const { data, error } = useSWR<
     HttpResponseOk<SandboxBackend.Access.BankAccountTransactionInfo>,
-    HttpError<SandboxBackend.SandboxError>
+    RequestError<SandboxBackend.SandboxError>
   >([`access-api/accounts/${account}/transactions/${tid}`], fetcher, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -205,17 +239,20 @@ export function useTransactionDetails(account: string, 
tid: string): HttpRespons
 
   // if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
 
 interface PaginationFilter {
-  page: number,
+  page: number;
 }
 
 export function usePublicAccounts(
   args?: PaginationFilter,
-): HttpResponsePaginated<SandboxBackend.Access.PublicAccountsResponse, 
SandboxBackend.SandboxError> {
+): HttpResponsePaginated<
+  SandboxBackend.Access.PublicAccountsResponse,
+  SandboxBackend.SandboxError
+> {
   const { paginatedFetcher } = usePublicBackend();
 
   const [page, setPage] = useState(1);
@@ -226,18 +263,21 @@ export function usePublicAccounts(
     isValidating: loadingAfter,
   } = useSWR<
     HttpResponseOk<SandboxBackend.Access.PublicAccountsResponse>,
-    HttpError<SandboxBackend.SandboxError>
+    RequestError<SandboxBackend.SandboxError>
   >([`public-accounts`, args?.page, PAGE_SIZE], paginatedFetcher);
 
   const [lastAfter, setLastAfter] = useState<
-    HttpResponse<SandboxBackend.Access.PublicAccountsResponse, 
SandboxBackend.SandboxError>
+    HttpResponse<
+      SandboxBackend.Access.PublicAccountsResponse,
+      SandboxBackend.SandboxError
+    >
   >({ loading: true });
 
   useEffect(() => {
     if (afterData) setLastAfter(afterData);
   }, [afterData]);
 
-  if (afterError) return afterError;
+  if (afterError) return afterError.info;
 
   // if the query returns less that we ask, then we have reach the end or 
beginning
   const isReachingEnd =
@@ -254,30 +294,33 @@ export function usePublicAccounts(
       }
     },
     loadMorePrev: () => {
-      null
+      null;
     },
   };
 
-  const publicAccounts = !afterData ? [] : (afterData || 
lastAfter).data.publicAccounts;
-  if (loadingAfter)
-    return { loading: true, data: { publicAccounts } };
+  const publicAccounts = !afterData
+    ? []
+    : (afterData || lastAfter).data.publicAccounts;
+  if (loadingAfter) return { loading: true, data: { publicAccounts } };
   if (afterData) {
     return { ok: true, data: { publicAccounts }, ...pagination };
   }
   return { loading: true };
 }
 
-
 /**
  * FIXME: mutate result when balance change (transaction )
- * @param account 
- * @param args 
- * @returns 
+ * @param account
+ * @param args
+ * @returns
  */
 export function useTransactions(
   account: string,
   args?: PaginationFilter,
-): 
HttpResponsePaginated<SandboxBackend.Access.BankAccountTransactionsResponse, 
SandboxBackend.SandboxError> {
+): HttpResponsePaginated<
+  SandboxBackend.Access.BankAccountTransactionsResponse,
+  SandboxBackend.SandboxError
+> {
   const { paginatedFetcher } = useAuthenticatedBackend();
 
   const [page, setPage] = useState(1);
@@ -288,18 +331,24 @@ export function useTransactions(
     isValidating: loadingAfter,
   } = useSWR<
     HttpResponseOk<SandboxBackend.Access.BankAccountTransactionsResponse>,
-    HttpError<SandboxBackend.SandboxError>
-  >([`access-api/accounts/${account}/transactions`, args?.page, PAGE_SIZE], 
paginatedFetcher);
+    RequestError<SandboxBackend.SandboxError>
+  >(
+    [`access-api/accounts/${account}/transactions`, args?.page, PAGE_SIZE],
+    paginatedFetcher,
+  );
 
   const [lastAfter, setLastAfter] = useState<
-    HttpResponse<SandboxBackend.Access.BankAccountTransactionsResponse, 
SandboxBackend.SandboxError>
+    HttpResponse<
+      SandboxBackend.Access.BankAccountTransactionsResponse,
+      SandboxBackend.SandboxError
+    >
   >({ loading: true });
 
   useEffect(() => {
     if (afterData) setLastAfter(afterData);
   }, [afterData]);
 
-  if (afterError) return afterError;
+  if (afterError) return afterError.info;
 
   // if the query returns less that we ask, then we have reach the end or 
beginning
   const isReachingEnd =
@@ -316,13 +365,14 @@ export function useTransactions(
       }
     },
     loadMorePrev: () => {
-      null
+      null;
     },
   };
 
-  const transactions = !afterData ? [] : (afterData || 
lastAfter).data.transactions;
-  if (loadingAfter)
-    return { loading: true, data: { transactions } };
+  const transactions = !afterData
+    ? []
+    : (afterData || lastAfter).data.transactions;
+  if (loadingAfter) return { loading: true, data: { transactions } };
   if (afterData) {
     return { ok: true, data: { transactions }, ...pagination };
   }
diff --git a/packages/demobank-ui/src/hooks/backend.ts 
b/packages/demobank-ui/src/hooks/backend.ts
index f4f5ecfd0..e87bdd5fe 100644
--- a/packages/demobank-ui/src/hooks/backend.ts
+++ b/packages/demobank-ui/src/hooks/backend.ts
@@ -15,7 +15,10 @@
  */
 
 import { canonicalizeBaseUrl } from "@gnu-taler/taler-util";
-import { useLocalStorage } from "@gnu-taler/web-util/lib/index.browser";
+import {
+  RequestError,
+  useLocalStorage,
+} from "@gnu-taler/web-util/lib/index.browser";
 import {
   HttpResponse,
   HttpResponseOk,
@@ -57,7 +60,7 @@ export function getInitialBackendBaseURL(): string {
 
 export const defaultState: BackendState = {
   status: "loggedOut",
-  url: getInitialBackendBaseURL()
+  url: getInitialBackendBaseURL(),
 };
 
 export interface BackendStateHandler {
@@ -91,7 +94,12 @@ export function useBackendState(): BackendStateHandler {
     },
     logIn(info) {
       //admin is defined by the username
-      const nextState: BackendState = { status: "loggedIn", url: state.url, 
...info, isUserAdministrator: info.username === "admin" };
+      const nextState: BackendState = {
+        status: "loggedIn",
+        url: state.url,
+        ...info,
+        isUserAdministrator: info.username === "admin",
+      };
       update(JSON.stringify(nextState));
     },
   };
@@ -103,24 +111,25 @@ interface useBackendType {
     options?: RequestOptions,
   ) => Promise<HttpResponseOk<T>>;
   fetcher: <T>(endpoint: string) => Promise<HttpResponseOk<T>>;
-  multiFetcher: <T>(endpoint: string[]) => Promise<HttpResponseOk<T>[]>;
-  paginatedFetcher: <T>(args: [string, number, number]) => 
Promise<HttpResponseOk<T>>;
-  sandboxAccountsFetcher: <T>(args: [string, number, number, string]) => 
Promise<HttpResponseOk<T>>;
+  multiFetcher: <T>(endpoint: string[][]) => Promise<HttpResponseOk<T>[]>;
+  paginatedFetcher: <T>(
+    args: [string, number, number],
+  ) => Promise<HttpResponseOk<T>>;
+  sandboxAccountsFetcher: <T>(
+    args: [string, number, number, string],
+  ) => Promise<HttpResponseOk<T>>;
 }
-
-
 export function usePublicBackend(): useBackendType {
   const { state } = useBackendContext();
   const { request: requestHandler } = useApiContext();
 
-  const baseUrl = state.url
+  const baseUrl = state.url;
 
   const request = useCallback(
     function requestImpl<T>(
       path: string,
       options: RequestOptions = {},
     ): Promise<HttpResponseOk<T>> {
-
       return requestHandler<T>(baseUrl, path, options);
     },
     [baseUrl],
@@ -133,15 +142,21 @@ export function usePublicBackend(): useBackendType {
     [baseUrl],
   );
   const paginatedFetcher = useCallback(
-    function fetcherImpl<T>([endpoint, page, size]: [string, number, number]): 
Promise<HttpResponseOk<T>> {
-      return requestHandler<T>(baseUrl, endpoint, { params: { page: page || 1, 
size } });
+    function fetcherImpl<T>([endpoint, page, size]: [
+      string,
+      number,
+      number,
+    ]): Promise<HttpResponseOk<T>> {
+      return requestHandler<T>(baseUrl, endpoint, {
+        params: { page: page || 1, size },
+      });
     },
     [baseUrl],
   );
   const multiFetcher = useCallback(
-    function multiFetcherImpl<T>(
-      endpoints: string[],
-    ): Promise<HttpResponseOk<T>[]> {
+    function multiFetcherImpl<T>([endpoints]: string[][]): Promise<
+      HttpResponseOk<T>[]
+    > {
       return Promise.all(
         endpoints.map((endpoint) => requestHandler<T>(baseUrl, endpoint)),
       );
@@ -149,27 +164,39 @@ export function usePublicBackend(): useBackendType {
     [baseUrl],
   );
   const sandboxAccountsFetcher = useCallback(
-    function fetcherImpl<T>([endpoint, page, size, account]: [string, number, 
number, string]): Promise<HttpResponseOk<T>> {
-      return requestHandler<T>(baseUrl, endpoint, { params: { page: page || 1, 
size } });
+    function fetcherImpl<T>([endpoint, page, size, account]: [
+      string,
+      number,
+      number,
+      string,
+    ]): Promise<HttpResponseOk<T>> {
+      return requestHandler<T>(baseUrl, endpoint, {
+        params: { page: page || 1, size },
+      });
     },
     [baseUrl],
   );
-  return { request, fetcher, paginatedFetcher, multiFetcher, 
sandboxAccountsFetcher };
+  return {
+    request,
+    fetcher,
+    paginatedFetcher,
+    multiFetcher,
+    sandboxAccountsFetcher,
+  };
 }
 
 export function useAuthenticatedBackend(): useBackendType {
   const { state } = useBackendContext();
   const { request: requestHandler } = useApiContext();
 
-  const creds = state.status === "loggedIn" ? state : undefined
-  const baseUrl = state.url
+  const creds = state.status === "loggedIn" ? state : undefined;
+  const baseUrl = state.url;
 
   const request = useCallback(
     function requestImpl<T>(
       path: string,
       options: RequestOptions = {},
     ): Promise<HttpResponseOk<T>> {
-
       return requestHandler<T>(baseUrl, path, { basicAuth: creds, ...options 
});
     },
     [baseUrl, creds],
@@ -182,36 +209,66 @@ export function useAuthenticatedBackend(): useBackendType 
{
     [baseUrl, creds],
   );
   const paginatedFetcher = useCallback(
-    function fetcherImpl<T>([endpoint, page = 0, size]: [string, number, 
number]): Promise<HttpResponseOk<T>> {
-      return requestHandler<T>(baseUrl, endpoint, { basicAuth: creds, params: 
{ page, size } });
+    function fetcherImpl<T>([endpoint, page = 0, size]: [
+      string,
+      number,
+      number,
+    ]): Promise<HttpResponseOk<T>> {
+      return requestHandler<T>(baseUrl, endpoint, {
+        basicAuth: creds,
+        params: { page, size },
+      });
     },
     [baseUrl, creds],
   );
   const multiFetcher = useCallback(
-    function multiFetcherImpl<T>(
-      endpoints: string[],
-    ): Promise<HttpResponseOk<T>[]> {
+    function multiFetcherImpl<T>([endpoints]: string[][]): Promise<
+      HttpResponseOk<T>[]
+    > {
+      console.log("list size", endpoints.length, endpoints);
       return Promise.all(
-        endpoints.map((endpoint) => requestHandler<T>(baseUrl, endpoint, { 
basicAuth: creds })),
+        endpoints.map((endpoint) =>
+          requestHandler<T>(baseUrl, endpoint, { basicAuth: creds }),
+        ),
       );
     },
     [baseUrl, creds],
   );
   const sandboxAccountsFetcher = useCallback(
-    function fetcherImpl<T>([endpoint, page, size, account]: [string, number, 
number, string]): Promise<HttpResponseOk<T>> {
-      return requestHandler<T>(baseUrl, endpoint, { basicAuth: creds, params: 
{ page: page || 1, size } });
+    function fetcherImpl<T>([endpoint, page, size, account]: [
+      string,
+      number,
+      number,
+      string,
+    ]): Promise<HttpResponseOk<T>> {
+      return requestHandler<T>(baseUrl, endpoint, {
+        basicAuth: creds,
+        params: { page: page || 1, size },
+      });
     },
     [baseUrl],
   );
-  return { request, fetcher, paginatedFetcher, multiFetcher, 
sandboxAccountsFetcher };
+
+  return {
+    request,
+    fetcher,
+    paginatedFetcher,
+    multiFetcher,
+    sandboxAccountsFetcher,
+  };
 }
 
-export function useBackendConfig(): HttpResponse<SandboxBackend.Config, 
SandboxBackend.SandboxError> {
+export function useBackendConfig(): HttpResponse<
+  SandboxBackend.Config,
+  SandboxBackend.SandboxError
+> {
   const { request } = usePublicBackend();
 
   type Type = SandboxBackend.Config;
 
-  const [result, setResult] = useState<HttpResponse<Type, 
SandboxBackend.SandboxError>>({ loading: true });
+  const [result, setResult] = useState<
+    HttpResponse<Type, SandboxBackend.SandboxError>
+  >({ loading: true });
 
   useEffect(() => {
     request<Type>(`/config`)
@@ -238,10 +295,8 @@ export function useMatchMutate(): (
     const allKeys = Array.from(cache.keys());
     const keys = allKeys.filter((key) => re.test(key));
     const mutations = keys.map((key) => {
-      mutate(key, value, true);
+      return mutate(key, value, true);
     });
     return Promise.all(mutations);
   };
 }
-
-
diff --git a/packages/demobank-ui/src/hooks/circuit.ts 
b/packages/demobank-ui/src/hooks/circuit.ts
index 6e9ada601..91922a6ba 100644
--- a/packages/demobank-ui/src/hooks/circuit.ts
+++ b/packages/demobank-ui/src/hooks/circuit.ts
@@ -15,23 +15,24 @@
  */
 
 import {
-  HttpError,
   HttpResponse,
   HttpResponseOk,
   HttpResponsePaginated,
-  RequestError
+  RequestError,
+  useApiContext,
 } from "@gnu-taler/web-util/lib/index.browser";
 import { useEffect, useMemo, useState } from "preact/hooks";
 import useSWR from "swr";
 import { useBackendContext } from "../context/backend.js";
 import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils.js";
-import { useAuthenticatedBackend } from "./backend.js";
+import { useAuthenticatedBackend, useMatchMutate } from "./backend.js";
 
 export function useAdminAccountAPI(): AdminAccountAPI {
   const { request } = useAuthenticatedBackend();
-  const { state } = useBackendContext()
+  const mutateAll = useMatchMutate();
+  const { state } = useBackendContext();
   if (state.status === "loggedOut") {
-    throw Error("access-api can't be used when the user is not logged In")
+    throw Error("access-api can't be used when the user is not logged In");
   }
 
   const createAccount = async (
@@ -40,8 +41,9 @@ export function useAdminAccountAPI(): AdminAccountAPI {
     const res = await request<void>(`circuit-api/accounts`, {
       method: "POST",
       data,
-      contentType: "json"
+      contentType: "json",
     });
+    await mutateAll(/.*circuit-api\/accounts.*/);
     return res;
   };
 
@@ -52,8 +54,9 @@ export function useAdminAccountAPI(): AdminAccountAPI {
     const res = await request<void>(`circuit-api/accounts/${account}`, {
       method: "PATCH",
       data,
-      contentType: "json"
+      contentType: "json",
     });
+    await mutateAll(/.*circuit-api\/accounts.*/);
     return res;
   };
   const deleteAccount = async (
@@ -61,8 +64,9 @@ export function useAdminAccountAPI(): AdminAccountAPI {
   ): Promise<HttpResponseOk<void>> => {
     const res = await request<void>(`circuit-api/accounts/${account}`, {
       method: "DELETE",
-      contentType: "json"
+      contentType: "json",
     });
+    await mutateAll(/.*circuit-api\/accounts.*/);
     return res;
   };
   const changePassword = async (
@@ -72,7 +76,7 @@ export function useAdminAccountAPI(): AdminAccountAPI {
     const res = await request<void>(`circuit-api/accounts/${account}/auth`, {
       method: "PATCH",
       data,
-      contentType: "json"
+      contentType: "json",
     });
     return res;
   };
@@ -82,9 +86,10 @@ export function useAdminAccountAPI(): AdminAccountAPI {
 
 export function useCircuitAccountAPI(): CircuitAccountAPI {
   const { request } = useAuthenticatedBackend();
-  const { state } = useBackendContext()
+  const mutateAll = useMatchMutate();
+  const { state } = useBackendContext();
   if (state.status === "loggedOut") {
-    throw Error("access-api can't be used when the user is not logged In")
+    throw Error("access-api can't be used when the user is not logged In");
   }
   const account = state.username;
 
@@ -94,8 +99,9 @@ export function useCircuitAccountAPI(): CircuitAccountAPI {
     const res = await request<void>(`circuit-api/accounts/${account}`, {
       method: "PATCH",
       data,
-      contentType: "json"
+      contentType: "json",
     });
+    await mutateAll(/.*circuit-api\/accounts.*/);
     return res;
   };
   const changePassword = async (
@@ -104,7 +110,7 @@ export function useCircuitAccountAPI(): CircuitAccountAPI {
     const res = await request<void>(`circuit-api/accounts/${account}/auth`, {
       method: "PATCH",
       data,
-      contentType: "json"
+      contentType: "json",
     });
     return res;
   };
@@ -120,57 +126,72 @@ export interface AdminAccountAPI {
 
   updateAccount: (
     account: string,
-    data: SandboxBackend.Circuit.CircuitAccountReconfiguration
+    data: SandboxBackend.Circuit.CircuitAccountReconfiguration,
   ) => Promise<HttpResponseOk<void>>;
   changePassword: (
     account: string,
-    data: SandboxBackend.Circuit.AccountPasswordChange
+    data: SandboxBackend.Circuit.AccountPasswordChange,
   ) => Promise<HttpResponseOk<void>>;
 }
 
 export interface CircuitAccountAPI {
   updateAccount: (
-    data: SandboxBackend.Circuit.CircuitAccountReconfiguration
+    data: SandboxBackend.Circuit.CircuitAccountReconfiguration,
   ) => Promise<HttpResponseOk<void>>;
   changePassword: (
-    data: SandboxBackend.Circuit.AccountPasswordChange
+    data: SandboxBackend.Circuit.AccountPasswordChange,
   ) => Promise<HttpResponseOk<void>>;
 }
 
-
 export interface InstanceTemplateFilter {
   //FIXME: add filter to the template list
   position?: string;
 }
 
-
-export function useMyAccountDetails(): 
HttpResponse<SandboxBackend.Circuit.CircuitAccountData, 
SandboxBackend.SandboxError> {
-  const { fetcher } = useAuthenticatedBackend();
-  const { state } = useBackendContext()
-  if (state.status === "loggedOut") {
-    throw Error("can't access my-account-details when logged out")
+async function getBusinessStatus(
+  request: ReturnType<typeof useApiContext>["request"],
+  url: string,
+  basicAuth: { username: string; password: string },
+): Promise<boolean> {
+  try {
+    const result = await request<
+      HttpResponseOk<SandboxBackend.Circuit.CircuitAccountData>
+    >(url, `circuit-api/accounts/${basicAuth.username}`, { basicAuth });
+    return result.ok;
+  } catch (error) {
+    return false;
   }
-  const { data, error } = useSWR<
-    HttpResponseOk<SandboxBackend.Circuit.CircuitAccountData>,
-    HttpError<SandboxBackend.SandboxError>
-  >([`accounts/${state.username}`], fetcher, {
-    refreshInterval: 0,
-    refreshWhenHidden: false,
-    revalidateOnFocus: false,
-    revalidateOnReconnect: false,
-    refreshWhenOffline: false,
-    errorRetryCount: 0,
-    errorRetryInterval: 1,
-    shouldRetryOnError: false,
-    keepPreviousData: true,
+}
+
+export function useBusinessAccountFlag(): boolean | undefined {
+  const [isBusiness, setIsBusiness] = useState<boolean | undefined>();
+  const { state } = useBackendContext();
+  const { request } = useApiContext();
+  const creds =
+    state.status === "loggedOut"
+      ? undefined
+      : { username: state.username, password: state.password };
+
+  useEffect(() => {
+    if (!creds) return;
+    getBusinessStatus(request, state.url, creds)
+      .then((result) => {
+        setIsBusiness(result);
+      })
+      .catch((error) => {
+        setIsBusiness(false);
+      });
   });
 
-  if (data) return data;
-  if (error) return error;
-  return { loading: true };
+  return isBusiness;
 }
 
-export function useAccountDetails(account: string): 
HttpResponse<SandboxBackend.Circuit.CircuitAccountData, 
SandboxBackend.SandboxError> {
+export function useBusinessAccountDetails(
+  account: string,
+): HttpResponse<
+  SandboxBackend.Circuit.CircuitAccountData,
+  SandboxBackend.SandboxError
+> {
   const { fetcher } = useAuthenticatedBackend();
 
   const { data, error } = useSWR<
@@ -188,20 +209,22 @@ export function useAccountDetails(account: string): 
HttpResponse<SandboxBackend.
     keepPreviousData: true,
   });
 
-  // if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
   if (error) return error.info;
   return { loading: true };
 }
 
 interface PaginationFilter {
-  account?: string,
-  page?: number,
+  account?: string;
+  page?: number;
 }
 
-export function useAccounts(
+export function useBusinessAccounts(
   args?: PaginationFilter,
-): HttpResponsePaginated<SandboxBackend.Circuit.CircuitAccounts, 
SandboxBackend.SandboxError> {
+): HttpResponsePaginated<
+  SandboxBackend.Circuit.CircuitAccounts,
+  SandboxBackend.SandboxError
+> {
   const { sandboxAccountsFetcher } = useAuthenticatedBackend();
   const [page, setPage] = useState(0);
 
@@ -212,17 +235,21 @@ export function useAccounts(
   } = useSWR<
     HttpResponseOk<SandboxBackend.Circuit.CircuitAccounts>,
     RequestError<SandboxBackend.SandboxError>
-  >([`circuit-api/accounts`, args?.page, PAGE_SIZE, args?.account], 
sandboxAccountsFetcher, {
-    refreshInterval: 0,
-    refreshWhenHidden: false,
-    revalidateOnFocus: false,
-    revalidateOnReconnect: false,
-    refreshWhenOffline: false,
-    errorRetryCount: 0,
-    errorRetryInterval: 1,
-    shouldRetryOnError: false,
-    keepPreviousData: true,
-  });
+  >(
+    [`circuit-api/accounts`, args?.page, PAGE_SIZE, args?.account],
+    sandboxAccountsFetcher,
+    {
+      refreshInterval: 0,
+      refreshWhenHidden: false,
+      revalidateOnFocus: false,
+      revalidateOnReconnect: false,
+      refreshWhenOffline: false,
+      errorRetryCount: 0,
+      errorRetryInterval: 1,
+      shouldRetryOnError: false,
+      keepPreviousData: true,
+    },
+  );
 
   // const [lastAfter, setLastAfter] = useState<
   //   HttpResponse<SandboxBackend.Circuit.CircuitAccounts, 
SandboxBackend.SandboxError>
@@ -247,18 +274,18 @@ export function useAccounts(
       }
     },
     loadMorePrev: () => {
-      null
+      null;
     },
   };
 
   const result = useMemo(() => {
-    const customers = !afterData ? [] : (afterData)?.data?.customers ?? [];
-    return { ok: true as const, data: { customers }, ...pagination }
-  }, [afterData?.data])
+    const customers = !afterData ? [] : afterData?.data?.customers ?? [];
+    return { ok: true as const, data: { customers }, ...pagination };
+  }, [afterData?.data]);
 
   if (afterError) return afterError.info;
   if (afterData) {
-    return result
+    return result;
   }
 
   // if (loadingAfter)
diff --git a/packages/demobank-ui/src/pages/AccountPage.tsx 
b/packages/demobank-ui/src/pages/AccountPage.tsx
index 769e85804..370605871 100644
--- a/packages/demobank-ui/src/pages/AccountPage.tsx
+++ b/packages/demobank-ui/src/pages/AccountPage.tsx
@@ -104,49 +104,48 @@ export function AccountPage({ account, onLoadNotOk }: 
Props): VNode {
       )}
 
       <section style={{ marginTop: "2em" }}>
-        <Moves account={account} />
+        <div class="active">
+          <h3>{i18n.str`Latest transactions`}</h3>
+          <Transactions account={account} />
+        </div>
       </section>
     </Fragment>
   );
 }
 
-function Moves({ account }: { account: string }): VNode {
-  const [tab, setTab] = useState<"transactions" | "cashouts">("transactions");
-  const { i18n } = useTranslationContext();
-  return (
-    <article>
-      <div class="payments">
-        <div class="tab">
-          <button
-            class={tab === "transactions" ? "tablinks active" : "tablinks"}
-            onClick={(): void => {
-              setTab("transactions");
-            }}
-          >
-            {i18n.str`Transactions`}
-          </button>
-          <button
-            class={tab === "cashouts" ? "tablinks active" : "tablinks"}
-            onClick={(): void => {
-              setTab("cashouts");
-            }}
-          >
-            {i18n.str`Cashouts`}
-          </button>
-        </div>
-        {tab === "transactions" && (
-          <div class="active">
-            <h3>{i18n.str`Latest transactions`}</h3>
-            <Transactions account={account} />
-          </div>
-        )}
-        {tab === "cashouts" && (
-          <div class="active">
-            <h3>{i18n.str`Latest cashouts`}</h3>
-            <Cashouts account={account} />
-          </div>
-        )}
-      </div>
-    </article>
-  );
-}
+// function Moves({ account }: { account: string }): VNode {
+//   const [tab, setTab] = useState<"transactions" | 
"cashouts">("transactions");
+//   const { i18n } = useTranslationContext();
+//   return (
+//     <article>
+//       <div class="payments">
+//         <div class="tab">
+//           <button
+//             class={tab === "transactions" ? "tablinks active" : "tablinks"}
+//             onClick={(): void => {
+//               setTab("transactions");
+//             }}
+//           >
+//             {i18n.str`Transactions`}
+//           </button>
+//           <button
+//             class={tab === "cashouts" ? "tablinks active" : "tablinks"}
+//             onClick={(): void => {
+//               setTab("cashouts");
+//             }}
+//           >
+//             {i18n.str`Cashouts`}
+//           </button>
+//         </div>
+//         {tab === "transactions" && (
+//         )}
+//         {tab === "cashouts" && (
+//           <div class="active">
+//             <h3>{i18n.str`Latest cashouts`}</h3>
+//             <Cashouts account={account} />
+//           </div>
+//         )}
+//       </div>
+//     </article>
+//   );
+// }
diff --git a/packages/demobank-ui/src/pages/AdminPage.tsx 
b/packages/demobank-ui/src/pages/AdminPage.tsx
index 9efd37f12..f8efddd80 100644
--- a/packages/demobank-ui/src/pages/AdminPage.tsx
+++ b/packages/demobank-ui/src/pages/AdminPage.tsx
@@ -24,8 +24,8 @@ import { Fragment, h, VNode } from "preact";
 import { useState } from "preact/hooks";
 import { ErrorMessage, usePageContext } from "../context/pageState.js";
 import {
-  useAccountDetails,
-  useAccounts,
+  useBusinessAccountDetails,
+  useBusinessAccounts,
   useAdminAccountAPI,
 } from "../hooks/circuit.js";
 import {
@@ -71,7 +71,7 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
     }));
   }
 
-  const result = useAccounts({ account });
+  const result = useBusinessAccounts({ account });
   const { i18n } = useTranslationContext();
 
   if (result.loading) return <div />;
@@ -86,6 +86,10 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
       <ShowAccountDetails
         account={showDetails}
         onLoadNotOk={onLoadNotOk}
+        onChangePassword={() => {
+          setUpdatePassword(showDetails);
+          setShowDetails(undefined);
+        }}
         onUpdateSuccess={() => {
           showInfoMessage(i18n.str`Account updated`);
           setShowDetails(undefined);
@@ -230,7 +234,7 @@ function initializeFromTemplate(
   return initial as any;
 }
 
-function UpdateAccountPassword({
+export function UpdateAccountPassword({
   account,
   onClear,
   onUpdateSuccess,
@@ -242,7 +246,7 @@ function UpdateAccountPassword({
   account: string;
 }): VNode {
   const { i18n } = useTranslationContext();
-  const result = useAccountDetails(account);
+  const result = useBusinessAccountDetails(account);
   const { changePassword } = useAdminAccountAPI();
   const [password, setPassword] = useState<string | undefined>();
   const [repeat, setRepeat] = useState<string | undefined>();
@@ -268,7 +272,7 @@ function UpdateAccountPassword({
     <div>
       <div>
         <h1 class="nav welcome-text">
-          <i18n.Translate>Admin panel</i18n.Translate>
+          <i18n.Translate>Update password for {account}</i18n.Translate>
         </h1>
       </div>
       {error && (
@@ -276,10 +280,6 @@ function UpdateAccountPassword({
       )}
 
       <form class="pure-form">
-        <fieldset>
-          <label for="username">{i18n.str`Username`}</label>
-          <input name="username" type="text" readOnly value={account} />
-        </fieldset>
         <fieldset>
           <label>{i18n.str`Password`}</label>
           <input
@@ -366,7 +366,7 @@ function CreateNewAccount({
     <div>
       <div>
         <h1 class="nav welcome-text">
-          <i18n.Translate>Admin panel</i18n.Translate>
+          <i18n.Translate>New account</i18n.Translate>
         </h1>
       </div>
       {error && (
@@ -428,19 +428,21 @@ function CreateNewAccount({
   );
 }
 
-function ShowAccountDetails({
+export function ShowAccountDetails({
   account,
   onClear,
   onUpdateSuccess,
   onLoadNotOk,
+  onChangePassword,
 }: {
   onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
-  onClear: () => void;
+  onClear?: () => void;
+  onChangePassword: () => void;
   onUpdateSuccess: () => void;
   account: string;
 }): VNode {
   const { i18n } = useTranslationContext();
-  const result = useAccountDetails(account);
+  const result = useBusinessAccountDetails(account);
   const { updateAccount } = useAdminAccountAPI();
   const [update, setUpdate] = useState(false);
   const [submitAccount, setSubmitAccount] = useState<
@@ -459,7 +461,7 @@ function ShowAccountDetails({
     <div>
       <div>
         <h1 class="nav welcome-text">
-          <i18n.Translate>Admin panel</i18n.Translate>
+          <i18n.Translate>Business account details</i18n.Translate>
         </h1>
       </div>
       {error && (
@@ -474,42 +476,59 @@ function ShowAccountDetails({
       <p>
         <div style={{ display: "flex", justifyContent: "space-between" }}>
           <div>
-            <input
-              class="pure-button"
-              type="submit"
-              value={i18n.str`Close`}
-              onClick={async (e) => {
-                e.preventDefault();
-                onClear();
-              }}
-            />
+            {onClear ? (
+              <input
+                class="pure-button"
+                type="submit"
+                value={i18n.str`Close`}
+                onClick={async (e) => {
+                  e.preventDefault();
+                  onClear();
+                }}
+              />
+            ) : undefined}
           </div>
-          <div>
-            <input
-              id="select-exchange"
-              class="pure-button pure-button-primary content"
-              disabled={update && !submitAccount}
-              type="submit"
-              value={update ? i18n.str`Confirm` : i18n.str`Update`}
-              onClick={async (e) => {
-                e.preventDefault();
-
-                if (!update) {
-                  setUpdate(true);
-                } else {
-                  if (!submitAccount) return;
-                  try {
-                    await updateAccount(account, {
-                      cashout_address: submitAccount.cashout_address,
-                      contact_data: submitAccount.contact_data,
-                    });
-                    onUpdateSuccess();
-                  } catch (error) {
-                    handleError(error, saveError, i18n);
+          <div style={{ display: "flex" }}>
+            <div>
+              <input
+                id="select-exchange"
+                class="pure-button pure-button-primary content"
+                disabled={update && !submitAccount}
+                type="submit"
+                value={i18n.str`Change password`}
+                onClick={async (e) => {
+                  e.preventDefault();
+                  onChangePassword();
+                }}
+              />
+            </div>
+            <div>
+              <input
+                id="select-exchange"
+                class="pure-button pure-button-primary content"
+                disabled={update && !submitAccount}
+                type="submit"
+                value={update ? i18n.str`Confirm` : i18n.str`Update`}
+                onClick={async (e) => {
+                  e.preventDefault();
+
+                  if (!update) {
+                    setUpdate(true);
+                  } else {
+                    if (!submitAccount) return;
+                    try {
+                      await updateAccount(account, {
+                        cashout_address: submitAccount.cashout_address,
+                        contact_data: submitAccount.contact_data,
+                      });
+                      onUpdateSuccess();
+                    } catch (error) {
+                      handleError(error, saveError, i18n);
+                    }
                   }
-                }
-              }}
-            />
+                }}
+              />
+            </div>
           </div>
         </div>
       </p>
diff --git a/packages/demobank-ui/src/pages/BankFrame.tsx 
b/packages/demobank-ui/src/pages/BankFrame.tsx
index ed36daa21..0fb75b87b 100644
--- a/packages/demobank-ui/src/pages/BankFrame.tsx
+++ b/packages/demobank-ui/src/pages/BankFrame.tsx
@@ -15,6 +15,7 @@
  */
 
 import { Logger } from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
 import { ComponentChildren, Fragment, h, VNode } from "preact";
 import talerLogo from "../assets/logo-white.svg";
 import { LangSelectorLikePy as LangSelector } from 
"../components/LangSelector.js";
@@ -24,41 +25,46 @@ import {
   PageStateType,
   usePageContext,
 } from "../context/pageState.js";
-import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
+import { useBusinessAccountDetails } from "../hooks/circuit.js";
 import { bankUiSettings } from "../settings.js";
 
 const logger = new Logger("BankFrame");
 
+function MaybeBusinessButton({
+  account,
+  onClick,
+}: {
+  account: string;
+  onClick: () => void;
+}): VNode {
+  const { i18n } = useTranslationContext();
+  const result = useBusinessAccountDetails(account);
+  if (!result.ok) return <Fragment />;
+  return (
+    <div class="some-space">
+      <a
+        href="#"
+        class="pure-button pure-button-primary"
+        onClick={(e) => {
+          e.preventDefault();
+          onClick();
+        }}
+      >{i18n.str`Business Profile`}</a>
+    </div>
+  );
+}
+
 export function BankFrame({
   children,
+  goToBusinessAccount,
 }: {
   children: ComponentChildren;
+  goToBusinessAccount?: () => void;
 }): VNode {
   const { i18n } = useTranslationContext();
   const backend = useBackendContext();
   const { pageState, pageStateSetter } = usePageContext();
   logger.trace("state", pageState);
-  const logOut = (
-    <div class="logout">
-      <a
-        href="#"
-        class="pure-button logout-button"
-        onClick={() => {
-          pageStateSetter((prevState: PageStateType) => {
-            const { talerWithdrawUri, withdrawalId, ...rest } = prevState;
-            backend.logOut();
-            return {
-              ...rest,
-              withdrawalInProgress: false,
-              error: undefined,
-              info: undefined,
-              isRawPayto: false,
-            };
-          });
-        }}
-      >{i18n.str`Logout`}</a>
-    </div>
-  );
 
   const demo_sites = [];
   for (const i in bankUiSettings.demoSites)
@@ -120,7 +126,36 @@ export function BankFrame({
           />
         )}
         <StatusBanner />
-        {backend.state.status === "loggedIn" ? logOut : null}
+        {backend.state.status === "loggedIn" ? (
+          <div class="top-right">
+            {goToBusinessAccount ? (
+              <MaybeBusinessButton
+                account={backend.state.username}
+                onClick={goToBusinessAccount}
+              />
+            ) : undefined}
+            <div class="some-space">
+              <a
+                href="#"
+                class="pure-button logout-button"
+                onClick={() => {
+                  pageStateSetter((prevState: PageStateType) => {
+                    const { talerWithdrawUri, withdrawalId, ...rest } =
+                      prevState;
+                    backend.logOut();
+                    return {
+                      ...rest,
+                      withdrawalInProgress: false,
+                      error: undefined,
+                      info: undefined,
+                      isRawPayto: false,
+                    };
+                  });
+                }}
+              >{i18n.str`Logout`}</a>
+            </div>
+          </div>
+        ) : null}
         {children}
       </section>
       <section id="footer" class="footer">
diff --git a/packages/demobank-ui/src/pages/BusinessAccount.tsx 
b/packages/demobank-ui/src/pages/BusinessAccount.tsx
new file mode 100644
index 000000000..d845c2fa0
--- /dev/null
+++ b/packages/demobank-ui/src/pages/BusinessAccount.tsx
@@ -0,0 +1,90 @@
+/*
+ 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 { TranslatedString } from "@gnu-taler/taler-util";
+import {
+  HttpResponsePaginated,
+  useTranslationContext,
+} from "@gnu-taler/web-util/lib/index.browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Cashouts } from "../components/Cashouts/index.js";
+import { useBackendContext } from "../context/backend.js";
+import { usePageContext } from "../context/pageState.js";
+import { ShowAccountDetails, UpdateAccountPassword } from "./AdminPage.js";
+import { LoginForm } from "./LoginForm.js";
+
+interface Props {
+  onClose: () => void;
+  onRegister: () => void;
+  onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
+}
+export function BusinessAccount({
+  onClose,
+  onLoadNotOk,
+  onRegister,
+}: Props): VNode {
+  const { i18n } = useTranslationContext();
+  const { pageStateSetter } = usePageContext();
+  const backend = useBackendContext();
+  const [updatePassword, setUpdatePassword] = useState(false);
+  function showInfoMessage(info: TranslatedString): void {
+    pageStateSetter((prev) => ({
+      ...prev,
+      info,
+    }));
+  }
+
+  if (backend.state.status === "loggedOut") {
+    return <LoginForm onRegister={onRegister} />;
+  }
+
+  if (updatePassword) {
+    return (
+      <UpdateAccountPassword
+        account={backend.state.username}
+        onLoadNotOk={onLoadNotOk}
+        onUpdateSuccess={() => {
+          showInfoMessage(i18n.str`Password changed`);
+          setUpdatePassword(false);
+        }}
+        onClear={() => {
+          setUpdatePassword(false);
+        }}
+      />
+    );
+  }
+  return (
+    <div>
+      <ShowAccountDetails
+        account={backend.state.username}
+        onLoadNotOk={onLoadNotOk}
+        onUpdateSuccess={() => {
+          showInfoMessage(i18n.str`Account updated`);
+        }}
+        onChangePassword={() => {
+          setUpdatePassword(true);
+        }}
+        onClear={onClose}
+      />
+      <section style={{ marginTop: "2em" }}>
+        <div class="active">
+          <h3>{i18n.str`Latest cashouts`}</h3>
+          <Cashouts />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git a/packages/demobank-ui/src/pages/HomePage.tsx 
b/packages/demobank-ui/src/pages/HomePage.tsx
index e60732d42..76eb8d515 100644
--- a/packages/demobank-ui/src/pages/HomePage.tsx
+++ b/packages/demobank-ui/src/pages/HomePage.tsx
@@ -50,6 +50,7 @@ export function HomePage({ onRegister }: { onRegister: () => 
void }): VNode {
   }
 
   function saveErrorAndLogout(error: PageStateType["error"]): void {
+    console.log("rrot", error);
     saveError(error);
     backend.logOut();
   }
@@ -123,6 +124,7 @@ function handleNotOkResult(
   return function handleNotOkResult2<T, E>(
     result: HttpResponsePaginated<T, E>,
   ): VNode {
+    console.log("qweqwe", JSON.stringify(result, undefined, 2));
     if (result.clientError && result.isUnauthorized) {
       onErrorHandler({
         title: i18n.str`Wrong credentials for "${account}"`,
@@ -139,7 +141,7 @@ function handleNotOkResult(
     if (!result.ok) {
       onErrorHandler({
         title: i18n.str`The backend reported a problem: HTTP status 
#${result.status}`,
-        description: `Diagnostic from ${result.info?.url.href} is 
"${result.message}"`,
+        description: `Diagnostic from ${result.info?.url} is 
"${result.message}"`,
         debug: JSON.stringify(result.error),
       });
       return <LoginForm onRegister={onRegister} />;
diff --git a/packages/demobank-ui/src/pages/Routing.tsx 
b/packages/demobank-ui/src/pages/Routing.tsx
index a88af9b0b..cff561aac 100644
--- a/packages/demobank-ui/src/pages/Routing.tsx
+++ b/packages/demobank-ui/src/pages/Routing.tsx
@@ -28,6 +28,7 @@ import { HomePage } from "./HomePage.js";
 import { BankFrame } from "./BankFrame.js";
 import { PublicHistoriesPage } from "./PublicHistoriesPage.js";
 import { RegistrationPage } from "./RegistrationPage.js";
+import { BusinessAccount } from "./BusinessAccount.js";
 
 function handleNotOkResult(
   safe: string,
@@ -96,7 +97,11 @@ export function Routing(): VNode {
       <Route
         path="/account"
         component={() => (
-          <BankFrame>
+          <BankFrame
+            goToBusinessAccount={() => {
+              route("/business");
+            }}
+          >
             <HomePage
               onRegister={() => {
                 route("/register");
@@ -105,6 +110,22 @@ export function Routing(): VNode {
           </BankFrame>
         )}
       />
+      <Route
+        path="/business"
+        component={() => (
+          <BankFrame>
+            <BusinessAccount
+              onClose={() => {
+                route("/account");
+              }}
+              onRegister={() => {
+                route("/register");
+              }}
+              onLoadNotOk={handleNotOkResult("/account", saveError, i18n)}
+            />
+          </BankFrame>
+        )}
+      />
       <Route default component={Redirect} to="/account" />
     </Router>
   );
diff --git a/packages/demobank-ui/src/scss/bank.scss 
b/packages/demobank-ui/src/scss/bank.scss
index c55dfe966..2bd5f317a 100644
--- a/packages/demobank-ui/src/scss/bank.scss
+++ b/packages/demobank-ui/src/scss/bank.scss
@@ -51,8 +51,11 @@ input[type="number"]::-webkit-inner-spin-button {
   overflow: hidden;
 }
 
-.logout {
+.top-right {
   float: right;
+}
+.some-space {
+  display: inline-block;
   border: 20px;
   margin-right: 15px;
   margin-top: 15px;
diff --git a/packages/demobank-ui/src/utils.ts 
b/packages/demobank-ui/src/utils.ts
index 0dc24e468..642b3c68d 100644
--- a/packages/demobank-ui/src/utils.ts
+++ b/packages/demobank-ui/src/utils.ts
@@ -54,8 +54,10 @@ export type PartialButDefined<T> = {
 };
 
 export type WithIntermediate<Type extends object> = {
-  [prop in keyof Type]: Type[prop] extends object ? 
WithIntermediate<Type[prop]> : (Type[prop] | undefined);
-}
+  [prop in keyof Type]: Type[prop] extends object
+    ? WithIntermediate<Type[prop]>
+    : Type[prop] | undefined;
+};
 
 // export function partialWithObjects<T extends object>(obj: T | undefined, () 
=> complete): WithIntermediate<T> {
 //   const root = obj === undefined ? {} : obj;
diff --git a/packages/merchant-backoffice-ui/src/hooks/backend.ts 
b/packages/merchant-backoffice-ui/src/hooks/backend.ts
index 952b33f7e..6c4e5c176 100644
--- a/packages/merchant-backoffice-ui/src/hooks/backend.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/backend.ts
@@ -47,8 +47,7 @@ export function useMatchMutate(): (
     const allKeys = Array.from(cache.keys());
     const keys = allKeys.filter((key) => re.test(key));
     const mutations = keys.map((key) => {
-      // console.log(key)
-      mutate(key, value, true);
+      return mutate(key, value, true);
     });
     return Promise.all(mutations);
   };
diff --git a/packages/merchant-backoffice-ui/src/hooks/instance.ts 
b/packages/merchant-backoffice-ui/src/hooks/instance.ts
index f118e1e6e..0b00936cd 100644
--- a/packages/merchant-backoffice-ui/src/hooks/instance.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/instance.ts
@@ -13,14 +13,14 @@
  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 useSWR, { useSWRConfig } from "swr";
-import { useBackendContext } from "../context/backend.js";
-import { MerchantBackend } from "../declaration.js";
 import {
-  HttpError,
   HttpResponse,
   HttpResponseOk,
+  RequestError,
 } from "@gnu-taler/web-util/lib/index.browser";
+import useSWR, { useSWRConfig } from "swr";
+import { useBackendContext } from "../context/backend.js";
+import { MerchantBackend } from "../declaration.js";
 import {
   useBackendBaseRequest,
   useBackendInstanceRequest,
@@ -188,7 +188,7 @@ export function useInstanceDetails(): HttpResponse<
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Instances.QueryInstancesResponse>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/`], fetcher, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -202,7 +202,7 @@ export function useInstanceDetails(): HttpResponse<
 
   if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
 
@@ -218,7 +218,7 @@ export function useInstanceKYCDetails(): HttpResponse<
 
   const { data, error } = useSWR<
     HttpResponseOk<MerchantBackend.Instances.AccountKycRedirects>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/kyc`], fetcher, {
     refreshInterval: 5000,
     refreshWhenHidden: false,
@@ -235,7 +235,7 @@ export function useInstanceKYCDetails(): HttpResponse<
       return { ok: true, data: { type: "redirect", status: data.data } };
     return { ok: true, data: { type: "ok" } };
   }
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
 
@@ -249,7 +249,7 @@ export function useManagedInstanceDetails(
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Instances.QueryInstancesResponse>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/management/instances/${instanceId}`], request, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -263,7 +263,7 @@ export function useManagedInstanceDetails(
 
   if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
 
@@ -275,11 +275,11 @@ export function useBackendInstances(): HttpResponse<
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Instances.InstancesResponse>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >(["/management/instances"], request);
 
   if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
diff --git a/packages/merchant-backoffice-ui/src/hooks/order.ts 
b/packages/merchant-backoffice-ui/src/hooks/order.ts
index c01f8dd83..3bcf7aaab 100644
--- a/packages/merchant-backoffice-ui/src/hooks/order.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/order.ts
@@ -13,16 +13,16 @@
  You should have received a copy of the GNU General Public License along with
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
-import { useEffect, useState } from "preact/hooks";
-import useSWR from "swr";
-import { MerchantBackend } from "../declaration.js";
-import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
 import {
-  HttpError,
   HttpResponse,
   HttpResponseOk,
   HttpResponsePaginated,
+  RequestError,
 } from "@gnu-taler/web-util/lib/index.browser";
+import { useEffect, useState } from "preact/hooks";
+import useSWR from "swr";
+import { MerchantBackend } from "../declaration.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
 import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
 
 export interface OrderAPI {
@@ -136,7 +136,7 @@ export function useOrderDetails(
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Orders.MerchantOrderStatusResponse>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/orders/${oderId}`], fetcher, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -147,7 +147,7 @@ export function useOrderDetails(
 
   if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
 
@@ -185,7 +185,7 @@ export function useInstanceOrders(
     isValidating: loadingBefore,
   } = useSWR<
     HttpResponseOk<MerchantBackend.Orders.OrderHistory>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >(
     [
       `/private/orders`,
@@ -203,7 +203,7 @@ export function useInstanceOrders(
     isValidating: loadingAfter,
   } = useSWR<
     HttpResponseOk<MerchantBackend.Orders.OrderHistory>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >(
     [
       `/private/orders`,
@@ -234,8 +234,8 @@ export function useInstanceOrders(
     if (beforeData) setLastBefore(beforeData);
   }, [afterData, beforeData]);
 
-  if (beforeError) return beforeError;
-  if (afterError) return afterError;
+  if (beforeError) return beforeError.info;
+  if (afterError) return afterError.info;
 
   // if the query returns less that we ask, then we have reach the end or 
beginning
   const isReachingEnd = afterData && afterData.data.orders.length < totalAfter;
diff --git a/packages/merchant-backoffice-ui/src/hooks/product.ts 
b/packages/merchant-backoffice-ui/src/hooks/product.ts
index 5d95a2f8f..df86f68f5 100644
--- a/packages/merchant-backoffice-ui/src/hooks/product.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/product.ts
@@ -13,13 +13,13 @@
  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 useSWR, { useSWRConfig } from "swr";
-import { MerchantBackend, WithId } from "../declaration.js";
 import {
-  HttpError,
   HttpResponse,
   HttpResponseOk,
+  RequestError,
 } from "@gnu-taler/web-util/lib/index.browser";
+import useSWR, { useSWRConfig } from "swr";
+import { MerchantBackend, WithId } from "../declaration.js";
 import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
 
 export interface ProductAPI {
@@ -96,7 +96,7 @@ export function useInstanceProducts(): HttpResponse<
 
   const { data: list, error: listError } = useSWR<
     HttpResponseOk<MerchantBackend.Products.InventorySummaryResponse>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/products`], fetcher, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -110,7 +110,7 @@ export function useInstanceProducts(): HttpResponse<
   );
   const { data: products, error: productError } = useSWR<
     HttpResponseOk<MerchantBackend.Products.ProductDetail>[],
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([paths], multiFetcher, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -119,8 +119,8 @@ export function useInstanceProducts(): HttpResponse<
     refreshWhenOffline: false,
   });
 
-  if (listError) return listError;
-  if (productError) return productError;
+  if (listError) return listError.info;
+  if (productError) return productError.info;
 
   if (products) {
     const dataWithId = products.map((d) => {
@@ -145,7 +145,7 @@ export function useProductDetails(
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Products.ProductDetail>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/products/${productId}`], fetcher, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -156,6 +156,6 @@ export function useProductDetails(
 
   if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
diff --git a/packages/merchant-backoffice-ui/src/hooks/reserves.ts 
b/packages/merchant-backoffice-ui/src/hooks/reserves.ts
index 0215f32c5..a4c0a7e55 100644
--- a/packages/merchant-backoffice-ui/src/hooks/reserves.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/reserves.ts
@@ -13,13 +13,13 @@
  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 useSWR, { useSWRConfig } from "swr";
-import { MerchantBackend } from "../declaration.js";
 import {
-  HttpError,
   HttpResponse,
   HttpResponseOk,
+  RequestError,
 } from "@gnu-taler/web-util/lib/index.browser";
+import useSWR, { useSWRConfig } from "swr";
+import { MerchantBackend } from "../declaration.js";
 import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
 
 export function useReservesAPI(): ReserveMutateAPI {
@@ -121,12 +121,12 @@ export function useInstanceReserves(): HttpResponse<
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Tips.TippingReserveStatus>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/reserves`], fetcher);
 
   if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
 
@@ -140,7 +140,7 @@ export function useReserveDetails(
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Tips.ReserveDetail>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/reserves/${reserveId}`], reserveDetailFetcher, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -151,7 +151,7 @@ export function useReserveDetails(
 
   if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
 
@@ -162,7 +162,7 @@ export function useTipDetails(
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Tips.TipDetails>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/tips/${tipId}`], tipsDetailFetcher, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -173,6 +173,6 @@ export function useTipDetails(
 
   if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
diff --git a/packages/merchant-backoffice-ui/src/hooks/templates.ts 
b/packages/merchant-backoffice-ui/src/hooks/templates.ts
index 124786887..579478537 100644
--- a/packages/merchant-backoffice-ui/src/hooks/templates.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/templates.ts
@@ -13,17 +13,17 @@
  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 { MerchantBackend } from "../declaration.js";
-import { useMatchMutate, useBackendInstanceRequest } from "./backend.js";
-import useSWR from "swr";
-import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
-import { useEffect, useState } from "preact/hooks";
 import {
-  HttpError,
   HttpResponse,
   HttpResponseOk,
   HttpResponsePaginated,
+  RequestError,
 } from "@gnu-taler/web-util/lib/index.browser";
+import { useEffect, useState } from "preact/hooks";
+import useSWR from "swr";
+import { MerchantBackend } from "../declaration.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
+import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
 
 export function useTemplateAPI(): TemplateAPI {
   const mutateAll = useMatchMutate();
@@ -148,7 +148,7 @@ export function useInstanceTemplates(
     isValidating: loadingAfter,
   } = useSWR<
     HttpResponseOk<MerchantBackend.Template.TemplateSummaryResponse>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/templates`, args?.position, -totalAfter], templateFetcher);
 
   //this will save last result
@@ -167,7 +167,7 @@ export function useInstanceTemplates(
   }, [afterData /*, beforeData*/]);
 
   // if (beforeError) return beforeError;
-  if (afterError) return afterError;
+  if (afterError) return afterError.info;
 
   // if the query returns less that we ask, then we have reach the end or 
beginning
   const isReachingEnd =
@@ -231,7 +231,7 @@ export function useTemplateDetails(
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Template.TemplateDetails>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/templates/${templateId}`], templateFetcher, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -242,6 +242,6 @@ export function useTemplateDetails(
 
   if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }
diff --git a/packages/merchant-backoffice-ui/src/hooks/transfer.ts 
b/packages/merchant-backoffice-ui/src/hooks/transfer.ts
index 6b30047e9..0f9d79f24 100644
--- a/packages/merchant-backoffice-ui/src/hooks/transfer.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/transfer.ts
@@ -13,16 +13,16 @@
  You should have received a copy of the GNU General Public License along with
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
-import { useEffect, useState } from "preact/hooks";
-import useSWR from "swr";
-import { MerchantBackend } from "../declaration.js";
-import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
 import {
-  HttpError,
   HttpResponse,
   HttpResponseOk,
   HttpResponsePaginated,
+  RequestError,
 } from "@gnu-taler/web-util/lib/index.browser";
+import { useEffect, useState } from "preact/hooks";
+import useSWR from "swr";
+import { MerchantBackend } from "../declaration.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
 import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
 
 export function useTransferAPI(): TransferAPI {
@@ -91,7 +91,7 @@ export function useInstanceTransfers(
     isValidating: loadingBefore,
   } = useSWR<
     HttpResponseOk<MerchantBackend.Transfers.TransferList>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >(
     [
       `/private/transfers`,
@@ -108,7 +108,7 @@ export function useInstanceTransfers(
     isValidating: loadingAfter,
   } = useSWR<
     HttpResponseOk<MerchantBackend.Transfers.TransferList>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >(
     [
       `/private/transfers`,
@@ -138,8 +138,8 @@ export function useInstanceTransfers(
     if (beforeData) setLastBefore(beforeData);
   }, [afterData, beforeData]);
 
-  if (beforeError) return beforeError;
-  if (afterError) return afterError;
+  if (beforeError) return beforeError.info;
+  if (afterError) return afterError.info;
 
   // if the query returns less that we ask, then we have reach the end or 
beginning
   const isReachingEnd =
diff --git a/packages/merchant-backoffice-ui/src/hooks/webhooks.ts 
b/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
index e1cd3daf2..9cf6fae03 100644
--- a/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
@@ -13,17 +13,17 @@
  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 { MerchantBackend } from "../declaration.js";
-import { useMatchMutate, useBackendInstanceRequest } from "./backend.js";
-import useSWR from "swr";
-import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
-import { useEffect, useState } from "preact/hooks";
 import {
-  HttpError,
   HttpResponse,
   HttpResponseOk,
   HttpResponsePaginated,
+  RequestError,
 } from "@gnu-taler/web-util/lib/index.browser";
+import { useEffect, useState } from "preact/hooks";
+import useSWR from "swr";
+import { MerchantBackend } from "../declaration.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
+import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
 
 export function useWebhookAPI(): WebhookAPI {
   const mutateAll = useMatchMutate();
@@ -100,7 +100,7 @@ export function useInstanceWebhooks(
     isValidating: loadingAfter,
   } = useSWR<
     HttpResponseOk<MerchantBackend.Webhooks.WebhookSummaryResponse>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/webhooks`, args?.position, -totalAfter], webhookFetcher);
 
   const [lastAfter, setLastAfter] = useState<
@@ -113,7 +113,7 @@ export function useInstanceWebhooks(
     if (afterData) setLastAfter(afterData);
   }, [afterData]);
 
-  if (afterError) return afterError;
+  if (afterError) return afterError.info;
 
   const isReachingEnd =
     afterData && afterData.data.webhooks.length < totalAfter;
@@ -157,7 +157,7 @@ export function useWebhookDetails(
 
   const { data, error, isValidating } = useSWR<
     HttpResponseOk<MerchantBackend.Webhooks.WebhookDetails>,
-    HttpError<MerchantBackend.ErrorDetail>
+    RequestError<MerchantBackend.ErrorDetail>
   >([`/private/webhooks/${webhookId}`], webhookFetcher, {
     refreshInterval: 0,
     refreshWhenHidden: false,
@@ -168,6 +168,6 @@ export function useWebhookDetails(
 
   if (isValidating) return { loading: true, data: data?.data };
   if (data) return data;
-  if (error) return error;
+  if (error) return error.info;
   return { loading: true };
 }

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