aboutsummaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/pages/OperationState/state.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/demobank-ui/src/pages/OperationState/state.ts')
-rw-r--r--packages/demobank-ui/src/pages/OperationState/state.ts109
1 files changed, 98 insertions, 11 deletions
diff --git a/packages/demobank-ui/src/pages/OperationState/state.ts b/packages/demobank-ui/src/pages/OperationState/state.ts
index 6fb7bb28f..ae03ed529 100644
--- a/packages/demobank-ui/src/pages/OperationState/state.ts
+++ b/packages/demobank-ui/src/pages/OperationState/state.ts
@@ -15,21 +15,24 @@
*/
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 { ErrorType, RequestError, notify, notifyError, notifyInfo, useTranslationContext, utils } from "@gnu-taler/web-util/browser";
import { useBackendContext } from "../../context/backend.js";
-import { useAccessAPI, useAccountDetails, useWithdrawalDetails } from "../../hooks/access.js";
+import { useAccessAPI, useAccessAnonAPI, 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 { buildRequestErrorMessage, undefinedIfEmpty } from "../../utils.js";
+import { useEffect, useMemo, useState } from "preact/hooks";
import { getInitialBackendBaseURL } from "../../hooks/backend.js";
-export function useComponentState({ currency, onClose }: Props): utils.RecursiveState<State> {
+export function useComponentState({ currency, onClose,goToConfirmOperation }: Props): utils.RecursiveState<State> {
const { i18n } = useTranslationContext();
const [settings, updateSettings] = useSettings()
const { createWithdrawal } = useAccessAPI();
+ const { abortWithdrawal, confirmWithdrawal } = useAccessAnonAPI();
+ const [busy, setBusy] = useState<Record<string, undefined>>()
const amount = settings.maxWithdrawalAmount
+
async function doSilentStart() {
//FIXME: if amount is not enough use balance
const parsedAmount = Amounts.parseOrThrow(`${currency}:${amount}`)
@@ -67,12 +70,14 @@ export function useComponentState({ currency, onClose }: Props): utils.Recursive
}
}
+ const withdrawalOperationId = settings.currentWithdrawalOperationId
useEffect(() => {
- doSilentStart()
+ if (withdrawalOperationId === undefined) {
+ doSilentStart()
+ }
}, [settings.fastWithdrawal, amount])
const baseUrl = getInitialBackendBaseURL()
- const withdrawalOperationId = settings.currentWithdrawalOperationId
if (!withdrawalOperationId) {
return {
@@ -81,6 +86,63 @@ export function useComponentState({ currency, onClose }: Props): utils.Recursive
}
}
+ const wid = withdrawalOperationId
+
+ async function doAbort() {
+ try {
+ setBusy({})
+ await abortWithdrawal(wid);
+ onClose();
+ } catch (error) {
+ if (error instanceof RequestError) {
+ notify(
+ buildRequestErrorMessage(i18n, error.cause, {
+ onClientError: (status) =>
+ status === HttpStatusCode.Conflict
+ ? i18n.str`The reserve operation has been confirmed previously and can't be aborted`
+ : undefined,
+ }),
+ );
+ } else {
+ notifyError(
+ i18n.str`Operation failed, please report`,
+ (error instanceof Error
+ ? error.message
+ : JSON.stringify(error)) as TranslatedString
+ )
+ }
+ }
+ setBusy(undefined)
+ }
+
+ async function doConfirm() {
+ try {
+ setBusy({})
+ await confirmWithdrawal(wid);
+ notifyInfo(i18n.str`Wire transfer completed!`)
+ } catch (error) {
+ if (error instanceof RequestError) {
+ notify(
+ buildRequestErrorMessage(i18n, error.cause, {
+ onClientError: (status) =>
+ status === HttpStatusCode.Conflict
+ ? i18n.str`The withdrawal has been aborted previously and can't be confirmed`
+ : status === HttpStatusCode.UnprocessableEntity
+ ? i18n.str`The withdraw operation cannot be confirmed because no exchange and reserve public key selection happened before`
+ : undefined,
+ }),
+ );
+ } else {
+ notifyError(
+ i18n.str`Operation failed, please report`,
+ (error instanceof Error
+ ? error.message
+ : JSON.stringify(error)) as TranslatedString
+ )
+ }
+ }
+ setBusy(undefined)
+ }
const bankIntegrationApiBaseUrl = `${baseUrl}/integration-api`
const uri = stringifyWithdrawUri({
bankIntegrationApiBaseUrl,
@@ -92,11 +154,13 @@ export function useComponentState({ currency, onClose }: Props): utils.Recursive
status: "invalid-withdrawal",
error: undefined,
uri,
+ onClose,
}
}
return (): utils.RecursiveState<State> => {
const result = useWithdrawalDetails(withdrawalOperationId);
+
if (!result.ok) {
if (result.loading) {
return {
@@ -119,10 +183,17 @@ export function useComponentState({ currency, onClose }: Props): utils.Recursive
}
if (data.confirmation_done) {
+ if (!settings.showWithdrawalSuccess) {
+ updateSettings("currentWithdrawalOperationId", undefined)
+ onClose()
+ }
return {
status: "confirmed",
error: undefined,
- onClose,
+ onClose: async () => {
+ updateSettings("currentWithdrawalOperationId", undefined)
+ onClose()
+ },
}
}
@@ -131,7 +202,12 @@ export function useComponentState({ currency, onClose }: Props): utils.Recursive
status: "ready",
error: undefined,
uri: parsedUri,
- onClose
+ onClose: async () => {
+ await doAbort()
+ updateSettings("currentWithdrawalOperationId", undefined)
+ onClose()
+ },
+ onAbort: doAbort,
}
}
@@ -139,7 +215,8 @@ export function useComponentState({ currency, onClose }: Props): utils.Recursive
return {
status: "invalid-reserve",
error: undefined,
- reserve: data.selected_reserve_pub
+ reserve: data.selected_reserve_pub,
+ onClose,
}
}
@@ -149,13 +226,23 @@ export function useComponentState({ currency, onClose }: Props): utils.Recursive
return {
status: "invalid-payto",
error: undefined,
- payto: data.selected_exchange_account
+ payto: data.selected_exchange_account,
+ onClose,
}
}
+
+ // goToConfirmOperation(withdrawalOperationId)
return {
status: "need-confirmation",
error: undefined,
+ onAbort: async () => {
+ await doAbort()
+ updateSettings("currentWithdrawalOperationId", undefined)
+ onClose()
+ },
+ busy: !!busy,
+ onConfirm: doConfirm
}
}