summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-webextension/src/cta/Withdraw/state.ts')
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw/state.ts140
1 files changed, 91 insertions, 49 deletions
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
index 05aef690e..90ad65d6e 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts
@@ -14,14 +14,14 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-/* eslint-disable react-hooks/rules-of-hooks */
import {
AmountJson,
+ AmountString,
Amounts,
ExchangeFullDetails,
ExchangeListItem,
NotificationType,
- TalerError,
+ TransactionMajorState,
parseWithdrawExchangeUri,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
@@ -44,6 +44,7 @@ export function useComponentStateFromParams({
const api = useBackendContext();
const { i18n } = useTranslationContext();
const paramsAmount = amount ? Amounts.parse(amount) : undefined;
+ const [updatedExchangeByUser, setUpdatedExchangeByUser] = useState<string>();
const uriInfoHook = useAsyncAsHook(async () => {
const exchanges = await api.wallet.call(
WalletApiOperation.ListExchanges,
@@ -52,12 +53,12 @@ export function useComponentStateFromParams({
const uri = maybeTalerUri
? parseWithdrawExchangeUri(maybeTalerUri)
: undefined;
- const exchangeByTalerUri = uri?.exchangeBaseUrl;
+ const exchangeByTalerUri = updatedExchangeByUser ?? uri?.exchangeBaseUrl;
+
let ex: ExchangeFullDetails | undefined;
- if (exchangeByTalerUri && uri.exchangePub) {
+ if (exchangeByTalerUri) {
await api.wallet.call(WalletApiOperation.AddExchange, {
exchangeBaseUrl: exchangeByTalerUri,
- masterPub: uri.exchangePub,
});
const info = await api.wallet.call(
WalletApiOperation.GetExchangeDetailedInfo,
@@ -159,6 +160,7 @@ export function useComponentStateFromParams({
async function doManualWithdraw(
exchange: string,
ageRestricted: number | undefined,
+ amount: AmountString,
): Promise<{
transactionId: string;
confirmTransferUrl: string | undefined;
@@ -167,7 +169,7 @@ export function useComponentStateFromParams({
WalletApiOperation.AcceptManualWithdrawal,
{
exchangeBaseUrl: exchange,
- amount: Amounts.stringify(chosenAmount),
+ amount,
restrictAge: ageRestricted,
},
);
@@ -184,8 +186,10 @@ export function useComponentStateFromParams({
onSuccess,
undefined,
chosenAmount,
+ chosenAmount.currency,
exchangeList,
exchangeByTalerUri,
+ setUpdatedExchangeByUser,
);
}
@@ -196,6 +200,8 @@ export function useComponentStateFromURI({
}: PropsFromURI): RecursiveState<State> {
const api = useBackendContext();
const { i18n } = useTranslationContext();
+
+ const [updatedExchangeByUser, setUpdatedExchangeByUser] = useState<string>();
/**
* Ask the wallet about the withdraw URI
*/
@@ -206,31 +212,33 @@ export function useComponentStateFromURI({
: maybeTalerUri;
const uriInfo = await api.wallet.call(
- WalletApiOperation.GetWithdrawalDetailsForUri,
+ WalletApiOperation.PrepareBankIntegratedWithdrawal,
{
talerWithdrawUri,
- notifyChangeFromPendingTimeoutMs: 30 * 1000,
+ selectedExchange: updatedExchangeByUser,
},
);
const {
amount,
defaultExchangeBaseUrl,
possibleExchanges,
- operationId,
confirmTransferUrl,
status,
- } = uriInfo;
- const transaction = await api.wallet.call(
- WalletApiOperation.GetWithdrawalTransactionByUri,
- { talerWithdrawUri },
- );
+ } = uriInfo.info;
+ const txInfo =
+ uriInfo.transactionId === undefined
+ ? undefined
+ : await api.wallet.call(WalletApiOperation.GetTransactionById, {
+ transactionId: uriInfo.transactionId,
+ });
return {
talerWithdrawUri,
- operationId,
status,
- transaction,
+ transactionId: uriInfo.transactionId,
+ currency: uriInfo.info.currency,
+ txInfo: txInfo,
confirmTransferUrl,
- amount: Amounts.parseOrThrow(amount),
+ amount: !amount ? undefined : Amounts.parseOrThrow(amount),
thisExchange: defaultExchangeBaseUrl,
exchanges: possibleExchanges,
};
@@ -239,13 +247,20 @@ export function useComponentStateFromURI({
const readyToListen = uriInfoHook && !uriInfoHook.hasError;
useEffect(() => {
- if (!uriInfoHook) {
+ if (!uriInfoHook || uriInfoHook.hasError) {
return;
}
+ const txId = uriInfoHook.response.transactionId;
+
return api.listener.onUpdateNotification(
- [NotificationType.WithdrawalOperationTransition],
- (asd) => {
- uriInfoHook.retry();
+ [NotificationType.TransactionStateTransition],
+ (notif) => {
+ if (
+ notif.type === NotificationType.TransactionStateTransition &&
+ notif.transactionId === txId
+ ) {
+ uriInfoHook.retry();
+ }
},
);
}, [readyToListen]);
@@ -264,39 +279,45 @@ export function useComponentStateFromURI({
}
const uri = uriInfoHook.response.talerWithdrawUri;
- const chosenAmount = uriInfoHook.response.amount;
+ const txId = uriInfoHook.response.transactionId;
+ const infoAmount = uriInfoHook.response.amount;
const defaultExchange = uriInfoHook.response.thisExchange;
const exchangeList = uriInfoHook.response.exchanges;
async function doManagedWithdraw(
exchange: string,
ageRestricted: number | undefined,
+ amount: AmountString,
): Promise<{
transactionId: string;
confirmTransferUrl: string | undefined;
}> {
- const res = await api.wallet.call(
- WalletApiOperation.AcceptBankIntegratedWithdrawal,
- {
- exchangeBaseUrl: exchange,
- talerWithdrawUri: uri,
- restrictAge: ageRestricted,
- },
- );
+ if (!txId) {
+ throw Error("can't confirm transaction");
+ }
+ const res = await api.wallet.call(WalletApiOperation.ConfirmWithdrawal, {
+ exchangeBaseUrl: exchange,
+ amount,
+ restrictAge: ageRestricted,
+ transactionId: txId,
+ });
return {
confirmTransferUrl: res.confirmTransferUrl,
transactionId: res.transactionId,
};
}
- if (uriInfoHook.response.status !== "pending") {
- if (uriInfoHook.response.transaction) {
- onSuccess(uriInfoHook.response.transaction.transactionId);
- }
+ if (
+ uriInfoHook.response.txInfo &&
+ uriInfoHook.response.status !== "pending"
+ ) {
+ const info = uriInfoHook.response.txInfo;
return {
status: "already-completed",
operationState: uriInfoHook.response.status,
confirmTransferUrl: uriInfoHook.response.confirmTransferUrl,
+ thisWallet: info.txState.major === TransactionMajorState.Pending,
+ redirectToTx: () => onSuccess(info.transactionId),
error: undefined,
};
}
@@ -307,9 +328,11 @@ export function useComponentStateFromURI({
cancel,
onSuccess,
uri,
- chosenAmount,
+ infoAmount,
+ uriInfoHook.response.currency,
exchangeList,
defaultExchange,
+ setUpdatedExchangeByUser,
);
}, []);
}
@@ -317,6 +340,7 @@ export function useComponentStateFromURI({
type ManualOrManagedWithdrawFunction = (
exchange: string,
ageRestricted: number | undefined,
+ amount: AmountString,
) => Promise<{ transactionId: string; confirmTransferUrl: string | undefined }>;
function exchangeSelectionState(
@@ -324,21 +348,37 @@ function exchangeSelectionState(
cancel: () => Promise<void>,
onSuccess: (txid: string) => Promise<void>,
talerWithdrawUri: string | undefined,
- chosenAmount: AmountJson,
+ infoAmount: AmountJson | undefined,
+ currency: string,
exchangeList: ExchangeListItem[],
exchangeSuggestedByTheBank: string | undefined,
+ onExchangeUpdated: (ex: string) => void,
): RecursiveState<State> {
const api = useBackendContext();
const selectedExchange = useSelectedExchange({
- currency: chosenAmount.currency,
+ currency: currency,
defaultExchange: exchangeSuggestedByTheBank,
list: exchangeList,
});
+ const current =
+ selectedExchange.status !== "ready"
+ ? undefined
+ : selectedExchange.selected.exchangeBaseUrl;
+ useEffect(() => {
+ if (current) {
+ onExchangeUpdated(current);
+ }
+ }, [current]);
+
+ const safeAmount = !infoAmount ? Amounts.zeroOfCurrency(currency) : infoAmount
+ const [choosenAmount, setChoosenAmount] = useState(safeAmount)
+
if (selectedExchange.status !== "ready") {
return selectedExchange;
}
+
return useCallback(():
| State.Success
| State.LoadingUriError
@@ -348,9 +388,7 @@ function exchangeSelectionState(
const [ageRestricted, setAgeRestricted] = useState(0);
const currentExchange = selectedExchange.selected;
- const [selectedCurrency, setSelectedCurrency] = useState<string>(
- chosenAmount.currency,
- );
+ const [selectedCurrency, setSelectedCurrency] = useState<string>(currency);
/**
* With the exchange and amount, ask the wallet the information
* about the withdrawal
@@ -360,7 +398,7 @@ function exchangeSelectionState(
WalletApiOperation.GetWithdrawalDetailsForAmount,
{
exchangeBaseUrl: currentExchange.exchangeBaseUrl,
- amount: Amounts.stringify(chosenAmount),
+ amount: Amounts.stringify(choosenAmount),
restrictAge: ageRestricted,
},
);
@@ -377,9 +415,6 @@ function exchangeSelectionState(
};
}, []);
- const [withdrawError, setWithdrawError] = useState<TalerError | undefined>(
- undefined,
- );
const [doingWithdraw, setDoingWithdraw] = useState<boolean>(false);
async function doWithdrawAndCheckError(): Promise<void> {
@@ -388,6 +423,7 @@ function exchangeSelectionState(
const res = await doWithdraw(
currentExchange.exchangeBaseUrl,
!ageRestricted ? undefined : ageRestricted,
+ Amounts.stringify(choosenAmount),
);
if (res.confirmTransferUrl) {
document.location.href = res.confirmTransferUrl;
@@ -395,9 +431,9 @@ function exchangeSelectionState(
onSuccess(res.transactionId);
}
} catch (e) {
- if (e instanceof TalerError) {
- setWithdrawError(e);
- }
+ console.error(e);
+ // if (e instanceof TalerError) {
+ // }
}
setDoingWithdraw(false);
}
@@ -427,7 +463,7 @@ function exchangeSelectionState(
const ageRestrictionOptions =
amountHook.response.ageRestrictionOptions?.reduce(
- (p, c) => ({ ...p, [c]: `under ${c}` }),
+ (p, c) => ({ ...p, [c]: i18n.str`under ${c}` }),
{} as Record<string, string>,
);
@@ -454,6 +490,7 @@ function exchangeSelectionState(
altCurrencies.length === 0
? []
: [toBeReceived.currency, ...altCurrencies];
+
const convAccount = amountHook.response.accounts.find((c) => {
return (
c.currencySpecification &&
@@ -480,7 +517,12 @@ function exchangeSelectionState(
},
conversionInfo,
withdrawalFee,
- chosenAmount,
+ amount: {
+ value: choosenAmount,
+ onInput: pushAlertOnError(async (v) => {
+ setChoosenAmount(v)
+ })
+ },
talerWithdrawUri,
ageRestriction,
doWithdrawal: {