gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: some fixes afte testing demob


From: gnunet
Subject: [taler-wallet-core] branch master updated: some fixes afte testing demobank with ms
Date: Sat, 25 Feb 2023 23:44: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 1723f16b9 some fixes afte testing demobank with ms
1723f16b9 is described below

commit 1723f16b9c4b008e9e44578c2587c7a1bd6560b4
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Sat Feb 25 19:43:45 2023 -0300

    some fixes afte testing demobank with ms
---
 packages/demobank-ui/src/hooks/circuit.ts          |  15 +-
 packages/demobank-ui/src/pages/AccountPage.tsx     |   4 +-
 packages/demobank-ui/src/pages/AdminPage.tsx       |  45 ++--
 packages/demobank-ui/src/pages/BusinessAccount.tsx | 257 +++++++++++++++------
 packages/demobank-ui/src/pages/HomePage.tsx        |  56 ++++-
 .../src/pages/PaytoWireTransferForm.tsx            |  14 +-
 .../demobank-ui/src/pages/PublicHistoriesPage.tsx  |   4 +-
 .../demobank-ui/src/pages/RegistrationPage.tsx     |  69 ++++--
 packages/demobank-ui/src/pages/Routing.tsx         |  56 ++++-
 .../demobank-ui/src/pages/WithdrawalQRCode.tsx     |   4 +-
 .../merchant-backoffice-ui/src/InstanceRoutes.tsx  |  50 ++--
 packages/web-util/src/utils/request.ts             |  47 +++-
 12 files changed, 462 insertions(+), 159 deletions(-)

diff --git a/packages/demobank-ui/src/hooks/circuit.ts 
b/packages/demobank-ui/src/hooks/circuit.ts
index 3abe8cd54..6cf543a3c 100644
--- a/packages/demobank-ui/src/hooks/circuit.ts
+++ b/packages/demobank-ui/src/hooks/circuit.ts
@@ -33,7 +33,7 @@ const useSWR = _useSWR as unknown as SWRHook;
 export function useAdminAccountAPI(): AdminAccountAPI {
   const { request } = useAuthenticatedBackend();
   const mutateAll = useMatchMutate();
-  const { state } = useBackendContext();
+  const { state, logIn } = useBackendContext();
   if (state.status === "loggedOut") {
     throw Error("access-api can't be used when the user is not logged In");
   }
@@ -81,6 +81,13 @@ export function useAdminAccountAPI(): AdminAccountAPI {
       data,
       contentType: "json",
     });
+    if (account === state.username) {
+      await mutateAll(/.*/)
+      logIn({
+        username: account,
+        password: data.new_password
+      })
+    }
     return res;
   };
 
@@ -288,6 +295,12 @@ export function useRatiosAndFeeConfig(): HttpResponse<
     keepPreviousData: true,
   });
 
+  if (data) {
+    // data.data.ratios_and_fees.sell_out_fee = 2
+    if (!data.data.ratios_and_fees.fiat_currency) {
+      data.data.ratios_and_fees.fiat_currency = "FIAT"
+    }
+  }
   if (data) return data;
   if (error) return error.info;
   return { loading: true };
diff --git a/packages/demobank-ui/src/pages/AccountPage.tsx 
b/packages/demobank-ui/src/pages/AccountPage.tsx
index ae0c2b1f8..bd9a5acd7 100644
--- a/packages/demobank-ui/src/pages/AccountPage.tsx
+++ b/packages/demobank-ui/src/pages/AccountPage.tsx
@@ -28,7 +28,9 @@ import { PaymentOptions } from "./PaymentOptions.js";
 
 interface Props {
   account: string;
-  onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
+  onLoadNotOk: <T>(
+    error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
+  ) => VNode;
 }
 /**
  * Query account information and show QR code if there is pending withdrawal
diff --git a/packages/demobank-ui/src/pages/AdminPage.tsx 
b/packages/demobank-ui/src/pages/AdminPage.tsx
index b4ce58588..0a1dc26ec 100644
--- a/packages/demobank-ui/src/pages/AdminPage.tsx
+++ b/packages/demobank-ui/src/pages/AdminPage.tsx
@@ -59,7 +59,9 @@ function randomPassword(): string {
 }
 
 interface Props {
-  onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
+  onLoadNotOk: <T>(
+    error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
+  ) => VNode;
 }
 /**
  * Query account information and show QR code if there is pending withdrawal
@@ -109,6 +111,11 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
   if (showCashouts) {
     return (
       <div>
+        <div>
+          <h1 class="nav welcome-text">
+            <i18n.Translate>Cashout for account {showCashouts}</i18n.Translate>
+          </h1>
+        </div>
         <Cashouts
           account={showCashouts}
           onSelected={(id) => {
@@ -116,15 +123,17 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
             setShowCashouts(undefined);
           }}
         />
-        <input
-          class="pure-button"
-          type="submit"
-          value={i18n.str`Close`}
-          onClick={async (e) => {
-            e.preventDefault();
-            setShowCashouts(undefined);
-          }}
-        />
+        <p>
+          <input
+            class="pure-button"
+            type="submit"
+            value={i18n.str`Close`}
+            onClick={async (e) => {
+              e.preventDefault();
+              setShowCashouts(undefined);
+            }}
+          />
+        </p>
       </div>
     );
   }
@@ -184,7 +193,7 @@ export function AdminPage({ onLoadNotOk }: Props): VNode {
         onClose={() => setCreateAccount(false)}
         onCreateSuccess={(password) => {
           showInfoMessage(
-            i18n.str`Account created with password "${password}"`,
+            i18n.str`Account created with password "${password}". The user 
must change the password on the next login.`,
           );
           setCreateAccount(false);
         }}
@@ -326,7 +335,9 @@ export function UpdateAccountPassword({
   onUpdateSuccess,
   onLoadNotOk,
 }: {
-  onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
+  onLoadNotOk: <T>(
+    error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
+  ) => VNode;
   onClear: () => void;
   onUpdateSuccess: () => void;
   account: string;
@@ -521,7 +532,9 @@ export function ShowAccountDetails({
   onLoadNotOk,
   onChangePassword,
 }: {
-  onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
+  onLoadNotOk: <T>(
+    error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
+  ) => VNode;
   onClear?: () => void;
   onChangePassword: () => void;
   onUpdateSuccess: () => void;
@@ -628,7 +641,9 @@ function RemoveAccount({
   onUpdateSuccess,
   onLoadNotOk,
 }: {
-  onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
+  onLoadNotOk: <T>(
+    error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
+  ) => VNode;
   onClear: () => void;
   onUpdateSuccess: () => void;
   account: string;
@@ -806,7 +821,7 @@ function AccountForm({
         />
       </fieldset>
       <fieldset>
-        <label>{i18n.str`IBAN`}</label>
+        <label>{i18n.str`Internal IBAN`}</label>
         <input
           disabled={purpose !== "create"}
           value={form.iban ?? ""}
diff --git a/packages/demobank-ui/src/pages/BusinessAccount.tsx 
b/packages/demobank-ui/src/pages/BusinessAccount.tsx
index 23a03cc9b..6278fe08b 100644
--- a/packages/demobank-ui/src/pages/BusinessAccount.tsx
+++ b/packages/demobank-ui/src/pages/BusinessAccount.tsx
@@ -20,6 +20,7 @@ import {
   TranslatedString,
 } from "@gnu-taler/taler-util";
 import {
+  ErrorType,
   HttpResponsePaginated,
   RequestError,
   useTranslationContext,
@@ -44,7 +45,9 @@ import { ShowInputErrorLabel } from 
"./ShowInputErrorLabel.js";
 interface Props {
   onClose: () => void;
   onRegister: () => void;
-  onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
+  onLoadNotOk: <T>(
+    error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
+  ) => VNode;
 }
 export function BusinessAccount({
   onClose,
@@ -79,6 +82,9 @@ export function BusinessAccount({
           setNewcashout(false);
         }}
         onComplete={(id) => {
+          showInfoMessage(
+            i18n.str`Cashout created. You need to confirm the operation to 
complete the transaction.`,
+          );
           setNewcashout(false);
           setShowCashoutDetails(id);
         }}
@@ -156,7 +162,9 @@ interface PropsCashout {
   account: string;
   onComplete: (id: string) => void;
   onCancel: () => void;
-  onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
+  onLoadNotOk: <T>(
+    error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
+  ) => VNode;
 }
 
 type FormType = {
@@ -180,7 +188,7 @@ function CreateCashout({
   const result = useAccountDetails(account);
   const [error, saveError] = useState<ErrorMessage | undefined>();
 
-  const [form, setForm] = useState<Partial<FormType>>({});
+  const [form, setForm] = useState<Partial<FormType>>({ isDebit: true });
 
   const { createCashout } = useCircuitAccountAPI();
   if (!result.ok) return onLoadNotOk(result);
@@ -277,10 +285,14 @@ function CreateCashout({
               type="text"
               readonly
               class="currency-indicator"
-              size={balance.currency.length}
-              maxLength={balance.currency.length}
+              size={
+                !form.isDebit ? fiatCurrency.length : balance.currency.length
+              }
+              maxLength={
+                !form.isDebit ? fiatCurrency.length : balance.currency.length
+              }
               tabIndex={-1}
-              value={balance.currency}
+              value={!form.isDebit ? fiatCurrency : balance.currency}
             />
             &nbsp;
             <input
@@ -389,16 +401,16 @@ function CreateCashout({
         {Amounts.isZero(sellFee) ? undefined : (
           <Fragment>
             <fieldset>
-              <label>{i18n.str`Transfer before fee`}</label>
+              <label>{i18n.str`Amount after conversion`}</label>
               <div style={{ width: "max-content" }}>
                 <input
                   type="text"
                   readonly
                   class="currency-indicator"
-                  size={balance.currency.length}
-                  maxLength={balance.currency.length}
+                  size={fiatCurrency.length}
+                  maxLength={fiatCurrency.length}
                   tabIndex={-1}
-                  value={balance.currency}
+                  value={fiatCurrency}
                 />
                 &nbsp;
                 <input
@@ -417,10 +429,10 @@ function CreateCashout({
                   type="text"
                   readonly
                   class="currency-indicator"
-                  size={balance.currency.length}
-                  maxLength={balance.currency.length}
+                  size={fiatCurrency.length}
+                  maxLength={fiatCurrency.length}
                   tabIndex={-1}
-                  value={balance.currency}
+                  value={fiatCurrency}
                 />
                 &nbsp;
                 <input
@@ -442,10 +454,10 @@ function CreateCashout({
               type="text"
               readonly
               class="currency-indicator"
-              size={balance.currency.length}
-              maxLength={balance.currency.length}
+              size={fiatCurrency.length}
+              maxLength={fiatCurrency.length}
               tabIndex={-1}
-              value={balance.currency}
+              value={fiatCurrency}
             />
             &nbsp;
             <input
@@ -543,34 +555,69 @@ function CreateCashout({
                 onComplete(res.data.uuid);
               } catch (error) {
                 if (error instanceof RequestError) {
-                  const errorData: SandboxBackend.SandboxError =
-                    error.info.error;
-                  if (error.info.status === HttpStatusCode.PreconditionFailed) 
{
-                    saveError({
-                      title: i18n.str`The account does not have sufficient 
funds`,
-                      description: errorData.error.description,
-                      debug: JSON.stringify(error.info),
-                    });
-                  } else if (
-                    error.info.status === HttpStatusCode.ServiceUnavailable
-                  ) {
-                    saveError({
-                      title: i18n.str`The bank does not support the TAN 
channel for this operation`,
-                      description: errorData.error.description,
-                      debug: JSON.stringify(error.info),
-                    });
-                  } else if (error.info.status === HttpStatusCode.Conflict) {
-                    saveError({
-                      title: i18n.str`No contact information for this channel`,
-                      description: errorData.error.description,
-                      debug: JSON.stringify(error.info),
-                    });
-                  } else {
-                    saveError({
-                      title: i18n.str`New cashout gave response error`,
-                      description: errorData.error.description,
-                      debug: JSON.stringify(error.info),
-                    });
+                  const e = error as RequestError<SandboxBackend.SandboxError>;
+                  switch (e.cause.type) {
+                    case ErrorType.TIMEOUT: {
+                      saveError({
+                        title: i18n.str`Request timeout, try again later.`,
+                      });
+                      break;
+                    }
+                    case ErrorType.CLIENT: {
+                      const errorData = e.cause.error;
+
+                      if (
+                        e.cause.status === HttpStatusCode.PreconditionFailed
+                      ) {
+                        saveError({
+                          title: i18n.str`The account does not have sufficient 
funds`,
+                          description: errorData.error.description,
+                          debug: JSON.stringify(error.info),
+                        });
+                      } else if (e.cause.status === HttpStatusCode.Conflict) {
+                        saveError({
+                          title: i18n.str`No contact information for this 
channel`,
+                          description: errorData.error.description,
+                          debug: JSON.stringify(error.info),
+                        });
+                      } else {
+                        saveError({
+                          title: i18n.str`New cashout gave response error`,
+                          description: errorData.error.description,
+                          debug: JSON.stringify(error.info),
+                        });
+                      }
+                      break;
+                    }
+                    case ErrorType.SERVER: {
+                      const errorData = e.cause.error;
+                      if (
+                        e.cause.status === HttpStatusCode.ServiceUnavailable
+                      ) {
+                        saveError({
+                          title: i18n.str`The bank does not support the TAN 
channel for this operation`,
+                          description: errorData.error.description,
+                          debug: JSON.stringify(error.info),
+                        });
+                      } else {
+                        saveError({
+                          title: i18n.str`Creating cashout returned with a 
server error`,
+                          description: errorData.error.description,
+                          debug: JSON.stringify(error.cause),
+                        });
+                      }
+                      break;
+                    }
+                    case ErrorType.UNEXPECTED: {
+                      saveError({
+                        title: i18n.str`Unexpected error trying to create 
cashout.`,
+                        debug: JSON.stringify(error.cause),
+                      });
+                      break;
+                    }
+                    default: {
+                      assertUnreachable(e.cause);
+                    }
                   }
                 } else if (error instanceof Error) {
                   saveError({
@@ -592,7 +639,9 @@ function CreateCashout({
 interface ShowCashoutProps {
   id: string;
   onCancel: () => void;
-  onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
+  onLoadNotOk: <T>(
+    error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
+  ) => VNode;
 }
 export function ShowCashoutDetails({
   id,
@@ -699,22 +748,59 @@ export function ShowCashoutDetails({
                   onCancel();
                 } catch (error) {
                   if (error instanceof RequestError) {
-                    const errorData: SandboxBackend.SandboxError =
-                      error.info.error;
-                    if (
-                      error.info.status === HttpStatusCode.PreconditionFailed
-                    ) {
-                      saveError({
-                        title: i18n.str`Cashout was already aborted`,
-                        description: errorData.error.description,
-                        debug: JSON.stringify(error.info),
-                      });
-                    } else {
-                      saveError({
-                        title: i18n.str`Aborting cashout gave response error`,
-                        description: errorData.error.description,
-                        debug: JSON.stringify(error.info),
-                      });
+                    const e =
+                      error as RequestError<SandboxBackend.SandboxError>;
+                    switch (e.cause.type) {
+                      case ErrorType.TIMEOUT: {
+                        saveError({
+                          title: i18n.str`Request timeout, try again later.`,
+                        });
+                        break;
+                      }
+                      case ErrorType.CLIENT: {
+                        const errorData = e.cause.error;
+                        if (
+                          e.cause.status === HttpStatusCode.PreconditionFailed
+                        ) {
+                          saveError({
+                            title: i18n.str`Cashout was already aborted`,
+                            description: errorData.error.description,
+                            debug: JSON.stringify(error.info),
+                          });
+                        } else {
+                          saveError({
+                            title: i18n.str`Aborting cashout gave response 
error`,
+                            description: errorData.error.description,
+                            debug: JSON.stringify(error.info),
+                          });
+                        }
+
+                        saveError({
+                          title: i18n.str`Aborting cashout gave response 
error`,
+                          description: errorData.error.description,
+                          debug: JSON.stringify(error.cause),
+                        });
+                        break;
+                      }
+                      case ErrorType.SERVER: {
+                        const errorData = e.cause.error;
+                        saveError({
+                          title: i18n.str`Aborting cashout returned with a 
server error`,
+                          description: errorData.error.description,
+                          debug: JSON.stringify(error.cause),
+                        });
+                        break;
+                      }
+                      case ErrorType.UNEXPECTED: {
+                        saveError({
+                          title: i18n.str`Unexpected error trying to abort 
cashout.`,
+                          debug: JSON.stringify(error.cause),
+                        });
+                        break;
+                      }
+                      default: {
+                        assertUnreachable(e.cause);
+                      }
                     }
                   } else if (error instanceof Error) {
                     saveError({
@@ -741,13 +827,44 @@ export function ShowCashoutDetails({
                   });
                 } catch (error) {
                   if (error instanceof RequestError) {
-                    const errorData: SandboxBackend.SandboxError =
-                      error.info.error;
-                    saveError({
-                      title: i18n.str`Confirmation of cashout gave response 
error`,
-                      description: errorData.error.description,
-                      debug: JSON.stringify(error.info),
-                    });
+                    const e =
+                      error as RequestError<SandboxBackend.SandboxError>;
+                    switch (e.cause.type) {
+                      case ErrorType.TIMEOUT: {
+                        saveError({
+                          title: i18n.str`Request timeout, try again later.`,
+                        });
+                        break;
+                      }
+                      case ErrorType.CLIENT: {
+                        const errorData = e.cause.error;
+                        saveError({
+                          title: i18n.str`Confirmation of cashout gave 
response error`,
+                          description: errorData.error.description,
+                          debug: JSON.stringify(error.cause),
+                        });
+                        break;
+                      }
+                      case ErrorType.SERVER: {
+                        const errorData = e.cause.error;
+                        saveError({
+                          title: i18n.str`Confirmation of cashout gave 
response error`,
+                          description: errorData.error.description,
+                          debug: JSON.stringify(error.cause),
+                        });
+                        break;
+                      }
+                      case ErrorType.UNEXPECTED: {
+                        saveError({
+                          title: i18n.str`Unexpected error trying to cashout.`,
+                          debug: JSON.stringify(error.cause),
+                        });
+                        break;
+                      }
+                      default: {
+                        assertUnreachable(e.cause);
+                      }
+                    }
                   } else if (error instanceof Error) {
                     saveError({
                       title: i18n.str`Confirmation failed, please report`,
@@ -767,3 +884,7 @@ export function ShowCashoutDetails({
     </div>
   );
 }
+
+export function assertUnreachable(x: never): never {
+  throw new Error("Didn't expect to get here");
+}
diff --git a/packages/demobank-ui/src/pages/HomePage.tsx 
b/packages/demobank-ui/src/pages/HomePage.tsx
index 5af195f48..a360bd64c 100644
--- a/packages/demobank-ui/src/pages/HomePage.tsx
+++ b/packages/demobank-ui/src/pages/HomePage.tsx
@@ -14,9 +14,11 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
-import { Logger } from "@gnu-taler/taler-util";
+import { HttpStatusCode, Logger } from "@gnu-taler/taler-util";
 import {
+  ErrorType,
   HttpResponsePaginated,
+  RequestError,
   useTranslationContext,
 } from "@gnu-taler/web-util/lib/index.browser";
 import { Fragment, h, VNode } from "preact";
@@ -119,9 +121,9 @@ function handleNotOkResult(
   onErrorHandler: (state: PageStateType["error"]) => void,
   i18n: ReturnType<typeof useTranslationContext>["i18n"],
   onRegister: () => void,
-): <T, E>(result: HttpResponsePaginated<T, E>) => VNode {
-  return function handleNotOkResult2<T, E>(
-    result: HttpResponsePaginated<T, E>,
+): <T>(result: HttpResponsePaginated<T, SandboxBackend.SandboxError>) => VNode 
{
+  return function handleNotOkResult2<T>(
+    result: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
   ): VNode {
     if (result.clientError && result.isUnauthorized) {
       onErrorHandler({
@@ -137,13 +139,49 @@ function handleNotOkResult(
     }
     if (result.loading) return <Loading />;
     if (!result.ok) {
-      onErrorHandler({
-        title: i18n.str`The backend reported a problem: HTTP status 
#${result.status}`,
-        description: `Diagnostic from ${result.info?.url} is 
"${result.message}"`,
-        debug: JSON.stringify(result.error),
-      });
+      switch (result.type) {
+        case ErrorType.TIMEOUT: {
+          onErrorHandler({
+            title: i18n.str`Request timeout, try again later.`,
+          });
+          break;
+        }
+        case ErrorType.CLIENT: {
+          const errorData = result.error;
+          onErrorHandler({
+            title: i18n.str`Could not load due to a client error`,
+            description: errorData.error.description,
+            debug: JSON.stringify(result),
+          });
+          break;
+        }
+        case ErrorType.SERVER: {
+          const errorData = result.error;
+          onErrorHandler({
+            title: i18n.str`Server returned with error`,
+            description: errorData.error.description,
+            debug: JSON.stringify(result),
+          });
+          break;
+        }
+        case ErrorType.UNEXPECTED: {
+          onErrorHandler({
+            title: i18n.str`Unexpected error.`,
+            description: `Diagnostic from ${result.info?.url} is 
"${result.message}"`,
+            debug: JSON.stringify(result.error),
+          });
+          break;
+        }
+        default: {
+          assertUnreachable(result);
+        }
+      }
+
       return <LoginForm onRegister={onRegister} />;
     }
     return <div />;
   };
 }
+export function assertUnreachable(x: never): never {
+  throw new Error("Didn't expect to get here");
+}
diff --git a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx 
b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
index d859b1cc7..07b011a00 100644
--- a/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
+++ b/packages/demobank-ui/src/pages/PaytoWireTransferForm.tsx
@@ -48,7 +48,7 @@ export function PaytoWireTransferForm({
   onSuccess: () => void;
   currency: string;
 }): VNode {
-  const backend = useBackendContext();
+  // const backend = useBackendContext();
   // const { pageState, pageStateSetter } = usePageContext(); // NOTE: used 
for go-back button?
 
   const [isRawPayto, setIsRawPayto] = useState(false);
@@ -188,17 +188,7 @@ export function PaytoWireTransferForm({
                   paytoUri,
                   amount: `${currency}:${amount}`,
                 });
-                // return await createTransactionCall(
-                //   transactionData,
-                //   backend.state,
-                //   pageStateSetter,
-                //   () => {
-                //     setAmount(undefined);
-                //     setIban(undefined);
-                //     setSubject(undefined);
-                //   },
-                //   i18n,
-                // );
+                onSuccess();
               }}
             />
             <input
diff --git a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx 
b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
index 54a77b42a..2b5f7e26c 100644
--- a/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
+++ b/packages/demobank-ui/src/pages/PublicHistoriesPage.tsx
@@ -36,7 +36,9 @@ const logger = new Logger("PublicHistoriesPage");
 // }
 
 interface Props {
-  onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
+  onLoadNotOk: <T>(
+    error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
+  ) => VNode;
 }
 
 /**
diff --git a/packages/demobank-ui/src/pages/RegistrationPage.tsx 
b/packages/demobank-ui/src/pages/RegistrationPage.tsx
index 247ef8d80..c6bc3c327 100644
--- a/packages/demobank-ui/src/pages/RegistrationPage.tsx
+++ b/packages/demobank-ui/src/pages/RegistrationPage.tsx
@@ -15,6 +15,7 @@
  */
 import { HttpStatusCode, Logger } from "@gnu-taler/taler-util";
 import {
+  ErrorType,
   RequestError,
   useTranslationContext,
 } from "@gnu-taler/web-util/lib/index.browser";
@@ -176,26 +177,52 @@ function RegistrationForm({
                     onComplete();
                   } catch (error) {
                     if (error instanceof RequestError) {
-                      const errorData: SandboxBackend.SandboxError =
-                        error.info.error;
-                      if (error.info.status === HttpStatusCode.Conflict) {
-                        onError({
-                          title: i18n.str`That username is already taken`,
-                          description: errorData.error.description,
-                          debug: JSON.stringify(error.info),
-                        });
-                      } else {
-                        onError({
-                          title: i18n.str`New registration gave response 
error`,
-                          description: errorData.error.description,
-                          debug: JSON.stringify(error.info),
-                        });
+                      const e =
+                        error as RequestError<SandboxBackend.SandboxError>;
+                      switch (e.cause.type) {
+                        case ErrorType.TIMEOUT: {
+                          onError({
+                            title: i18n.str`Request timeout, try again later.`,
+                          });
+                          break;
+                        }
+                        case ErrorType.CLIENT: {
+                          const errorData = e.cause.error;
+                          if (e.cause.status === HttpStatusCode.Conflict) {
+                            onError({
+                              title: i18n.str`That username is already taken`,
+                              description: errorData.error.description,
+                              debug: JSON.stringify(error.cause),
+                            });
+                          } else {
+                            onError({
+                              title: i18n.str`New registration gave response 
error`,
+                              description: errorData.error.description,
+                              debug: JSON.stringify(error.cause),
+                            });
+                          }
+                          break;
+                        }
+                        case ErrorType.SERVER: {
+                          const errorData = e.cause.error;
+                          onError({
+                            title: i18n.str`New registration gave response 
error`,
+                            description: errorData?.error?.description,
+                            debug: JSON.stringify(error.cause),
+                          });
+                          break;
+                        }
+                        case ErrorType.UNEXPECTED: {
+                          onError({
+                            title: i18n.str`Unexpected error doing the 
registration.`,
+                            debug: JSON.stringify(error.cause),
+                          });
+                          break;
+                        }
+                        default: {
+                          assertUnreachable(e.cause);
+                        }
                       }
-                    } else if (error instanceof Error) {
-                      onError({
-                        title: i18n.str`Registration failed, please report`,
-                        description: error.message,
-                      });
                     }
                   }
                 }}
@@ -222,3 +249,7 @@ function RegistrationForm({
     </Fragment>
   );
 }
+
+export function assertUnreachable(x: never): never {
+  throw new Error("Didn't expect to get here");
+}
diff --git a/packages/demobank-ui/src/pages/Routing.tsx 
b/packages/demobank-ui/src/pages/Routing.tsx
index 48f226574..8234d8988 100644
--- a/packages/demobank-ui/src/pages/Routing.tsx
+++ b/packages/demobank-ui/src/pages/Routing.tsx
@@ -15,6 +15,7 @@
  */
 
 import {
+  ErrorType,
   HttpResponsePaginated,
   useTranslationContext,
 } from "@gnu-taler/web-util/lib/index.browser";
@@ -34,9 +35,9 @@ function handleNotOkResult(
   safe: string,
   saveError: (state: PageStateType["error"]) => void,
   i18n: ReturnType<typeof useTranslationContext>["i18n"],
-): <T, E>(result: HttpResponsePaginated<T, E>) => VNode {
-  return function handleNotOkResult2<T, E>(
-    result: HttpResponsePaginated<T, E>,
+): <T>(result: HttpResponsePaginated<T, SandboxBackend.SandboxError>) => VNode 
{
+  return function handleNotOkResult2<T>(
+    result: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
   ): VNode {
     if (result.clientError && result.isUnauthorized) {
       route(safe);
@@ -50,12 +51,45 @@ function handleNotOkResult(
     }
     if (result.loading) return <Loading />;
     if (!result.ok) {
-      saveError({
-        title: i18n.str`The backend reported a problem: HTTP status 
#${result.status}`,
-        description: i18n.str`Diagnostic from ${result.info?.url} is 
"${result.message}"`,
-        debug: JSON.stringify(result.error),
-      });
-      route(safe);
+      switch (result.type) {
+        case ErrorType.TIMEOUT: {
+          saveError({
+            title: i18n.str`Request timeout, try again later.`,
+          });
+          break;
+        }
+        case ErrorType.CLIENT: {
+          const errorData = result.error;
+          saveError({
+            title: i18n.str`Could not load due to a client error`,
+            description: errorData.error.description,
+            debug: JSON.stringify(result),
+          });
+          break;
+        }
+        case ErrorType.SERVER: {
+          const errorData = result.error;
+          saveError({
+            title: i18n.str`Server returned with error`,
+            description: errorData.error.description,
+            debug: JSON.stringify(result),
+          });
+          break;
+        }
+        case ErrorType.UNEXPECTED: {
+          saveError({
+            title: i18n.str`Unexpected error.`,
+            description: `Diagnostic from ${result.info?.url} is 
"${result.message}"`,
+            debug: JSON.stringify(result.error),
+          });
+          break;
+        }
+        default:
+          {
+            assertUnreachable(result);
+          }
+          route(safe);
+      }
     }
     return <div />;
   };
@@ -137,3 +171,7 @@ function Redirect({ to }: { to: string }): VNode {
   }, []);
   return <div>being redirected to {to}</div>;
 }
+
+export function assertUnreachable(x: never): never {
+  throw new Error("Didn't expect to get here");
+}
diff --git a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx 
b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
index fd91c0e1a..d4c95d830 100644
--- a/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
+++ b/packages/demobank-ui/src/pages/WithdrawalQRCode.tsx
@@ -33,7 +33,9 @@ interface Props {
   withdrawalId: string;
   talerWithdrawUri: string;
   onAbort: () => void;
-  onLoadNotOk: <T, E>(error: HttpResponsePaginated<T, E>) => VNode;
+  onLoadNotOk: <T>(
+    error: HttpResponsePaginated<T, SandboxBackend.SandboxError>,
+  ) => VNode;
 }
 /**
  * Offer the QR code (and a clickable taler://-link) to
diff --git a/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx 
b/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx
index 5929b031a..e31ff4513 100644
--- a/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx
+++ b/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx
@@ -22,6 +22,7 @@
 import {
   useTranslationContext,
   HttpError,
+  ErrorType,
 } from "@gnu-taler/web-util/lib/index.browser";
 import { format } from "date-fns";
 import { Fragment, FunctionComponent, h, VNode } from "preact";
@@ -163,16 +164,25 @@ export function InstanceRoutes({
     return function ServerErrorRedirectToImpl(
       error: HttpError<MerchantBackend.ErrorDetail>,
     ) {
-      setGlobalNotification({
-        message: i18n.str`The backend reported a problem: HTTP status 
#${error.status}`,
-        description: i18n.str`Diagnostic from ${error.info?.url} is 
"${error.message}"`,
-        details:
-          error.clientError || error.serverError
-            ? error.error?.detail
-            : undefined,
-        type: "ERROR",
-        to,
-      });
+      if (error.type === ErrorType.TIMEOUT) {
+        setGlobalNotification({
+          message: i18n.str`The request to the backend take too long and was 
cancelled`,
+          description: i18n.str`Diagnostic from ${error.info?.url} is 
"${error.message}"`,
+          type: "ERROR",
+          to,
+        });
+      } else {
+        setGlobalNotification({
+          message: i18n.str`The backend reported a problem: HTTP status 
#${error.status}`,
+          description: i18n.str`Diagnostic from ${error.info?.url} is 
"${error.message}"`,
+          details:
+            error.clientError || error.serverError
+              ? error.error?.detail
+              : undefined,
+          type: "ERROR",
+          to,
+        });
+      }
       return <Redirect to={to} />;
     };
   }
@@ -572,19 +582,25 @@ function AdminInstanceUpdatePage({
         {...rest}
         instanceId={id}
         onLoadError={(error: HttpError<MerchantBackend.ErrorDetail>) => {
-          return (
-            <Fragment>
-              <NotificationCard
-                notification={{
+          const notif =
+            error.type === ErrorType.TIMEOUT
+              ? {
+                  message: i18n.str`The request to the backend take too long 
and was cancelled`,
+                  description: i18n.str`Diagnostic from ${error.info?.url} is 
"${error.message}"`,
+                  type: "ERROR" as const,
+                }
+              : {
                   message: i18n.str`The backend reported a problem: HTTP 
status #${error.status}`,
                   description: i18n.str`Diagnostic from ${error.info?.url} is 
"${error.message}"`,
                   details:
                     error.clientError || error.serverError
                       ? error.error?.detail
                       : undefined,
-                  type: "ERROR",
-                }}
-              />
+                  type: "ERROR" as const,
+                };
+          return (
+            <Fragment>
+              <NotificationCard notification={notif} />
               <LoginPage onConfirm={updateLoginStatus} />
             </Fragment>
           );
diff --git a/packages/web-util/src/utils/request.ts 
b/packages/web-util/src/utils/request.ts
index 24342bb80..3d91024dc 100644
--- a/packages/web-util/src/utils/request.ts
+++ b/packages/web-util/src/utils/request.ts
@@ -17,6 +17,10 @@
 import { HttpStatusCode } from "@gnu-taler/taler-util";
 import { base64encode } from "./base64.js";
 
+export enum ErrorType {
+  CLIENT, SERVER, TIMEOUT, UNEXPECTED
+}
+
 /**
  * 
  * @param baseUrl URL where the service is located
@@ -39,7 +43,7 @@ export async function defaultRequestHandler<T>(
 
   const requestMethod = options?.method ?? "GET";
   const requestBody = options?.data;
-  const requestTimeout = options?.timeout ?? 2 * 1000;
+  const requestTimeout = options?.timeout ?? 5 * 1000;
   const requestParams = options.params ?? {};
 
   const _url = new URL(`${baseUrl}${endpoint}`);
@@ -85,10 +89,13 @@ export async function defaultRequestHandler<T>(
       hasToken: !!options.token,
       status: 0,
     };
-    const error: HttpResponseUnexpectedError = {
+    const error: HttpRequestTimeoutError = {
+      clientError: true,
+      isNotfound: false,
+      isUnauthorized: false,
+      error: undefined,
       info,
-      status: 0,
-      error: ex,
+      type: ErrorType.TIMEOUT,
       message: "Request timeout",
     };
     throw new RequestError(error);
@@ -166,32 +173,50 @@ export interface WithPagination {
 }
 
 export type HttpError<ErrorDetail> =
+  | HttpRequestTimeoutError
   | HttpResponseClientError<ErrorDetail>
   | HttpResponseServerError<ErrorDetail>
   | HttpResponseUnexpectedError;
 
+
 export interface HttpResponseServerError<ErrorDetail> {
   ok?: false;
   loading?: false;
   clientError?: false;
   serverError: true;
+  type: ErrorType.SERVER,
 
-  error?: ErrorDetail;
+  error: ErrorDetail;
   status: HttpStatusCode;
   message: string;
   info?: RequestInfo;
 }
+interface HttpRequestTimeoutError {
+  ok?: false;
+  loading?: false;
+  clientError: true;
+  serverError?: false;
+  type: ErrorType.TIMEOUT,
+
+  info?: RequestInfo;
+  error: undefined,
+
+  isUnauthorized: false;
+  isNotfound: false;
+  message: string;
+}
 interface HttpResponseClientError<ErrorDetail> {
   ok?: false;
   loading?: false;
   clientError: true;
   serverError?: false;
+  type: ErrorType.CLIENT,
 
   info?: RequestInfo;
   isUnauthorized: boolean;
   isNotfound: boolean;
   status: HttpStatusCode;
-  error?: ErrorDetail;
+  error: ErrorDetail;
   message: string;
 }
 
@@ -200,6 +225,7 @@ interface HttpResponseUnexpectedError {
   loading?: false;
   clientError?: false;
   serverError?: false;
+  type: ErrorType.UNEXPECTED,
 
   info?: RequestInfo;
   status?: HttpStatusCode;
@@ -208,10 +234,15 @@ interface HttpResponseUnexpectedError {
 }
 
 export class RequestError<ErrorDetail> extends Error {
+  /**
+   * @deprecated use cause
+   */
   info: HttpError<ErrorDetail>;
+  cause: HttpError<ErrorDetail>;
   constructor(d: HttpError<ErrorDetail>) {
     super(d.message)
     this.info = d
+    this.cause = d
   }
 }
 
@@ -277,6 +308,7 @@ async function buildRequestFailed<ErrorDetail>(
         clientError: true,
         isNotfound: status === 404,
         isUnauthorized: status === 401,
+        type: ErrorType.CLIENT,
         status,
         info,
         message: data?.hint,
@@ -287,6 +319,7 @@ async function buildRequestFailed<ErrorDetail>(
     if (status && status >= 500 && status < 600) {
       const error: HttpResponseServerError<ErrorDetail> = {
         serverError: true,
+        type: ErrorType.SERVER,
         status,
         info,
         message: `${data?.hint} (code ${data?.code})`,
@@ -296,6 +329,7 @@ async function buildRequestFailed<ErrorDetail>(
     }
     return {
       info,
+      type: ErrorType.UNEXPECTED,
       status,
       error: {},
       message: "NOT DEFINED",
@@ -304,6 +338,7 @@ async function buildRequestFailed<ErrorDetail>(
     const error: HttpResponseUnexpectedError = {
       info,
       status,
+      type: ErrorType.UNEXPECTED,
       error: ex,
       message: "NOT DEFINED",
     };

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