From e92440e257b4df4a232a28701143a4f9db730458 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 8 Mar 2024 15:36:50 -0300 Subject: fix #8489 --- packages/aml-backoffice-ui/src/context/config.ts | 4 +- .../auditor-backoffice-ui/src/hooks/testing.tsx | 6 +- packages/bank-ui/TODO | 49 ------ packages/bank-ui/src/context/config.ts | 172 +++++++++++---------- packages/bank-ui/src/pages/OperationState/state.ts | 2 +- .../bank-ui/src/pages/WithdrawalOperationPage.tsx | 2 +- .../merchant-backoffice-ui/src/hooks/testing.tsx | 6 +- packages/taler-util/src/http-client/bank-core.ts | 48 +++--- packages/taler-util/src/index.ts | 1 + packages/taler-util/src/observability.ts | 35 +++++ .../taler-wallet-core/src/observable-wrappers.ts | 46 +----- packages/taler-wallet-core/src/wallet.ts | 10 +- .../src/components/WalletActivity.tsx | 3 +- .../src/wallet/AddExchange/state.ts | 20 ++- .../taler-wallet-webextension/src/wxBackend.ts | 21 +-- packages/web-util/src/utils/http-impl.browser.ts | 4 +- packages/web-util/src/utils/http-impl.sw.ts | 41 ++--- 17 files changed, 210 insertions(+), 260 deletions(-) delete mode 100644 packages/bank-ui/TODO diff --git a/packages/aml-backoffice-ui/src/context/config.ts b/packages/aml-backoffice-ui/src/context/config.ts index 3f62258c6..0ea491ca4 100644 --- a/packages/aml-backoffice-ui/src/context/config.ts +++ b/packages/aml-backoffice-ui/src/context/config.ts @@ -15,7 +15,7 @@ */ import { TalerExchangeApi, TalerExchangeHttpClient, TalerError } from "@gnu-taler/taler-util"; -import { BrowserHttpLib, useTranslationContext } from "@gnu-taler/web-util/browser"; +import { BrowserFetchHttpLib, useTranslationContext } from "@gnu-taler/web-util/browser"; import { ComponentChildren, createContext, FunctionComponent, h, VNode } from "preact"; import { useContext, useEffect, useState } from "preact/hooks"; import { ErrorLoading } from "@gnu-taler/web-util/browser"; @@ -61,7 +61,7 @@ export const ExchangeApiProvider = ({ const [checked, setChecked] = useState() const { i18n } = useTranslationContext(); const url = new URL(baseUrl) - const api = new TalerExchangeHttpClient(url.href, new BrowserHttpLib()) + const api = new TalerExchangeHttpClient(url.href, new BrowserFetchHttpLib()) useEffect(() => { api.getConfig() .then((resp) => { diff --git a/packages/auditor-backoffice-ui/src/hooks/testing.tsx b/packages/auditor-backoffice-ui/src/hooks/testing.tsx index 20b9c8a35..a0ba59b2e 100644 --- a/packages/auditor-backoffice-ui/src/hooks/testing.tsx +++ b/packages/auditor-backoffice-ui/src/hooks/testing.tsx @@ -144,9 +144,9 @@ export class ApiMockEnvironment extends MockEnvironment { } const bankCore = new TalerCoreBankHttpClient("http://localhost", mockHttpClient) - const bankIntegration = new TalerBankIntegrationHttpClient(bankCore.getIntegrationAPI(), mockHttpClient) - const bankRevenue = new TalerRevenueHttpClient(bankCore.getRevenueAPI("a"), "a", mockHttpClient) - const bankWire = new TalerWireGatewayHttpClient(bankCore.getWireGatewayAPI("b"), "b", mockHttpClient) + const bankIntegration = new TalerBankIntegrationHttpClient(bankCore.getIntegrationAPI().href, mockHttpClient) + const bankRevenue = new TalerRevenueHttpClient(bankCore.getRevenueAPI("a").href, "a", mockHttpClient) + const bankWire = new TalerWireGatewayHttpClient(bankCore.getWireGatewayAPI("b").href, "b", mockHttpClient) return ( diff --git a/packages/bank-ui/TODO b/packages/bank-ui/TODO deleted file mode 100644 index cc578cce0..000000000 --- a/packages/bank-ui/TODO +++ /dev/null @@ -1,49 +0,0 @@ -Urgent TODOs: - -- General: - - - not only Nora dark-theme, but default light! (CSS) - - DONE: auto-focus on input fields is not working well - - DONE: buttons should be visibly insensitive - as long as required input fields are not - working - - DONE: next required invalid/missing input field is - not properly highlighted in red - - Logout button needs more padding to the right (CSS) - -- Error bar: - - DONE: hows JSON, should only show good error message - and numeric code, not JSON syntax - - should auto-hide after next action, no need for - "clear"! - - need variant "status bar" in green (or blue) - which shows status of last operation - -* H1-Titles: - - Center more (currently way on the left) (CSS) - -- Assets: - - - Numeric amount needs to be shown MUCH bigger (CSS) - - Center more? (CSS) - -- Payments: - - - Amount to withdraw currently shown in white-on-white (CSS) - - Big frame drawn around notebook-tabs is not nice (CSS) - - Center more? (CSS) - - "Wire to bank account" - - maybe split two types (payto and IBAN) into - two tabs? - - currently cannot switch back from payto to IBAN - -- Withdraw: - - - Should use new 'status' bar at the end, instead - of extra dialog with "close" button - - ditto for bank-wire-transfer final stage - -- Footer: - - overlaps with transaction history or other - content, needs to consistently show at the - end! => change rendering logic!? (CSS?) diff --git a/packages/bank-ui/src/context/config.ts b/packages/bank-ui/src/context/config.ts index 39d12be86..cb0d599aa 100644 --- a/packages/bank-ui/src/context/config.ts +++ b/packages/bank-ui/src/context/config.ts @@ -15,27 +15,29 @@ */ import { - assertUnreachable, LibtoolVersion, + ObservableHttpClientLibrary, + TalerAuthenticationHttpClient, TalerBankConversionCacheEviction, TalerBankConversionHttpClient, - TalerCorebankApi, - TalerAuthenticationHttpClient, TalerCoreBankCacheEviction, TalerCoreBankHttpClient, - TalerError + TalerCorebankApi, + TalerError, + assertUnreachable, + CacheEvictor, } from "@gnu-taler/taler-util"; import { - BrowserHttpLib, + BrowserFetchHttpLib, ErrorLoading, - useTranslationContext, + useTranslationContext } from "@gnu-taler/web-util/browser"; import { ComponentChildren, - createContext, FunctionComponent, - h, VNode, + createContext, + h, } from "preact"; import { useContext, useEffect, useState } from "preact/hooks"; import { @@ -164,78 +166,20 @@ export const BankCoreApiProvider = ({ * @returns */ function buildApiClient(url: URL) { - const httpLib = new BrowserHttpLib(); - - const bankClient = new TalerCoreBankHttpClient(url.href, httpLib, { - async notifySuccess(op) { - switch (op) { - case TalerCoreBankCacheEviction.DELELE_ACCOUNT: { - await Promise.all([ - revalidatePublicAccounts(), - revalidateBusinessAccounts(), - ]); - return - } - case TalerCoreBankCacheEviction.CREATE_ACCOUNT: { - // admin balance change on new account - await Promise.all([ - revalidateAccountDetails(), - revalidateTransactions(), - revalidatePublicAccounts(), - revalidateBusinessAccounts(), - ]) - return; - } - case TalerCoreBankCacheEviction.UPDATE_ACCOUNT: { - await Promise.all([ - revalidateAccountDetails(), - ]) - return; - } - case TalerCoreBankCacheEviction.CREATE_TRANSACTION: { - await Promise.all([ - revalidateAccountDetails(), - revalidateTransactions(), - ]) - return; - } - case TalerCoreBankCacheEviction.CONFIRM_WITHDRAWAL: { - await Promise.all([ - revalidateAccountDetails(), - revalidateTransactions(), - ]) - return; - } - case TalerCoreBankCacheEviction.CREATE_CASHOUT: { - await Promise.all([ - revalidateAccountDetails(), - revalidateCashouts(), - revalidateTransactions(), - ]) - return; - } - case TalerCoreBankCacheEviction.UPDATE_PASSWORD: - case TalerCoreBankCacheEviction.ABORT_WITHDRAWAL: - case TalerCoreBankCacheEviction.CREATE_WITHDRAWAL: - return; - default: - assertUnreachable(op) - } - } + const httpFetch = new BrowserFetchHttpLib({ + enableThrottling: true, + requireTls: false, }); - const conversionClient = new TalerBankConversionHttpClient(bankClient.getConversionInfoAPI(), httpLib, { - async notifySuccess(op) { - switch (op) { - case TalerBankConversionCacheEviction.UPDATE_RATE: { - await revalidateConversionInfo(); - return - } - default: - assertUnreachable(op) - } + const httpLib = new ObservableHttpClientLibrary(httpFetch, { + observe(ev) { + console.log(ev) } - }); - const authClient = (user: string) => new TalerAuthenticationHttpClient(bankClient.getAuthenticationAPI(user), user, httpLib); + }) + + const bankClient = new TalerCoreBankHttpClient(url.href, httpLib, evictBankSwrCache); + const conversionClient = new TalerBankConversionHttpClient(bankClient.getConversionInfoAPI().href, httpLib, evictConversionSwrCache); + const authClient = (user: string) => new TalerAuthenticationHttpClient(bankClient.getAuthenticationAPI(user).href, user, httpLib); + return { bankClient, conversionClient, authClient } } @@ -261,3 +205,75 @@ export const BankCoreApiProviderTesting = ({ children, }); }; + + +const evictBankSwrCache: CacheEvictor = { + async notifySuccess(op) { + switch (op) { + case TalerCoreBankCacheEviction.DELELE_ACCOUNT: { + await Promise.all([ + revalidatePublicAccounts(), + revalidateBusinessAccounts(), + ]); + return + } + case TalerCoreBankCacheEviction.CREATE_ACCOUNT: { + // admin balance change on new account + await Promise.all([ + revalidateAccountDetails(), + revalidateTransactions(), + revalidatePublicAccounts(), + revalidateBusinessAccounts(), + ]) + return; + } + case TalerCoreBankCacheEviction.UPDATE_ACCOUNT: { + await Promise.all([ + revalidateAccountDetails(), + ]) + return; + } + case TalerCoreBankCacheEviction.CREATE_TRANSACTION: { + await Promise.all([ + revalidateAccountDetails(), + revalidateTransactions(), + ]) + return; + } + case TalerCoreBankCacheEviction.CONFIRM_WITHDRAWAL: { + await Promise.all([ + revalidateAccountDetails(), + revalidateTransactions(), + ]) + return; + } + case TalerCoreBankCacheEviction.CREATE_CASHOUT: { + await Promise.all([ + revalidateAccountDetails(), + revalidateCashouts(), + revalidateTransactions(), + ]) + return; + } + case TalerCoreBankCacheEviction.UPDATE_PASSWORD: + case TalerCoreBankCacheEviction.ABORT_WITHDRAWAL: + case TalerCoreBankCacheEviction.CREATE_WITHDRAWAL: + return; + default: + assertUnreachable(op) + } + } +} + +const evictConversionSwrCache: CacheEvictor = { + async notifySuccess(op) { + switch (op) { + case TalerBankConversionCacheEviction.UPDATE_RATE: { + await revalidateConversionInfo(); + return + } + default: + assertUnreachable(op) + } + } +} \ No newline at end of file diff --git a/packages/bank-ui/src/pages/OperationState/state.ts b/packages/bank-ui/src/pages/OperationState/state.ts index 5baf2d51c..9c5626cce 100644 --- a/packages/bank-ui/src/pages/OperationState/state.ts +++ b/packages/bank-ui/src/pages/OperationState/state.ts @@ -113,7 +113,7 @@ export function useComponentState({ } const uri = stringifyWithdrawUri({ - bankIntegrationApiBaseUrl: bank.getIntegrationAPI(), + bankIntegrationApiBaseUrl: bank.getIntegrationAPI().href, withdrawalOperationId, }); const parsedUri = parseWithdrawUri(uri); diff --git a/packages/bank-ui/src/pages/WithdrawalOperationPage.tsx b/packages/bank-ui/src/pages/WithdrawalOperationPage.tsx index 973a23011..b91fecd9d 100644 --- a/packages/bank-ui/src/pages/WithdrawalOperationPage.tsx +++ b/packages/bank-ui/src/pages/WithdrawalOperationPage.tsx @@ -38,7 +38,7 @@ export function WithdrawalOperationPage({ }): VNode { const { bank: api } = useBankCoreApiContext(); const uri = stringifyWithdrawUri({ - bankIntegrationApiBaseUrl: api.getIntegrationAPI(), + bankIntegrationApiBaseUrl: api.getIntegrationAPI().href, withdrawalOperationId: operationId, }); const parsedUri = parseWithdrawUri(uri); diff --git a/packages/merchant-backoffice-ui/src/hooks/testing.tsx b/packages/merchant-backoffice-ui/src/hooks/testing.tsx index 20b9c8a35..a0ba59b2e 100644 --- a/packages/merchant-backoffice-ui/src/hooks/testing.tsx +++ b/packages/merchant-backoffice-ui/src/hooks/testing.tsx @@ -144,9 +144,9 @@ export class ApiMockEnvironment extends MockEnvironment { } const bankCore = new TalerCoreBankHttpClient("http://localhost", mockHttpClient) - const bankIntegration = new TalerBankIntegrationHttpClient(bankCore.getIntegrationAPI(), mockHttpClient) - const bankRevenue = new TalerRevenueHttpClient(bankCore.getRevenueAPI("a"), "a", mockHttpClient) - const bankWire = new TalerWireGatewayHttpClient(bankCore.getWireGatewayAPI("b"), "b", mockHttpClient) + const bankIntegration = new TalerBankIntegrationHttpClient(bankCore.getIntegrationAPI().href, mockHttpClient) + const bankRevenue = new TalerRevenueHttpClient(bankCore.getRevenueAPI("a").href, "a", mockHttpClient) + const bankWire = new TalerWireGatewayHttpClient(bankCore.getWireGatewayAPI("b").href, "b", mockHttpClient) return ( diff --git a/packages/taler-util/src/http-client/bank-core.ts b/packages/taler-util/src/http-client/bank-core.ts index 4131edb11..b9fd6da80 100644 --- a/packages/taler-util/src/http-client/bank-core.ts +++ b/packages/taler-util/src/http-client/bank-core.ts @@ -86,16 +86,16 @@ export enum TalerCoreBankCacheEviction { CREATE_WITHDRAWAL, CREATE_CASHOUT, } - /** - * Protocol version spoken with the core bank. - * - * Endpoint must be ordered in the same way that in the docs - * Response code (http and taler) must have the same order that in the docs - * That way is easier to see changes - * - * Uses libtool's current:revision:age versioning. - */ - export class TalerCoreBankHttpClient { +/** + * Protocol version spoken with the core bank. + * + * Endpoint must be ordered in the same way that in the docs + * Response code (http and taler) must have the same order that in the docs + * That way is easier to see changes + * + * Uses libtool's current:revision:age versioning. + */ +export class TalerCoreBankHttpClient { public readonly PROTOCOL_VERSION = "4:0:0"; httpLib: HttpRequestLibrary; @@ -960,47 +960,39 @@ export enum TalerCoreBankCacheEviction { * https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api * */ - getIntegrationAPI(): string { - return new URL(`taler-integration/`, this.baseUrl).href; - // return new TalerBankIntegrationHttpClient(url.href, this.httpLib); + getIntegrationAPI(): URL { + return new URL(`taler-integration/`, this.baseUrl); } /** * https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api * */ - getWireGatewayAPI(username: string): string { - return new URL( - `accounts/${username}/taler-wire-gateway/`, - this.baseUrl, - ).href; - // return new TalerWireGatewayHttpClient(url.href, username, this.httpLib); + getWireGatewayAPI(username: string): URL { + return new URL(`accounts/${username}/taler-wire-gateway/`, this.baseUrl); } /** * https://docs.taler.net/core/api-corebank.html#taler-bank-integration-api * */ - getRevenueAPI(username: string): string { - return new URL(`accounts/${username}/taler-revenue/`, this.baseUrl).href; - // return new TalerRevenueHttpClient(url.href, username, this.httpLib); + getRevenueAPI(username: string): URL { + return new URL(`accounts/${username}/taler-revenue/`, this.baseUrl); } /** * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-token * */ - getAuthenticationAPI(username: string): string { - return new URL(`accounts/${username}/`, this.baseUrl).href; - // return new TalerAuthenticationHttpClient(url.href, username, this.httpLib); + getAuthenticationAPI(username: string): URL { + return new URL(`accounts/${username}/`, this.baseUrl); } /** * https://docs.taler.net/core/api-corebank.html#post--accounts-$USERNAME-token * */ - getConversionInfoAPI(): string { - return new URL(`conversion-info/`, this.baseUrl).href; - // TalerBankConversionHttpClient + getConversionInfoAPI(): URL { + return new URL(`conversion-info/`, this.baseUrl); } } diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts index 74ef9e8e6..6b9a4ae2f 100644 --- a/packages/taler-util/src/index.ts +++ b/packages/taler-util/src/index.ts @@ -25,6 +25,7 @@ export * from "./http-client/bank-integration.js"; export * from "./http-client/bank-revenue.js"; export * from "./http-client/bank-wire.js"; export * from "./http-client/exchange.js"; +export { CacheEvictor } from "./http-client/utils.js"; export * from "./http-client/officer-account.js"; export * from "./http-client/types.js"; export * from "./http-status-codes.js"; diff --git a/packages/taler-util/src/observability.ts b/packages/taler-util/src/observability.ts index fde951e37..198dcbe6e 100644 --- a/packages/taler-util/src/observability.ts +++ b/packages/taler-util/src/observability.ts @@ -15,6 +15,9 @@ */ import { ObservabilityEvent } from "./index.js"; +import { HttpRequestLibrary, HttpRequestOptions, HttpResponse } from "./http-common.js"; +import { ObservabilityEventType } from "./notifications.js" +import { getErrorDetailFromException } from "./errors.js"; /** * Observability sink can be passed into various operations (HTTP requests, DB access) @@ -23,3 +26,35 @@ import { ObservabilityEvent } from "./index.js"; export interface ObservabilityContext { observe(evt: ObservabilityEvent): void; } + +export class ObservableHttpClientLibrary implements HttpRequestLibrary { + constructor( + private impl: HttpRequestLibrary, + private oc: ObservabilityContext, + ) { } + async fetch( + url: string, + opt?: HttpRequestOptions | undefined, + ): Promise { + this.oc.observe({ + type: ObservabilityEventType.HttpFetchStart, + url: url, + }); + try { + const res = await this.impl.fetch(url, opt); + this.oc.observe({ + type: ObservabilityEventType.HttpFetchFinishSuccess, + url, + status: res.status, + }); + return res; + } catch (e) { + this.oc.observe({ + type: ObservabilityEventType.HttpFetchFinishError, + url, + error: getErrorDetailFromException(e), + }); + throw e; + } + } +} diff --git a/packages/taler-wallet-core/src/observable-wrappers.ts b/packages/taler-wallet-core/src/observable-wrappers.ts index 5653f185e..5a8be9cf6 100644 --- a/packages/taler-wallet-core/src/observable-wrappers.ts +++ b/packages/taler-wallet-core/src/observable-wrappers.ts @@ -25,14 +25,8 @@ import { IDBDatabase } from "@gnu-taler/idb-bridge"; import { ObservabilityContext, ObservabilityEventType, - RetryLoopOpts, - getErrorDetailFromException, + RetryLoopOpts } from "@gnu-taler/taler-util"; -import { - HttpRequestLibrary, - HttpRequestOptions, - HttpResponse, -} from "@gnu-taler/taler-util/http"; import { TaskIdStr } from "./common.js"; import { TalerCryptoInterface } from "./index.js"; import { @@ -50,7 +44,7 @@ export class ObservableTaskScheduler implements TaskScheduler { constructor( private impl: TaskScheduler, private oc: ObservabilityContext, - ) {} + ) { } private taskDepCache = new Set(); @@ -70,7 +64,7 @@ export class ObservableTaskScheduler implements TaskScheduler { getActiveTasks(): TaskIdStr[] { return this.impl.getActiveTasks(); } - + ensureRunning(): void { return this.impl.ensureRunning(); } @@ -110,38 +104,6 @@ export class ObservableTaskScheduler implements TaskScheduler { } } -export class ObservableHttpClientLibrary implements HttpRequestLibrary { - constructor( - private impl: HttpRequestLibrary, - private oc: ObservabilityContext, - ) {} - async fetch( - url: string, - opt?: HttpRequestOptions | undefined, - ): Promise { - this.oc.observe({ - type: ObservabilityEventType.HttpFetchStart, - url: url, - }); - try { - const res = await this.impl.fetch(url, opt); - this.oc.observe({ - type: ObservabilityEventType.HttpFetchFinishSuccess, - url, - status: res.status, - }); - return res; - } catch (e) { - this.oc.observe({ - type: ObservabilityEventType.HttpFetchFinishError, - url, - error: getErrorDetailFromException(e), - }); - throw e; - } - } -} - const locRegex = /\s*at\s*([a-zA-Z0-9_.!]*)\s*/; export function getCallerInfo(up: number = 2): string { @@ -160,7 +122,7 @@ export class ObservableDbAccess implements DbAccess { constructor( private impl: DbAccess, private oc: ObservabilityContext, - ) {} + ) { } idbHandle(): IDBDatabase { return this.impl.idbHandle(); } diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 46f58ec81..1602eb158 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -144,6 +144,7 @@ import { parseTalerUri, sampleWalletCoreTransactions, setDangerousTimetravel, + ObservableHttpClientLibrary, validateIban, } from "@gnu-taler/taler-util"; import type { HttpRequestLibrary } from "@gnu-taler/taler-util/http"; @@ -211,7 +212,6 @@ import { } from "./instructedAmountConversion.js"; import { ObservableDbAccess, - ObservableHttpClientLibrary, ObservableTaskScheduler, observeTalerCrypto, } from "./observable-wrappers.js"; @@ -521,9 +521,9 @@ async function dumpCoins(wex: WalletExecutionContext): Promise { ageCommitmentProof: c.ageCommitmentProof, spend_allocation: c.spendAllocation ? { - amount: c.spendAllocation.amount, - id: c.spendAllocation.id, - } + amount: c.spendAllocation.amount, + id: c.spendAllocation.id, + } : undefined, }); } @@ -1526,7 +1526,7 @@ async function handleCoreApiRequest( wex = getObservedWalletExecutionContext(ws, CancellationToken.CONTINUE, oc); } else { oc = { - observe(evt) {}, + observe(evt) { }, }; wex = getNormalWalletExecutionContext(ws, CancellationToken.CONTINUE, oc); } diff --git a/packages/taler-wallet-webextension/src/components/WalletActivity.tsx b/packages/taler-wallet-webextension/src/components/WalletActivity.tsx index 316596fb4..60839e1f0 100644 --- a/packages/taler-wallet-webextension/src/components/WalletActivity.tsx +++ b/packages/taler-wallet-webextension/src/components/WalletActivity.tsx @@ -33,14 +33,13 @@ import { useBackendContext } from "../context/backend.js"; import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js"; import { useSettings } from "../hooks/useSettings.js"; import { Button } from "../mui/Button.js"; +import { WxApiType } from "../wxApi.js"; import { Modal } from "./Modal.js"; import { Time } from "./Time.js"; -import { WalletEvent, WxApiType } from "../wxApi.js"; interface Props extends JSX.HTMLAttributes { } - export function WalletActivity({ }: Props): VNode { const { i18n } = useTranslationContext() const [settings, updateSettings] = useSettings() diff --git a/packages/taler-wallet-webextension/src/wallet/AddExchange/state.ts b/packages/taler-wallet-webextension/src/wallet/AddExchange/state.ts index 1b9cbe397..5ae0aa8f4 100644 --- a/packages/taler-wallet-webextension/src/wallet/AddExchange/state.ts +++ b/packages/taler-wallet-webextension/src/wallet/AddExchange/state.ts @@ -16,13 +16,13 @@ import { ExchangeEntryStatus, OperationFailWithBody, OperationOk, TalerExchangeApi, TalerExchangeHttpClient, canonicalizeBaseUrl, opKnownFailureWithBody } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; -import { BrowserHttpLib } from "@gnu-taler/web-util/browser"; import { useCallback, useEffect, useState } from "preact/hooks"; import { useBackendContext } from "../../context/backend.js"; import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js"; import { withSafe } from "../../mui/handlers.js"; import { RecursiveState } from "../../utils/index.js"; import { CheckExchangeErrors, Props, State } from "./index.js"; +import { BrowserFetchHttpLib } from "@gnu-taler/web-util/browser"; function urlFromInput(str: string): URL { let result: URL; @@ -65,7 +65,23 @@ export function useComponentState({ onBack, currency, noDebounce }: Props): Recu if (found !== -1) { return opKnownFailureWithBody("already-active", undefined); } - const api = new TalerExchangeHttpClient(baseUrl.href, new BrowserHttpLib() as any); + + /** + * FIXME: For some reason typescript doesn't like the next BrowserFetchHttpLib + * + * │ src/wallet/AddExchange/state.ts(68,63): error TS2345: Argument of type 'BrowserFetchHttpLib' is not assignable to parameter of ty + * │ Types of property 'fetch' are incompatible. + * │ Type '(requestUrl: string, options?: HttpRequestOptions | undefined) => Promise' is not assignable to type '(ur + * │ Types of parameters 'options' and 'opt' are incompatible. + * │ Type 'import("$PATH/wallet.git/packages/taler-util/lib/http-common", { wi + * │ Type 'import("$PATH/wallet.git/packages/taler-util/lib/http-common", { + * │ Types of property 'cancellationToken' are incompatible. + * │ Type 'import("$PATH/wallet.git/packages/taler-util/lib/Cancellation + * │ Type 'import("$PATH/wallet.git/packages/taler-util/lib/Cancellati + * │ Types have separate declarations of a private property '_isCancelled'. + * + */ + const api = new TalerExchangeHttpClient(baseUrl.href, new BrowserFetchHttpLib() as any); const config = await api.getConfig() if (!api.isCompatible(config.body.version)) { return opKnownFailureWithBody("invalid-version", config.body.version) diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts index 195e05687..44e4c0d48 100644 --- a/packages/taler-wallet-webextension/src/wxBackend.ts +++ b/packages/taler-wallet-webextension/src/wxBackend.ts @@ -49,14 +49,11 @@ import { exportDb, importDb, } from "@gnu-taler/taler-wallet-core"; -import { - BrowserHttpLib, - ServiceWorkerHttpLib, -} from "@gnu-taler/web-util/browser"; import { MessageFromFrontend, MessageResponse } from "./platform/api.js"; import { platform } from "./platform/background.js"; import { ExtensionOperations } from "./taler-wallet-interaction-loader.js"; import { BackgroundOperations, WalletEvent } from "./wxApi.js"; +import { BrowserFetchHttpLib } from "@gnu-taler/web-util/browser"; /** * Currently active wallet instance. Might be unloaded and @@ -101,7 +98,7 @@ async function getNotifications(): Promise { } async function clearNotifications(): Promise { - notifications.splice(0,notifications.length) + notifications.splice(0, notifications.length) } @@ -242,7 +239,7 @@ async function dispatch< error: makeErrorDetail( TalerErrorCode.WALLET_CORE_NOT_AVAILABLE, { lastError }, - `wallet core not available${!lastError ? "": `,last error: ${lastError.hint}`}`, + `wallet core not available${!lastError ? "" : `,last error: ${lastError.hint}`}`, ), }; } @@ -279,15 +276,9 @@ async function reinitWallet(): Promise { let timer; const httpFactory = (): HttpRequestLibrary => { - if (platform.useServiceWorkerAsBackgroundProcess()) { - return new ServiceWorkerHttpLib({ - // enableThrottling: false, - }); - } else { - return new BrowserHttpLib({ - // enableThrottling: false, - }); - } + return new BrowserFetchHttpLib({ + // enableThrottling: false, + }); }; if (platform.useServiceWorkerAsBackgroundProcess()) { diff --git a/packages/web-util/src/utils/http-impl.browser.ts b/packages/web-util/src/utils/http-impl.browser.ts index 5d65c3903..1e5496071 100644 --- a/packages/web-util/src/utils/http-impl.browser.ts +++ b/packages/web-util/src/utils/http-impl.browser.ts @@ -41,8 +41,10 @@ const logger = new Logger("browserHttpLib"); /** * An implementation of the [[HttpRequestLibrary]] using the * browser's XMLHttpRequest. + * + * @deprecated use BrowserFetchHttpLib */ -export class BrowserHttpLib implements HttpRequestLibrary { +export class BrowserHttpLibDepreacted implements HttpRequestLibrary { private throttle = new RequestThrottler(); private throttlingEnabled = true; private requireTls = false; diff --git a/packages/web-util/src/utils/http-impl.sw.ts b/packages/web-util/src/utils/http-impl.sw.ts index 2ae4ccd86..316b75dfd 100644 --- a/packages/web-util/src/utils/http-impl.sw.ts +++ b/packages/web-util/src/utils/http-impl.sw.ts @@ -39,7 +39,7 @@ import { * An implementation of the [[HttpRequestLibrary]] using the * browser's XMLHttpRequest. */ -export class ServiceWorkerHttpLib implements HttpRequestLibrary { +export class BrowserFetchHttpLib implements HttpRequestLibrary { private throttle = new RequestThrottler(); private throttlingEnabled = true; private requireTls = false; @@ -58,6 +58,7 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary { const requestHeader = options?.headers; const requestTimeout = options?.timeout ?? Duration.fromMilliseconds(DEFAULT_REQUEST_TIMEOUT_MS); + const requestCancel = options?.cancellationToken; const parsedUrl = new URL(requestUrl); if (this.throttlingEnabled && this.throttle.applyThrottle(requestUrl)) { @@ -82,8 +83,10 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary { ); } - let myBody: ArrayBuffer | undefined = - requestMethod === "POST" ? encodeBody(requestBody) : undefined; + const myBody: ArrayBuffer | undefined = + requestMethod === "POST" || requestMethod === "PUT" || requestMethod === "PATCH" + ? encodeBody(requestBody) + : undefined; const requestHeadersMap = getDefaultHeaders(requestMethod); if (requestHeader) { @@ -94,12 +97,17 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary { } const controller = new AbortController(); - let timeoutId: any | undefined; + let timeoutId: ReturnType | undefined; if (requestTimeout.d_ms !== "forever") { timeoutId = setTimeout(() => { - controller.abort(TalerErrorCode.WALLET_HTTP_REQUEST_GENERIC_TIMEOUT); + controller.abort(TalerErrorCode.GENERIC_TIMEOUT); }, requestTimeout.d_ms); } + if (requestCancel) { + requestCancel.onCancelled(() => { + controller.abort(TalerErrorCode.GENERIC_CLIENT_INTERNAL_ERROR) + }); + } try { const response = await fetch(requestUrl, { @@ -142,29 +150,6 @@ export class ServiceWorkerHttpLib implements HttpRequestLibrary { } } - get(url: string, opt?: HttpRequestOptions): Promise { - return this.fetch(url, { - method: "GET", - ...opt, - }); - } - - postJson( - url: string, - body: any, - opt?: HttpRequestOptions, - ): Promise { - return this.fetch(url, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(body), - ...opt, - }); - } - - stop(): void { - // Nothing to do - } } function makeTextHandler( -- cgit v1.2.3