support for exchange-withdraw call to action, pending use case when the user need to specify the amount
This commit is contained in:
parent
87fc6ebf48
commit
2779086a32
@ -84,7 +84,7 @@ function pageDefinition<T extends object>(pattern: string): PageLocation<T> {
|
||||
return { ...prev, [name]: cur };
|
||||
}, {} as Record<string, string>);
|
||||
|
||||
const f = (values: T): string => replaceAll(pattern, vars, values);
|
||||
const f = (values: T): string => replaceAll(pattern, vars, values ?? {});
|
||||
f.pattern = pattern;
|
||||
return f;
|
||||
}
|
||||
@ -152,6 +152,7 @@ const talerUriActionToPageName: {
|
||||
[TalerUriAction.PayPush]: "ctaTransferPickup",
|
||||
[TalerUriAction.Restore]: "ctaRecovery",
|
||||
[TalerUriAction.PayTemplate]: "ctaPayTemplate",
|
||||
[TalerUriAction.WithdrawExchange]: "ctaWithdrawManual",
|
||||
[TalerUriAction.DevExperiment]: undefined,
|
||||
[TalerUriAction.Exchange]: undefined,
|
||||
[TalerUriAction.Auditor]: undefined,
|
||||
@ -166,7 +167,11 @@ export function getPathnameForTalerURI(talerUri: string): string | undefined {
|
||||
if (!pageName) {
|
||||
return undefined;
|
||||
}
|
||||
return `${Pages[pageName]}?talerUri=${encodeURIComponent(talerUri)}`;
|
||||
const pageString: string =
|
||||
typeof Pages[pageName] === "function"
|
||||
? (Pages[pageName] as any)()
|
||||
: Pages[pageName];
|
||||
return `${pageString}?talerUri=${encodeURIComponent(talerUri)}`;
|
||||
}
|
||||
|
||||
export type PopupNavBarOptions = "balance" | "backup" | "dev";
|
||||
|
@ -16,20 +16,19 @@
|
||||
|
||||
import { AmountJson, ExchangeListItem } from "@gnu-taler/taler-util";
|
||||
import { Loading } from "../../components/Loading.js";
|
||||
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
||||
import { State as SelectExchangeState } from "../../hooks/useSelectedExchange.js";
|
||||
import { ButtonHandler, SelectFieldHandler } from "../../mui/handlers.js";
|
||||
import { compose, StateViewMap } from "../../utils/index.js";
|
||||
import { StateViewMap, compose } from "../../utils/index.js";
|
||||
import {
|
||||
useComponentStateFromParams,
|
||||
useComponentStateFromURI,
|
||||
} from "./state.js";
|
||||
|
||||
import { ErrorAlertView } from "../../components/CurrentAlerts.js";
|
||||
import { ErrorAlert } from "../../context/alert.js";
|
||||
import { ExchangeSelectionPage } from "../../wallet/ExchangeSelection/index.js";
|
||||
import { NoExchangesView } from "../../wallet/ExchangeSelection/views.js";
|
||||
import { SuccessView } from "./views.js";
|
||||
import { ErrorAlert } from "../../context/alert.js";
|
||||
import { ErrorAlertView } from "../../components/CurrentAlerts.js";
|
||||
import { SelectAmountView, SuccessView } from "./views.js";
|
||||
|
||||
export interface PropsFromURI {
|
||||
talerWithdrawUri: string | undefined;
|
||||
@ -38,6 +37,7 @@ export interface PropsFromURI {
|
||||
}
|
||||
|
||||
export interface PropsFromParams {
|
||||
talerExchangeWithdrawUri: string;
|
||||
amount: string;
|
||||
cancel: () => Promise<void>;
|
||||
onSuccess: (txid: string) => Promise<void>;
|
||||
@ -48,6 +48,7 @@ export type State =
|
||||
| State.LoadingUriError
|
||||
| SelectExchangeState.NoExchangeFound
|
||||
| SelectExchangeState.Selecting
|
||||
| State.SelectAmount
|
||||
| State.Success;
|
||||
|
||||
export namespace State {
|
||||
@ -60,6 +61,13 @@ export namespace State {
|
||||
error: ErrorAlert;
|
||||
}
|
||||
|
||||
export interface SelectAmount {
|
||||
status: "select-amount";
|
||||
error: undefined;
|
||||
currentExchange: ExchangeListItem;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
export type Success = {
|
||||
status: "success";
|
||||
error: undefined;
|
||||
@ -84,13 +92,14 @@ export namespace State {
|
||||
const viewMapping: StateViewMap<State> = {
|
||||
loading: Loading,
|
||||
error: ErrorAlertView,
|
||||
"select-amount": SelectAmountView,
|
||||
"no-exchange-found": NoExchangesView,
|
||||
"selecting-exchange": ExchangeSelectionPage,
|
||||
success: SuccessView,
|
||||
};
|
||||
|
||||
export const WithdrawPageFromURI = compose(
|
||||
"WithdrawPageFromURI",
|
||||
"WithdrawPageFromURI_Withdraw",
|
||||
(p: PropsFromURI) => useComponentStateFromURI(p),
|
||||
viewMapping,
|
||||
);
|
||||
|
@ -18,9 +18,12 @@
|
||||
import {
|
||||
AmountJson,
|
||||
Amounts,
|
||||
ExchangeFullDetails,
|
||||
ExchangeListItem,
|
||||
ExchangeTosStatus,
|
||||
TalerError,
|
||||
parseWithdrawExchangeUri,
|
||||
stringifyWithdrawUri,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { useState } from "preact/hooks";
|
||||
@ -33,6 +36,7 @@ import { RecursiveState } from "../../utils/index.js";
|
||||
import { PropsFromParams, PropsFromURI, State } from "./index.js";
|
||||
|
||||
export function useComponentStateFromParams({
|
||||
talerExchangeWithdrawUri: maybeTalerUri,
|
||||
amount,
|
||||
cancel,
|
||||
onSuccess,
|
||||
@ -44,7 +48,29 @@ export function useComponentStateFromParams({
|
||||
WalletApiOperation.ListExchanges,
|
||||
{},
|
||||
);
|
||||
return { amount: Amounts.parseOrThrow(amount), exchanges };
|
||||
const uri = parseWithdrawExchangeUri(maybeTalerUri);
|
||||
const exchangeByTalerUri = uri?.exchangeBaseUrl;
|
||||
let ex: ExchangeFullDetails | undefined;
|
||||
if (exchangeByTalerUri && uri.exchangePub) {
|
||||
await api.wallet.call(WalletApiOperation.AddExchange, {
|
||||
exchangeBaseUrl: exchangeByTalerUri,
|
||||
masterPub: uri.exchangePub,
|
||||
});
|
||||
const info = await api.wallet.call(
|
||||
WalletApiOperation.GetExchangeDetailedInfo,
|
||||
{
|
||||
exchangeBaseUrl: exchangeByTalerUri,
|
||||
},
|
||||
);
|
||||
|
||||
ex = info.exchange;
|
||||
}
|
||||
const chosenAmount = uri
|
||||
? uri.amount
|
||||
? Amounts.parseOrThrow(uri.amount)
|
||||
: Amounts.parseOrThrow(`${ex ? ex.currency : "KUDOS"}:66`)
|
||||
: Amounts.parseOrThrow(amount);
|
||||
return { amount: chosenAmount, exchanges, exchange: ex };
|
||||
});
|
||||
|
||||
if (!uriInfoHook) return { status: "loading", error: undefined };
|
||||
@ -60,6 +86,7 @@ export function useComponentStateFromParams({
|
||||
}
|
||||
|
||||
const chosenAmount = uriInfoHook.response.amount;
|
||||
const exchangeByTalerUri = uriInfoHook.response.exchange?.exchangeBaseUrl;
|
||||
const exchangeList = uriInfoHook.response.exchanges.exchanges;
|
||||
|
||||
async function doManualWithdraw(
|
||||
@ -92,7 +119,7 @@ export function useComponentStateFromParams({
|
||||
undefined,
|
||||
chosenAmount,
|
||||
exchangeList,
|
||||
undefined,
|
||||
exchangeByTalerUri,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -142,3 +142,12 @@ function WithdrawWithMobile({
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export function SelectAmountView({ currency }: State.SelectAmount): VNode {
|
||||
const { i18n } = useTranslationContext();
|
||||
return (
|
||||
<Fragment>
|
||||
<p>select the amount for ${currency}</p>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
@ -259,6 +259,7 @@ function openWalletURIFromPopup(uri: TalerUri): void {
|
||||
encodeURIComponent;
|
||||
let url: string | undefined = undefined;
|
||||
switch (uri.type) {
|
||||
case TalerUriAction.WithdrawExchange:
|
||||
case TalerUriAction.Withdraw:
|
||||
url = chrome.runtime.getURL(
|
||||
`static/wallet.html#/cta/withdraw?talerUri=${encodeURIComponent(
|
||||
|
@ -40,6 +40,7 @@ function ContentByUriType({
|
||||
}) {
|
||||
const { i18n } = useTranslationContext();
|
||||
switch (uri.type) {
|
||||
case TalerUriAction.WithdrawExchange:
|
||||
case TalerUriAction.Withdraw:
|
||||
return (
|
||||
<div>
|
||||
|
@ -391,9 +391,16 @@ export function Application(): VNode {
|
||||
/>
|
||||
<Route
|
||||
path={Pages.ctaWithdrawManual.pattern}
|
||||
component={({ amount }: { amount: string }) => (
|
||||
component={({
|
||||
amount,
|
||||
talerUri,
|
||||
}: {
|
||||
amount: string;
|
||||
talerUri: string;
|
||||
}) => (
|
||||
<CallToActionTemplate title={i18n.str`Digital cash withdrawal`}>
|
||||
<WithdrawPageFromParams
|
||||
talerExchangeWithdrawUri={talerUri}
|
||||
amount={amount}
|
||||
cancel={() => redirectTo(Pages.balance)}
|
||||
onSuccess={(tid: string) =>
|
||||
|
@ -250,13 +250,6 @@ export function SettingsView({
|
||||
<EnabledBySettings name="advanceMode">
|
||||
<AdvanceSettings />
|
||||
</EnabledBySettings>
|
||||
<Checkbox
|
||||
label={i18n.str`Lang selector`}
|
||||
name="langSelector"
|
||||
description={i18n.str`Allows to manually change the language of the UI. Otherwise it will be automatically selected by your browser configuration.`}
|
||||
enabled={langToggle.value!}
|
||||
onToggle={langToggle.button.onClick!}
|
||||
/>
|
||||
<EnabledBySettings name="langSelector">
|
||||
<SubTitle>
|
||||
<i18n.Translate>Display</i18n.Translate>
|
||||
@ -340,6 +333,10 @@ function AdvanceSettings(): VNode {
|
||||
label: i18n.str`Allow batch withdrawals`,
|
||||
description: i18n.str`Using the batch withdrawal API allows faster withdrawals (wallet restart required)`,
|
||||
},
|
||||
langSelector: {
|
||||
label: i18n.str`Lang selector`,
|
||||
description: i18n.str`Allows to manually change the language of the UI. Otherwise it will be automatically selected by your browser configuration.`,
|
||||
},
|
||||
};
|
||||
return (
|
||||
<Fragment>
|
||||
|
Loading…
Reference in New Issue
Block a user