gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated (505eb07d -> caa9a22d)


From: gnunet
Subject: [taler-wallet-core] branch master updated (505eb07d -> caa9a22d)
Date: Mon, 06 Dec 2021 19:27:38 +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 505eb07d show error details in devmode
     new ce3ffbcd show error hint if its found
     new caa9a22d check timeout when doing a query to /keys to add an exchange

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:
 .../src/components/ErrorTalerOperation.tsx         |  11 +-
 .../taler-wallet-webextension/src/utils/index.ts   |  25 ++++-
 .../src/wallet/ExchangeAddPage.tsx                 |  11 +-
 .../src/wallet/ExchangeAddSetUrl.stories.tsx       |  40 ++++---
 .../src/wallet/ExchangeSetUrl.tsx                  | 118 +++++++++++++--------
 .../src/wallet/Transaction.stories.tsx             |  15 ++-
 6 files changed, 151 insertions(+), 69 deletions(-)

diff --git 
a/packages/taler-wallet-webextension/src/components/ErrorTalerOperation.tsx 
b/packages/taler-wallet-webextension/src/components/ErrorTalerOperation.tsx
index 2f50fda2..ae451dcd 100644
--- a/packages/taler-wallet-webextension/src/components/ErrorTalerOperation.tsx
+++ b/packages/taler-wallet-webextension/src/components/ErrorTalerOperation.tsx
@@ -13,7 +13,7 @@
  You should have received a copy of the GNU General Public License along with
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
-import { TalerErrorDetails } from "@gnu-taler/taler-util";
+import { TalerErrorCode, TalerErrorDetails } from "@gnu-taler/taler-util";
 import { VNode, h, Fragment } from "preact";
 import { useState } from "preact/hooks";
 import arrowDown from "../../static/img/chevron-down.svg";
@@ -29,7 +29,11 @@ export function ErrorTalerOperation({
 }): VNode | null {
   const { devMode } = useDevContext();
   const [showErrorDetail, setShowErrorDetail] = useState(false);
+  
   if (!title || !error) return null;
+  // const errorCode: number | undefined = (error.details as 
any)?.errorResponse?.code
+  const errorHint: string | undefined = (error.details as 
any)?.errorResponse?.hint
+
   return (
     <ErrorBox style={{ paddingTop: 0, paddingBottom: 0 }}>
       <div>
@@ -49,6 +53,11 @@ export function ErrorTalerOperation({
           <div style={{ padding: 5, textAlign: "left" }}>
             <div>{error.message}</div>
           </div>
+          {errorHint && 
+          <div style={{ padding: 5, textAlign: "left" }}>
+            <div>{errorHint}</div>
+          </div>
+          }
           {devMode && (
             <div style={{ textAlign: "left", overflowX: "auto" }}>
               <pre>{JSON.stringify(error, undefined, 2)}</pre>
diff --git a/packages/taler-wallet-webextension/src/utils/index.ts 
b/packages/taler-wallet-webextension/src/utils/index.ts
index 8eb89d58..88f9bc4b 100644
--- a/packages/taler-wallet-webextension/src/utils/index.ts
+++ b/packages/taler-wallet-webextension/src/utils/index.ts
@@ -43,14 +43,37 @@ export async function queryToSlashConfig<T>(
     .then(getJsonIfOk);
 }
 
+function timeout<T>(ms: number, promise: Promise<T>): Promise<T> {
+  return new Promise((resolve, reject) => {
+    const timer = setTimeout(() => {
+      reject(new Error(`Timeout: the query took longer than ${Math.floor(ms / 
1000)} secs`))
+    }, ms)
+
+    promise
+      .then(value => {
+        clearTimeout(timer)
+        resolve(value)
+      })
+      .catch(reason => {
+        clearTimeout(timer)
+        reject(reason)
+      })
+  })
+}
+
 export async function queryToSlashKeys<T>(
   url: string,
 ): Promise<T> {
-  return fetch(new URL("keys", url).href)
+  const endpoint = new URL("keys", url)
+  endpoint.searchParams.set("cacheBreaker", new Date().getTime() + "");
+
+  const query = fetch(endpoint.href)
     .catch(() => {
       throw new Error(`Network error`);
     })
     .then(getJsonIfOk);
+
+  return timeout(3000, query)
 }
 
 export function buildTermsOfServiceState(tos: GetExchangeTosResult): 
TermsState {
diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx
index 0c8336e6..6dbdf4c3 100644
--- a/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx
@@ -47,8 +47,15 @@ export function ExchangeAddPage({ onBack }: Props): VNode {
     return (
       <ExchangeSetUrlPage
         onCancel={onBack}
-        knownExchanges={knownExchanges}
-        onVerify={(url) => queryToSlashKeys(url)}
+        onVerify={async (url) => {
+          const found =
+            knownExchanges.findIndex((e) => e.exchangeBaseUrl === url) !== -1;
+
+          if (found) {
+            throw Error("This exchange is already known");
+          }
+          return queryToSlashKeys(url);
+        }}
         onConfirm={(url) =>
           queryToSlashKeys<TalerConfigResponse>(url)
             .then((config) => {
diff --git 
a/packages/taler-wallet-webextension/src/wallet/ExchangeAddSetUrl.stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/ExchangeAddSetUrl.stories.tsx
index 9ea800fe..6f0a5872 100644
--- 
a/packages/taler-wallet-webextension/src/wallet/ExchangeAddSetUrl.stories.tsx
+++ 
b/packages/taler-wallet-webextension/src/wallet/ExchangeAddSetUrl.stories.tsx
@@ -36,33 +36,39 @@ export default {
 export const ExpectedUSD = createExample(TestedComponent, {
   expectedCurrency: "USD",
   onVerify: queryToSlashKeys,
-  knownExchanges: [],
 });
 
 export const ExpectedKUDOS = createExample(TestedComponent, {
   expectedCurrency: "KUDOS",
   onVerify: queryToSlashKeys,
-  knownExchanges: [],
 });
 
 export const InitialState = createExample(TestedComponent, {
   onVerify: queryToSlashKeys,
-  knownExchanges: [],
 });
 
-export const WithDemoAsKnownExchange = createExample(TestedComponent, {
-  knownExchanges: [
-    {
-      currency: "TESTKUDOS",
-      exchangeBaseUrl: "https://exchange.demo.taler.net/";,
-      tos: {
-        currentVersion: "1",
-        acceptedVersion: "1",
-        content: "content of tos",
-        contentType: "text/plain",
-      },
-      paytoUris: [],
+const knownExchanges = [
+  {
+    currency: "TESTKUDOS",
+    exchangeBaseUrl: "https://exchange.demo.taler.net/";,
+    tos: {
+      currentVersion: "1",
+      acceptedVersion: "1",
+      content: "content of tos",
+      contentType: "text/plain",
     },
-  ],
-  onVerify: queryToSlashKeys,
+    paytoUris: [],
+  },
+];
+
+export const WithDemoAsKnownExchange = createExample(TestedComponent, {
+  onVerify: async (url) => {
+    const found =
+      knownExchanges.findIndex((e) => e.exchangeBaseUrl === url) !== -1;
+
+    if (found) {
+      throw Error("This exchange is already known");
+    }
+    return queryToSlashKeys(url);
+  },
 });
diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx 
b/packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx
index e87a8894..d529d162 100644
--- a/packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx
@@ -17,52 +17,75 @@ import {
 export interface Props {
   initialValue?: string;
   expectedCurrency?: string;
-  knownExchanges: ExchangeListItem[];
   onCancel: () => void;
   onVerify: (s: string) => Promise<TalerConfigResponse | undefined>;
   onConfirm: (url: string) => Promise<string | undefined>;
   withError?: string;
 }
 
+function useEndpointStatus<T>(
+  endpoint: string,
+  onVerify: (e: string) => Promise<T>,
+): {
+  loading: boolean;
+  error?: string;
+  endpoint: string;
+  result: T | undefined;
+  updateEndpoint: (s: string) => void;
+} {
+  const [value, setValue] = useState<string>(endpoint);
+  const [dirty, setDirty] = useState(false);
+  const [loading, setLoading] = useState(false);
+  const [result, setResult] = useState<T | undefined>(undefined);
+  const [error, setError] = useState<string | undefined>(undefined);
+
+  const [handler, setHandler] = useState<number | undefined>(undefined);
+
+  useEffect(() => {
+    if (!value) return;
+    window.clearTimeout(handler);
+    const h = window.setTimeout(async () => {
+      setDirty(true);
+      setLoading(true);
+      try {
+        const url = canonicalizeBaseUrl(value);
+        const result = await onVerify(url);
+        setResult(result);
+        setError(undefined);
+        setLoading(false);
+      } catch (e) {
+        const errorMessage =
+          e instanceof Error ? e.message : `unknown error: ${e}`;
+        setError(errorMessage);
+        setLoading(false);
+        setResult(undefined);
+      }
+    }, 500);
+    setHandler(h);
+  }, [value]);
+
+  return {
+    error: dirty ? error : undefined,
+    loading: loading,
+    result: result,
+    endpoint: value,
+    updateEndpoint: setValue,
+  };
+}
+
 export function ExchangeSetUrlPage({
   initialValue,
-  knownExchanges,
   expectedCurrency,
   onCancel,
   onVerify,
   onConfirm,
-  withError,
 }: Props) {
-  const [value, setValue] = useState<string>(initialValue || "");
-  const [dirty, setDirty] = useState(false);
-  const [result, setResult] = useState<TalerConfigResponse | undefined>(
-    undefined,
-  );
-  const [error, setError] = useState<string | undefined>(withError);
-
-  useEffect(() => {
-    try {
-      const url = canonicalizeBaseUrl(value);
+  const { loading, result, endpoint, updateEndpoint, error } =
+    useEndpointStatus(initialValue ?? "", onVerify);
 
-      const found =
-        knownExchanges.findIndex((e) => e.exchangeBaseUrl === url) !== -1;
-
-      if (found) {
-        setError("This exchange is already known");
-        return;
-      }
-      onVerify(url)
-        .then((r) => {
-          setResult(r);
-        })
-        .catch(() => {
-          setResult(undefined);
-        });
-      setDirty(true);
-    } catch {
-      setResult(undefined);
-    }
-  }, [value]);
+  const [confirmationError, setConfirmationError] = useState<
+    string | undefined
+  >(undefined);
 
   return (
     <Fragment>
@@ -72,21 +95,32 @@ export function ExchangeSetUrlPage({
         ) : (
           <h2>Add exchange for {expectedCurrency}</h2>
         )}
+        {result && expectedCurrency && expectedCurrency !== result.currency && 
(
+          <WarningBox>
+            This exchange doesn't match the expected currency{" "}
+            <b>{expectedCurrency}</b>
+          </WarningBox>
+        )}
         <ErrorMessage
           title={error && "Unable to add this exchange"}
           description={error}
         />
+        <ErrorMessage
+          title={confirmationError && "Unable to add this exchange"}
+          description={confirmationError}
+        />
         <p>
-          <Input invalid={dirty && !!error}>
+          <Input invalid={!!error}>
             <label>URL</label>
             <input
               type="text"
               placeholder="https://";
-              value={value}
-              onInput={(e) => setValue(e.currentTarget.value)}
+              value={endpoint}
+              onInput={(e) => updateEndpoint(e.currentTarget.value)}
             />
           </Input>
-          {result && (
+          {loading && <div>loading... </div>}
+          {result && !loading && (
             <Fragment>
               <Input>
                 <label>Version</label>
@@ -100,12 +134,6 @@ export function ExchangeSetUrlPage({
           )}
         </p>
       </section>
-      {result && expectedCurrency && expectedCurrency !== result.currency && (
-        <WarningBox>
-          This exchange doesn't match the expected currency{" "}
-          <b>{expectedCurrency}</b>
-        </WarningBox>
-      )}
       <footer>
         <Button onClick={onCancel}>
           <i18n.Translate>Cancel</i18n.Translate>
@@ -118,8 +146,10 @@ export function ExchangeSetUrlPage({
               expectedCurrency !== result.currency)
           }
           onClick={() => {
-            const url = canonicalizeBaseUrl(value);
-            return onConfirm(url).then((r) => (r ? setError(r) : undefined));
+            const url = canonicalizeBaseUrl(endpoint);
+            return onConfirm(url).then((r) =>
+              r ? setConfirmationError(r) : undefined,
+            );
           }}
         >
           <i18n.Translate>Next</i18n.Translate>
diff --git 
a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx 
b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
index 6f57df31..4e843392 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.stories.tsx
@@ -123,10 +123,17 @@ const exampleData = {
 };
 
 const transactionError = {
-  code: 2000,
-  details: "details",
-  hint: "this is a hint for the error",
-  message: "this is the error message with get from the app",
+  code: 7005,
+  details: {
+    requestUrl: 
"http://merchant-backend.taler:9966/orders/2021.340-02AD5XCC97MQM/pay";,
+    httpStatusCode: 410,
+    errorResponse: {
+      code: 2161,
+      hint: "The payment is too late, the offer has expired."
+    }
+  },
+  hint: "Error: WALLET_UNEXPECTED_REQUEST_ERROR",
+  message: "Unexpected error code in response",
 };
 
 export const Withdraw = createExample(TestedComponent, {

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