/* This file is part of GNU Taler (C) 2022 Taler Systems S.A. GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Taler; see the file COPYING. If not, see */ import { Amounts, HttpStatusCode, TranslatedString, parsePaytoUri, parseWithdrawUri, stringifyWithdrawUri } from "@gnu-taler/taler-util"; import { ErrorType, RequestError, notify, notifyError, useTranslationContext, utils } from "@gnu-taler/web-util/browser"; import { useBackendContext } from "../../context/backend.js"; import { useAccessAPI, useAccountDetails, useWithdrawalDetails } from "../../hooks/access.js"; import { Props, State } from "./index.js"; import { useSettings } from "../../hooks/settings.js"; import { buildRequestErrorMessage } from "../../utils.js"; import { useEffect } from "preact/hooks"; import { getInitialBackendBaseURL } from "../../hooks/backend.js"; export function useComponentState({ currency, onClose }: Props): utils.RecursiveState { const { i18n } = useTranslationContext(); const [settings, updateSettings] = useSettings() const { createWithdrawal } = useAccessAPI(); const amount = settings.maxWithdrawalAmount async function doSilentStart() { //FIXME: if amount is not enough use balance const parsedAmount = Amounts.parseOrThrow(`${currency}:${amount}`) try { const result = await createWithdrawal({ amount: Amounts.stringify(parsedAmount), }); const uri = parseWithdrawUri(result.data.taler_withdraw_uri); if (!uri) { return notifyError( i18n.str`Server responded with an invalid withdraw URI`, i18n.str`Withdraw URI: ${result.data.taler_withdraw_uri}`); } else { updateSettings("currentWithdrawalOperationId", uri.withdrawalOperationId) } } catch (error) { if (error instanceof RequestError) { notify( buildRequestErrorMessage(i18n, error.cause, { onClientError: (status) => status === HttpStatusCode.Forbidden ? i18n.str`The operation was rejected due to insufficient funds` : undefined, }), ); } else { notifyError( i18n.str`Operation failed, please report`, (error instanceof Error ? error.message : JSON.stringify(error)) as TranslatedString ) } } } useEffect(() => { doSilentStart() }, [settings.fastWithdrawal, amount]) const baseUrl = getInitialBackendBaseURL() const withdrawalOperationId = settings.currentWithdrawalOperationId if (!withdrawalOperationId) { return { status: "loading", error: undefined } } const bankIntegrationApiBaseUrl = `${baseUrl}/integration-api` const uri = stringifyWithdrawUri({ bankIntegrationApiBaseUrl, withdrawalOperationId, }); const parsedUri = parseWithdrawUri(uri); if (!parsedUri) { return { status: "invalid-withdrawal", error: undefined, uri, } } return (): utils.RecursiveState => { const result = useWithdrawalDetails(withdrawalOperationId); if (!result.ok) { if (result.loading) { return { status: "loading", error: undefined } } return { status: "loading-error", error: result } } const { data } = result; if (data.aborted) { return { status: "aborted", error: undefined, onClose, } } if (data.confirmation_done) { return { status: "confirmed", error: undefined, onClose, } } if (!data.selection_done) { return { status: "ready", error: undefined, uri: parsedUri, onClose } } if (!data.selected_reserve_pub) { return { status: "invalid-reserve", error: undefined, reserve: data.selected_reserve_pub } } const account = !data.selected_exchange_account ? undefined : parsePaytoUri(data.selected_exchange_account) if (!account) { return { status: "invalid-payto", error: undefined, payto: data.selected_exchange_account } } return { status: "need-confirmation", error: undefined, } } }