diff options
3 files changed, 51 insertions, 89 deletions
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.test.ts b/packages/taler-wallet-webextension/src/cta/Withdraw.test.ts index 5a28c4cf5..e26e86445 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw.test.ts +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.test.ts @@ -59,13 +59,6 @@ describe("Withdraw CTA states", () => { expect(status).equals('loading-uri') expect(hook).deep.equals({ "hasError": true, "operational": false, "message": "ERROR_NO-URI-FOR-WITHDRAWAL" }); } - await waitNextUpdate() - { - const { status, hook } = getLastResultOrThrow() - - expect(status).equals('loading-uri') - expect(hook).deep.equals({ "hasError": true, "operational": false, "message": "ERROR_NO-URI-FOR-WITHDRAWAL" }); - } await assertNoPendingUpdate() }); @@ -93,25 +86,6 @@ describe("Withdraw CTA states", () => { const { status, hook } = getLastResultOrThrow() expect(status).equals('loading-exchange') - expect(hook).undefined; - } - - await waitNextUpdate() - - { - const { status, hook } = getLastResultOrThrow() - - expect(status).equals('loading-exchange') - - expect(hook).deep.equals({ "hasError": true, "operational": false, "message": "ERROR_NO-DEFAULT-EXCHANGE" }); - } - - await waitNextUpdate() - - { - const { status, hook } = getLastResultOrThrow() - - expect(status).equals('loading-exchange') expect(hook).deep.equals({ "hasError": true, "operational": false, "message": "ERROR_NO-DEFAULT-EXCHANGE" }); } diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx index 78e821576..6eb87a85c 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx @@ -24,7 +24,7 @@ import { AmountJson, Amounts } from "@gnu-taler/taler-util"; import { TalerError } from "@gnu-taler/taler-wallet-core"; import { Fragment, h, VNode } from "preact"; -import { useState } from "preact/hooks"; +import { useMemo, useState } from "preact/hooks"; import { Amount } from "../components/Amount.js"; import { ErrorTalerOperation } from "../components/ErrorTalerOperation.js"; import { Loading } from "../components/Loading.js"; @@ -116,44 +116,44 @@ export function useComponentState( /** * Get the amount and select one exchange */ - const exchangeAndAmount = useAsyncAsHook( - async () => { - if (!uriInfoHook || uriInfoHook.hasError || !uriInfoHook.response) return; - const { uriInfo, knownExchanges } = uriInfoHook.response; - - const amount = Amounts.parseOrThrow(uriInfo.amount); - - const thisCurrencyExchanges = knownExchanges.filter( - (ex) => ex.currency === amount.currency, - ); - - const thisExchange: string | undefined = - customExchange ?? - uriInfo.defaultExchangeBaseUrl ?? - (thisCurrencyExchanges[0] - ? thisCurrencyExchanges[0].exchangeBaseUrl - : undefined); - - if (!thisExchange) throw Error("ERROR_NO-DEFAULT-EXCHANGE"); - - return { amount, thisExchange, thisCurrencyExchanges }; - }, - [], - [!uriInfoHook || uriInfoHook.hasError ? undefined : uriInfoHook], - ); + const uriHookDep = + !uriInfoHook || uriInfoHook.hasError || !uriInfoHook.response + ? undefined + : uriInfoHook; + + const { amount, thisExchange, thisCurrencyExchanges } = useMemo(() => { + if (!uriHookDep) + return { + amount: undefined, + thisExchange: undefined, + thisCurrencyExchanges: [], + }; + + const { uriInfo, knownExchanges } = uriHookDep.response; + + const amount = uriInfo ? Amounts.parseOrThrow(uriInfo.amount) : undefined; + const thisCurrencyExchanges = + !amount || !knownExchanges + ? [] + : knownExchanges.filter((ex) => ex.currency === amount.currency); + + const thisExchange: string | undefined = + customExchange ?? + uriInfo?.defaultExchangeBaseUrl ?? + (thisCurrencyExchanges && thisCurrencyExchanges[0] + ? thisCurrencyExchanges[0].exchangeBaseUrl + : undefined); + + return { amount, thisExchange, thisCurrencyExchanges }; + }, [uriHookDep, customExchange]); /** * For the exchange selected, bring the status of the terms of service */ const terms = useAsyncAsHook( async () => { - if ( - !exchangeAndAmount || - exchangeAndAmount.hasError || - !exchangeAndAmount.response - ) - return; - const { thisExchange } = exchangeAndAmount.response; + if (!thisExchange) return false; + const exchangeTos = await api.getExchangeTos(thisExchange, ["text/xml"]); const state = buildTermsOfServiceState(exchangeTos); @@ -161,11 +161,7 @@ export function useComponentState( return { state }; }, [], - [ - !exchangeAndAmount || exchangeAndAmount.hasError - ? undefined - : exchangeAndAmount, - ], + [thisExchange], ); /** @@ -174,13 +170,7 @@ export function useComponentState( */ const info = useAsyncAsHook( async () => { - if ( - !exchangeAndAmount || - exchangeAndAmount.hasError || - !exchangeAndAmount.response - ) - return; - const { thisExchange, amount } = exchangeAndAmount.response; + if (!thisExchange || !amount) return false; const info = await api.getExchangeWithdrawalInfo({ exchangeBaseUrl: thisExchange, @@ -196,11 +186,7 @@ export function useComponentState( return { info, withdrawalFee }; }, [], - [ - !exchangeAndAmount || exchangeAndAmount.hasError - ? undefined - : exchangeAndAmount, - ], + [thisExchange, amount], ); const [reviewing, setReviewing] = useState<boolean>(false); @@ -221,26 +207,27 @@ export function useComponentState( }; } - if (!exchangeAndAmount || exchangeAndAmount.hasError) { + if (!thisExchange || !amount) { return { status: "loading-exchange", - hook: exchangeAndAmount, + hook: { + hasError: true, + operational: false, + message: "ERROR_NO-DEFAULT-EXCHANGE", + }, }; } - if (!exchangeAndAmount.response) { - return { - status: "loading-exchange", - hook: undefined, - }; - } - const { thisExchange, thisCurrencyExchanges, amount } = - exchangeAndAmount.response; + + const selectedExchange = thisExchange; async function doWithdrawAndCheckError(): Promise<void> { try { setConfirmDisabled(true); if (!talerWithdrawUri) return; - const res = await api.acceptWithdrawal(talerWithdrawUri, thisExchange); + const res = await api.acceptWithdrawal( + talerWithdrawUri, + selectedExchange, + ); if (res.confirmTransferUrl) { document.location.href = res.confirmTransferUrl; } @@ -308,7 +295,7 @@ export function useComponentState( try { await api.setExchangeTosAccepted( - thisExchange, + selectedExchange, accepted ? termsState.version : undefined, ); setReviewed(accepted); diff --git a/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts b/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts index 51123d154..e592073dd 100644 --- a/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts +++ b/packages/taler-wallet-webextension/src/hooks/useAsyncAsHook.ts @@ -42,7 +42,7 @@ export interface HookOperationalError { export type HookResponse<T> = HookOk<T> | HookError | undefined; export function useAsyncAsHook<T>( - fn: () => Promise<T>, + fn: () => Promise<T | false>, updateOnNotification?: Array<NotificationType>, deps?: any[], ): HookResponse<T> { @@ -57,6 +57,7 @@ export function useAsyncAsHook<T>( async function doAsync(): Promise<void> { try { const response = await args.fn(); + if (response === false) return; setHookResponse({ hasError: false, response }); } catch (e) { if (e instanceof TalerError) { |