From 5d23eb36354d07508a015531f298b3e261bbafce Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Tue, 22 Mar 2022 21:16:38 +0100 Subject: wallet: improve error handling and error codes --- .../src/browserHttpLib.ts | 22 +++---- .../src/components/ErrorTalerOperation.tsx | 6 +- .../taler-wallet-webextension/src/cta/Deposit.tsx | 14 ++--- packages/taler-wallet-webextension/src/cta/Pay.tsx | 4 +- .../taler-wallet-webextension/src/cta/Withdraw.tsx | 13 ++-- .../src/hooks/useAsyncAsHook.ts | 30 ++++++--- .../src/serviceWorkerHttpLib.ts | 18 +++--- packages/taler-wallet-webextension/src/wxApi.ts | 73 ++++++++++++++++------ .../taler-wallet-webextension/src/wxBackend.ts | 11 ++-- 9 files changed, 120 insertions(+), 71 deletions(-) (limited to 'packages/taler-wallet-webextension') diff --git a/packages/taler-wallet-webextension/src/browserHttpLib.ts b/packages/taler-wallet-webextension/src/browserHttpLib.ts index 8877edfc3..53ab85598 100644 --- a/packages/taler-wallet-webextension/src/browserHttpLib.ts +++ b/packages/taler-wallet-webextension/src/browserHttpLib.ts @@ -18,11 +18,11 @@ * Imports. */ import { - OperationFailedError, HttpRequestLibrary, HttpRequestOptions, HttpResponse, Headers, + TalerError, } from "@gnu-taler/taler-wallet-core"; import { Logger, @@ -49,14 +49,14 @@ export class BrowserHttpLib implements HttpRequestLibrary { if (this.throttlingEnabled && this.throttle.applyThrottle(requestUrl)) { const parsedUrl = new URL(requestUrl); - throw OperationFailedError.fromCode( + throw TalerError.fromDetail( TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED, - `request to origin ${parsedUrl.origin} was throttled`, { requestMethod, requestUrl, throttleStats: this.throttle.getThrottleStats(requestUrl), }, + `request to origin ${parsedUrl.origin} was throttled`, ); } @@ -78,12 +78,12 @@ export class BrowserHttpLib implements HttpRequestLibrary { myRequest.onerror = (e) => { logger.error("http request error"); reject( - OperationFailedError.fromCode( + TalerError.fromDetail( TalerErrorCode.WALLET_NETWORK_ERROR, - "Could not make request", { requestUrl: requestUrl, }, + "Could not make request", ), ); }; @@ -91,12 +91,12 @@ export class BrowserHttpLib implements HttpRequestLibrary { myRequest.addEventListener("readystatechange", (e) => { if (myRequest.readyState === XMLHttpRequest.DONE) { if (myRequest.status === 0) { - const exc = OperationFailedError.fromCode( + const exc = TalerError.fromDetail( TalerErrorCode.WALLET_NETWORK_ERROR, - "HTTP request failed (status 0, maybe URI scheme was wrong?)", { requestUrl: requestUrl, }, + "HTTP request failed (status 0, maybe URI scheme was wrong?)", ); reject(exc); return; @@ -112,23 +112,23 @@ export class BrowserHttpLib implements HttpRequestLibrary { const responseString = td.decode(myRequest.response); responseJson = JSON.parse(responseString); } catch (e) { - throw OperationFailedError.fromCode( + throw TalerError.fromDetail( TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE, - "Invalid JSON from HTTP response", { requestUrl: requestUrl, httpStatusCode: myRequest.status, }, + "Invalid JSON from HTTP response", ); } if (responseJson === null || typeof responseJson !== "object") { - throw OperationFailedError.fromCode( + throw TalerError.fromDetail( TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE, - "Invalid JSON from HTTP response", { requestUrl: requestUrl, httpStatusCode: myRequest.status, }, + "Invalid JSON from HTTP response", ); } return responseJson; diff --git a/packages/taler-wallet-webextension/src/components/ErrorTalerOperation.tsx b/packages/taler-wallet-webextension/src/components/ErrorTalerOperation.tsx index 356709091..38d6ec561 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 */ -import { TalerErrorDetails } from "@gnu-taler/taler-util"; +import { TalerErrorDetail } from "@gnu-taler/taler-util"; import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; import arrowDown from "../../static/img/chevron-down.svg"; @@ -25,7 +25,7 @@ export function ErrorTalerOperation({ error, }: { title?: VNode; - error?: TalerErrorDetails; + error?: TalerErrorDetail; }): VNode | null { const { devMode } = useDevContext(); const [showErrorDetail, setShowErrorDetail] = useState(false); @@ -59,7 +59,7 @@ export function ErrorTalerOperation({
- {error.message} {!errorHint ? "" : `: ${errorHint}`}{" "} + {error.hint} {!errorHint ? "" : `: ${errorHint}`}{" "}
{devMode && ( diff --git a/packages/taler-wallet-webextension/src/cta/Deposit.tsx b/packages/taler-wallet-webextension/src/cta/Deposit.tsx index ac6c1fd6d..933195a9e 100644 --- a/packages/taler-wallet-webextension/src/cta/Deposit.tsx +++ b/packages/taler-wallet-webextension/src/cta/Deposit.tsx @@ -35,7 +35,7 @@ import { PreparePayResultType, Translate, } from "@gnu-taler/taler-util"; -import { OperationFailedError } from "@gnu-taler/taler-wallet-core"; +import { TalerError } from "@gnu-taler/taler-wallet-core"; import { Fragment, h, VNode } from "preact"; import { useEffect, useState } from "preact/hooks"; import { ErrorTalerOperation } from "../components/ErrorTalerOperation"; @@ -64,9 +64,9 @@ export function DepositPage({ talerPayUri, goBack }: Props): VNode { const [payResult, setPayResult] = useState( undefined, ); - const [payErrMsg, setPayErrMsg] = useState< - OperationFailedError | string | undefined - >(undefined); + const [payErrMsg, setPayErrMsg] = useState( + undefined, + ); const balance = useAsyncAsHook(wxApi.getBalance, [ NotificationType.CoinWithdrawn, @@ -97,7 +97,7 @@ export function DepositPage({ talerPayUri, goBack }: Props): VNode { setPayStatus(p); } catch (e) { console.log("Got error while trying to pay", e); - if (e instanceof OperationFailedError) { + if (e instanceof TalerError) { setPayErrMsg(e); } if (e instanceof Error) { @@ -117,7 +117,7 @@ export function DepositPage({ talerPayUri, goBack }: Props): VNode { } if (!payStatus) { - if (payErrMsg instanceof OperationFailedError) { + if (payErrMsg instanceof TalerError) { return ( @@ -131,7 +131,7 @@ export function DepositPage({ talerPayUri, goBack }: Props): VNode { Could not get the payment information for this order } - error={payErrMsg?.operationError} + error={payErrMsg?.errorDetail} /> diff --git a/packages/taler-wallet-webextension/src/cta/Pay.tsx b/packages/taler-wallet-webextension/src/cta/Pay.tsx index 2a0d1b46b..f6ae02f72 100644 --- a/packages/taler-wallet-webextension/src/cta/Pay.tsx +++ b/packages/taler-wallet-webextension/src/cta/Pay.tsx @@ -36,7 +36,7 @@ import { PreparePayResultType, Product, } from "@gnu-taler/taler-util"; -import { OperationFailedError } from "@gnu-taler/taler-wallet-core"; +import { TalerError } from "@gnu-taler/taler-wallet-core"; import { Fragment, h, VNode } from "preact"; import { useEffect, useState } from "preact/hooks"; import { ErrorMessage } from "../components/ErrorMessage"; @@ -93,7 +93,7 @@ export function PayPage({ undefined, ); const [payErrMsg, setPayErrMsg] = useState< - OperationFailedError | string | undefined + TalerError | string | undefined >(undefined); const hook = useAsyncAsHook(async () => { diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx index 66c83cf15..d58e2ec80 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx @@ -25,10 +25,8 @@ import { AmountJson, Amounts, ExchangeListItem, - Translate, WithdrawUriInfoResponse, } from "@gnu-taler/taler-util"; -import { OperationFailedError } from "@gnu-taler/taler-wallet-core"; import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { Loading } from "../components/Loading"; @@ -52,6 +50,7 @@ import { import * as wxApi from "../wxApi"; import { TermsOfServiceSection } from "./TermsOfServiceSection"; import { useTranslationContext } from "../context/translation"; +import { TalerError } from "@gnu-taler/taler-wallet-core"; interface Props { talerWithdrawUri?: string; @@ -85,9 +84,9 @@ export function View({ reviewed, }: ViewProps): VNode { const { i18n } = useTranslationContext(); - const [withdrawError, setWithdrawError] = useState< - OperationFailedError | undefined - >(undefined); + const [withdrawError, setWithdrawError] = useState( + undefined, + ); const [confirmDisabled, setConfirmDisabled] = useState(false); const needsReview = terms.status === "changed" || terms.status === "new"; @@ -109,7 +108,7 @@ export function View({ setConfirmDisabled(true); await onWithdraw(); } catch (e) { - if (e instanceof OperationFailedError) { + if (e instanceof TalerError) { setWithdrawError(e); } setConfirmDisabled(false); @@ -130,7 +129,7 @@ export function View({ Could not finish the withdrawal operation } - error={withdrawError.operationError} + error={withdrawError.errorDetail} /> )} diff --git a/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts b/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts index 6efa1d181..8d31de94f 100644 --- a/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts +++ b/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts @@ -13,28 +13,32 @@ You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, see */ -import { NotificationType, TalerErrorDetails } from "@gnu-taler/taler-util"; +import { + NotificationType, + TalerErrorCode, + TalerErrorDetail, +} from "@gnu-taler/taler-util"; +import { TalerError } from "@gnu-taler/taler-wallet-core"; import { useEffect, useState } from "preact/hooks"; import * as wxApi from "../wxApi"; -import { OperationFailedError } from "@gnu-taler/taler-wallet-core"; interface HookOk { hasError: false; response: T; } -export type HookError = HookGenericError | HookOperationalError +export type HookError = HookGenericError | HookOperationalError; export interface HookGenericError { hasError: true; - operational: false, + operational: false; message: string; } export interface HookOperationalError { hasError: true; - operational: true, - details: TalerErrorDetails; + operational: true; + details: TalerErrorDetail; } export type HookResponse = HookOk | HookError | undefined; @@ -51,10 +55,18 @@ export function useAsyncAsHook( const response = await fn(); setHookResponse({ hasError: false, response }); } catch (e) { - if (e instanceof OperationFailedError) { - setHookResponse({ hasError: true, operational: true, details: e.operationError }); + if (e instanceof TalerError) { + setHookResponse({ + hasError: true, + operational: true, + details: e.errorDetail, + }); } else if (e instanceof Error) { - setHookResponse({ hasError: true, operational: false, message: e.message }); + setHookResponse({ + hasError: true, + operational: false, + message: e.message, + }); } } } diff --git a/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts b/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts index 6f2585c1e..4dee28a6c 100644 --- a/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts +++ b/packages/taler-wallet-webextension/src/serviceWorkerHttpLib.ts @@ -23,7 +23,7 @@ import { HttpRequestLibrary, HttpRequestOptions, HttpResponse, - OperationFailedError, + TalerError, } from "@gnu-taler/taler-wallet-core"; /** @@ -44,14 +44,14 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary { if (this.throttlingEnabled && this.throttle.applyThrottle(requestUrl)) { const parsedUrl = new URL(requestUrl); - throw OperationFailedError.fromCode( + throw TalerError.fromDetail( TalerErrorCode.WALLET_HTTP_REQUEST_THROTTLED, - `request to origin ${parsedUrl.origin} was throttled`, { requestMethod, requestUrl, throttleStats: this.throttle.getThrottleStats(requestUrl), }, + `request to origin ${parsedUrl.origin} was throttled`, ); } @@ -107,13 +107,13 @@ function makeTextHandler(response: Response, requestUrl: string) { try { respText = await response.text(); } catch (e) { - throw OperationFailedError.fromCode( + throw TalerError.fromDetail( TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE, - "Invalid JSON from HTTP response", { requestUrl, httpStatusCode: response.status, }, + "Invalid JSON from HTTP response", ); } return respText; @@ -126,23 +126,23 @@ function makeJsonHandler(response: Response, requestUrl: string) { try { responseJson = await response.json(); } catch (e) { - throw OperationFailedError.fromCode( + throw TalerError.fromDetail( TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE, - "Invalid JSON from HTTP response", { requestUrl, httpStatusCode: response.status, }, + "Invalid JSON from HTTP response", ); } if (responseJson === null || typeof responseJson !== "object") { - throw OperationFailedError.fromCode( + throw TalerError.fromDetail( TalerErrorCode.WALLET_RECEIVED_MALFORMED_RESPONSE, - "Invalid JSON from HTTP response", { requestUrl, httpStatusCode: response.status, }, + "Invalid JSON from HTTP response", ); } return responseJson; diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts index 31b46d88d..2071f85e5 100644 --- a/packages/taler-wallet-webextension/src/wxApi.ts +++ b/packages/taler-wallet-webextension/src/wxApi.ts @@ -23,26 +23,48 @@ */ import { AcceptExchangeTosRequest, - AcceptManualWithdrawalResult, AcceptTipRequest, AcceptWithdrawalResponse, - AddExchangeRequest, AmountString, ApplyRefundResponse, BalancesResponse, CoinDumpJson, ConfirmPayResult, - CoreApiResponse, CreateDepositGroupRequest, CreateDepositGroupResponse, DeleteTransactionRequest, ExchangesListRespose, - GetExchangeTosResult, GetExchangeWithdrawalInfo, + AcceptManualWithdrawalResult, + AcceptTipRequest, + AcceptWithdrawalResponse, + AddExchangeRequest, + AmountString, + ApplyRefundResponse, + BalancesResponse, + CoinDumpJson, + ConfirmPayResult, + CoreApiResponse, + CreateDepositGroupRequest, + CreateDepositGroupResponse, + DeleteTransactionRequest, + ExchangesListRespose, + GetExchangeTosResult, + GetExchangeWithdrawalInfo, GetFeeForDepositRequest, - GetWithdrawalDetailsForUriRequest, KnownBankAccounts, NotificationType, PreparePayResult, PrepareTipRequest, - PrepareTipResult, RetryTransactionRequest, - SetWalletDeviceIdRequest, TransactionsResponse, WalletDiagnostics, WithdrawUriInfoResponse + GetWithdrawalDetailsForUriRequest, + KnownBankAccounts, + NotificationType, + PreparePayResult, + PrepareTipRequest, + PrepareTipResult, + RetryTransactionRequest, + SetWalletDeviceIdRequest, + TransactionsResponse, + WalletDiagnostics, + WithdrawUriInfoResponse, } from "@gnu-taler/taler-util"; import { - AddBackupProviderRequest, BackupInfo, OperationFailedError, + AddBackupProviderRequest, + BackupInfo, PendingOperationsResponse, - RemoveBackupProviderRequest + RemoveBackupProviderRequest, + TalerError, } from "@gnu-taler/taler-wallet-core"; import { DepositFee } from "@gnu-taler/taler-wallet-core/src/operations/deposits"; import type { ExchangeWithdrawDetails } from "@gnu-taler/taler-wallet-core/src/operations/withdraw"; import { MessageFromBackend } from "./wxBackend"; /** - * + * * @autor Florian Dold * @autor sebasjm */ @@ -88,7 +110,7 @@ async function callBackend(operation: string, payload: any): Promise { console.log("got response", resp); const r = resp as CoreApiResponse; if (r.type === "error") { - reject(new OperationFailedError(r.error)); + reject(TalerError.fromUncheckedDetail(r.error)); return; } resolve(r.result); @@ -127,15 +149,23 @@ export function resetDb(): Promise { return callBackend("reset-db", {}); } -export function getFeeForDeposit(depositPaytoUri: string, amount: AmountString): Promise { +export function getFeeForDeposit( + depositPaytoUri: string, + amount: AmountString, +): Promise { return callBackend("getFeeForDeposit", { - depositPaytoUri, amount + depositPaytoUri, + amount, } as GetFeeForDepositRequest); } -export function createDepositGroup(depositPaytoUri: string, amount: AmountString): Promise { +export function createDepositGroup( + depositPaytoUri: string, + amount: AmountString, +): Promise { return callBackend("createDepositGroup", { - depositPaytoUri, amount + depositPaytoUri, + amount, } as CreateDepositGroupRequest); } @@ -190,7 +220,9 @@ export function listKnownCurrencies(): Promise { export function listExchanges(): Promise { return callBackend("listExchanges", {}); } -export function listKnownBankAccounts(currency?: string): Promise { +export function listKnownBankAccounts( + currency?: string, +): Promise { return callBackend("listKnownBankAccounts", { currency }); } @@ -387,14 +419,17 @@ export function exportDB(): Promise { } export function importDB(dump: any): Promise { - return callBackend("importDb", { dump }) + return callBackend("importDb", { dump }); } -export function onUpdateNotification(messageTypes: Array, doCallback: () => void): () => void { +export function onUpdateNotification( + messageTypes: Array, + doCallback: () => void, +): () => void { // eslint-disable-next-line no-undef const port = chrome.runtime.connect({ name: "notifications" }); const listener = (message: MessageFromBackend): void => { - const shouldNotify = messageTypes.includes(message.type) + const shouldNotify = messageTypes.includes(message.type); if (shouldNotify) { doCallback(); } diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts index e158d2946..b7a0cdc54 100644 --- a/packages/taler-wallet-webextension/src/wxBackend.ts +++ b/packages/taler-wallet-webextension/src/wxBackend.ts @@ -35,7 +35,7 @@ import { import { DbAccess, deleteTalerDatabase, - makeErrorDetails, + makeErrorDetail, OpenedPromise, openPromise, openTalerDatabase, @@ -167,10 +167,10 @@ async function dispatch( type: "error", id: req.id, operation: req.operation, - error: makeErrorDetails( + error: makeErrorDetail( TalerErrorCode.WALLET_CORE_NOT_AVAILABLE, - "wallet core not available", {}, + "wallet core not available", ), }; break; @@ -233,7 +233,10 @@ function makeSyncWalletRedirect( const tab = await getTab(tabId); if (tab.url === oldUrl) { console.log("redirecting to", innerUrl.href); - chrome.tabs.update(tabId, { url: innerUrl.href, loadReplace: true } as any); + chrome.tabs.update(tabId, { + url: innerUrl.href, + loadReplace: true, + } as any); } }; doit(); -- cgit v1.2.3