aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-08-09 13:19:17 -0300
committerSebastian <sebasjm@gmail.com>2024-08-09 13:19:17 -0300
commit78d6fdb04de336fab8fe85210c7f76c90eb2d424 (patch)
treeb1c973506a630769021651ae6137d39837107b6b
parent93f1f9867a6f5681df847d60efca4828f5d49deb (diff)
downloadwallet-core-78d6fdb04de336fab8fe85210c7f76c90eb2d424.tar.xz
fix #8871
-rw-r--r--packages/taler-wallet-webextension/src/NavigationBar.tsx8
-rw-r--r--packages/taler-wallet-webextension/src/cta/Deposit/index.ts10
-rw-r--r--packages/taler-wallet-webextension/src/cta/Deposit/state.ts68
-rw-r--r--packages/taler-wallet-webextension/src/cta/Deposit/stories.tsx6
-rw-r--r--packages/taler-wallet-webextension/src/cta/Deposit/test.ts71
-rw-r--r--packages/taler-wallet-webextension/src/cta/Deposit/views.tsx40
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Application.tsx111
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts4
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts7
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts14
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts59
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DestinationSelection/stories.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx50
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts6
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts10
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Transaction.tsx2
16 files changed, 249 insertions, 219 deletions
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx
index d045bc1e3..7d469ed7e 100644
--- a/packages/taler-wallet-webextension/src/NavigationBar.tsx
+++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx
@@ -112,6 +112,9 @@ export const Pages = {
balanceTransaction: pageDefinition<{ tid: string }>(
"/balance/transaction/:tid",
),
+ bankManange: pageDefinition<{ scope: CrockEncodedString}>(
+ "/bank/manage/:scope",
+ ),
balanceDeposit: pageDefinition<{
scope: CrockEncodedString;
}>("/balance/deposit/:scope"),
@@ -151,7 +154,10 @@ export const Pages = {
ctaRecovery: "/cta/recovery",
ctaRefund: "/cta/refund",
ctaWithdraw: "/cta/withdraw",
- ctaDeposit: "/cta/deposit",
+ ctaDeposit: pageDefinition<{
+ scope: CrockEncodedString;
+ account: CrockEncodedString,
+ }>("/cta/deposit/:scope/:account"),
ctaExperiment: "/cta/experiment",
ctaAddExchange: "/cta/add/exchange",
ctaInvoiceCreate: pageDefinition<{
diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/index.ts b/packages/taler-wallet-webextension/src/cta/Deposit/index.ts
index 6b228188b..d6a14f3dc 100644
--- a/packages/taler-wallet-webextension/src/cta/Deposit/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Deposit/index.ts
@@ -14,18 +14,18 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { AmountJson, AmountString } from "@gnu-taler/taler-util";
+import { AmountJson, AmountString, PaytoUri, ScopeInfo } from "@gnu-taler/taler-util";
import { ErrorAlertView } from "../../components/CurrentAlerts.js";
import { Loading } from "../../components/Loading.js";
import { ErrorAlert } from "../../context/alert.js";
-import { ButtonHandler } from "../../mui/handlers.js";
+import { AmountFieldHandler, ButtonHandler } from "../../mui/handlers.js";
import { compose, StateViewMap } from "../../utils/index.js";
import { useComponentState } from "./state.js";
import { ReadyView } from "./views.js";
export interface Props {
- talerDepositUri: string | undefined;
- amountStr: AmountString | undefined;
+ account: PaytoUri;
+ scope: ScopeInfo;
cancel: () => Promise<void>;
onSuccess: (tx: string) => Promise<void>;
}
@@ -44,7 +44,9 @@ export namespace State {
export interface Ready {
status: "ready";
error: undefined;
+ amount: AmountFieldHandler;
fee: AmountJson;
+ account: PaytoUri;
cost: AmountJson;
effective: AmountJson;
confirm: ButtonHandler;
diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/state.ts b/packages/taler-wallet-webextension/src/cta/Deposit/state.ts
index efcef8c28..e599b03f0 100644
--- a/packages/taler-wallet-webextension/src/cta/Deposit/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/Deposit/state.ts
@@ -14,52 +14,54 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { Amounts } from "@gnu-taler/taler-util";
+import { Amounts, stringifyPaytoUri } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { alertFromError, useAlertContext } from "../../context/alert.js";
import { useBackendContext } from "../../context/backend.js";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { Props, State } from "./index.js";
+import { useState } from "preact/hooks";
export function useComponentState({
- talerDepositUri,
- amountStr,
+ account,
+ scope,
cancel,
onSuccess,
}: Props): State {
const api = useBackendContext();
const { pushAlertOnError } = useAlertContext();
- const info = useAsyncAsHook(async () => {
- if (!talerDepositUri) throw Error("ERROR_NO-URI-FOR-DEPOSIT");
- if (!amountStr) throw Error("ERROR_NO-AMOUNT-FOR-DEPOSIT");
- const amount = Amounts.parse(amountStr);
- if (!amount) throw Error("ERROR_INVALID-AMOUNT-FOR-DEPOSIT");
+ const [amount, setAmount] = useState(Amounts.zeroOfCurrency(scope.currency))
+ const amountStr = Amounts.stringify(amount);
+
+ const hook = useAsyncAsHook(async () => {
const deposit = await api.wallet.call(WalletApiOperation.PrepareDeposit, {
- amount: Amounts.stringify(amount),
- depositPaytoUri: talerDepositUri,
+ amount: amountStr,
+ depositPaytoUri: stringifyPaytoUri(account),
});
- return { deposit, uri: talerDepositUri, amount };
- });
- const { i18n } = useTranslationContext();
+ return deposit;
+ }, [amountStr]);
+ // const { i18n } = useTranslationContext();
- if (!info) return { status: "loading", error: undefined };
- if (info.hasError) {
- return {
- status: "error",
- error: alertFromError(
- i18n,
- i18n.str`Could not load the status of deposit`,
- info,
- ),
- };
- }
+ // if (!hook) return { status: "loading", error: undefined };
+ // if (hook.hasError) {
+ // return {
+ // status: "error",
+ // error: alertFromError(
+ // i18n,
+ // i18n.str`Could not load the status of deposit`,
+ // hook,
+ // ),
+ // };
+ // }
- const { deposit, uri, amount } = info.response;
+ const debitAmount = !hook || hook.hasError ? Amounts.zeroOfCurrency(scope.currency) : Amounts.parseOrThrow(hook.response.effectiveDepositAmount);
+ const toBeReceived = !hook || hook.hasError ? Amounts.zeroOfCurrency(scope.currency) : Amounts.parseOrThrow(hook.response.totalDepositCost);
+ // const { deposit, uri, amount } = hook.response;
async function doDeposit(): Promise<void> {
const resp = await api.wallet.call(WalletApiOperation.CreateDepositGroup, {
- amount: Amounts.stringify(amount),
- depositPaytoUri: uri,
+ amount: amountStr,
+ depositPaytoUri: stringifyPaytoUri(account),
});
onSuccess(resp.transactionId);
}
@@ -67,13 +69,19 @@ export function useComponentState({
return {
status: "ready",
error: undefined,
+ account,
+ amount: {
+ value: amount,
+ onInput: pushAlertOnError(async (e) => setAmount(e)),
+ error: Amounts.isZero(amount) ? "Can't be zero" : undefined,
+ },
confirm: {
onClick: pushAlertOnError(doDeposit),
},
- fee: Amounts.sub(deposit.totalDepositCost, deposit.effectiveDepositAmount)
+ fee: Amounts.sub(toBeReceived, debitAmount)
.amount,
- cost: Amounts.parseOrThrow(deposit.totalDepositCost),
- effective: Amounts.parseOrThrow(deposit.effectiveDepositAmount),
+ cost: Amounts.parseOrThrow(toBeReceived),
+ effective: Amounts.parseOrThrow(debitAmount),
cancel,
};
}
diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/stories.tsx b/packages/taler-wallet-webextension/src/cta/Deposit/stories.tsx
index cd65ce8e1..aacb7b03d 100644
--- a/packages/taler-wallet-webextension/src/cta/Deposit/stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Deposit/stories.tsx
@@ -19,7 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { Amounts } from "@gnu-taler/taler-util";
+import { Amounts, parsePaytoUri } from "@gnu-taler/taler-util";
import * as tests from "@gnu-taler/web-util/testing";
import { ReadyView } from "./views.js";
@@ -30,6 +30,10 @@ export default {
export const Ready = tests.createExample(ReadyView, {
status: "ready",
confirm: {},
+ amount: {
+ value: Amounts.parseOrThrow("EUR:1")
+ },
+ account: parsePaytoUri("payto://iban/DE1231231231")!,
cost: Amounts.parseOrThrow("EUR:1.2"),
effective: Amounts.parseOrThrow("EUR:1"),
fee: Amounts.parseOrThrow("EUR:0.2"),
diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/test.ts b/packages/taler-wallet-webextension/src/cta/Deposit/test.ts
index 100929918..be4c1edd1 100644
--- a/packages/taler-wallet-webextension/src/cta/Deposit/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Deposit/test.ts
@@ -19,7 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { AmountString, Amounts } from "@gnu-taler/taler-util";
+import { AmountString, Amounts, ScopeType, parsePayUri, parsePaytoUri } from "@gnu-taler/taler-util";
import { expect } from "chai";
import { createWalletApiMock } from "../../test-utils.js";
import { useComponentState } from "./state.js";
@@ -28,42 +28,6 @@ import { Props } from "./index.js";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
describe("Deposit CTA states", () => {
- it("should tell the user that the URI is missing", async () => {
- const { handler, TestingContext } = createWalletApiMock();
-
- const props: Props = {
- talerDepositUri: undefined,
- amountStr: undefined,
- cancel: async () => {
- null;
- },
- onSuccess: async () => {
- null;
- },
- };
-
- const hookBehavior = await tests.hookBehaveLikeThis(
- useComponentState,
- props,
- [
- ({ status }) => {
- expect(status).equals("loading");
- },
- ({ status, error }) => {
- expect(status).equals("error");
-
- if (!error) expect.fail();
- // if (!error.hasError) expect.fail();
- // if (error.operational) expect.fail();
- expect(error.description).eq("ERROR_NO-URI-FOR-DEPOSIT");
- },
- ],
- TestingContext,
- );
-
- expect(hookBehavior).deep.equal({ result: "ok" });
- expect(handler.getCallingQueueState()).eq("empty");
- });
it("should be ready after loading", async () => {
const { handler, TestingContext } = createWalletApiMock();
@@ -72,19 +36,22 @@ describe("Deposit CTA states", () => {
WalletApiOperation.PrepareDeposit,
undefined,
{
- effectiveDepositAmount: "EUR:1" as AmountString,
- totalDepositCost: "EUR:1.2" as AmountString,
+ effectiveDepositAmount: "EUR:0" as AmountString,
+ totalDepositCost: "EUR:0" as AmountString,
fees: {
coin: "EUR:0" as AmountString,
- refresh: "EUR:0.2" as AmountString,
+ refresh: "EUR:0" as AmountString,
wire: "EUR:0" as AmountString,
},
},
);
const props = {
- talerDepositUri: "payto://refund/asdasdas",
- amountStr: "EUR:1" as AmountString,
+ account: parsePaytoUri("payto://refund/asdasdas")!,
+ scope: {
+ type: ScopeType.Global as const,
+ currency: "EUR",
+ },
cancel: async () => {
null;
},
@@ -97,16 +64,26 @@ describe("Deposit CTA states", () => {
useComponentState,
props,
[
- ({ status }) => {
- expect(status).equals("loading");
+ // ({ status }) => {
+ // expect(status).equals("loading");
+ // },
+ (state) => {
+ if (state.status !== "ready") expect.fail();
+ if (state.error) expect.fail();
+ expect(state.confirm.onClick).not.undefined;
+ expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
+ expect(state.cost).deep.eq(Amounts.parseOrThrow("EUR:0"));
+ expect(state.fee).deep.eq(Amounts.parseOrThrow("EUR:0"));
+ expect(state.effective).deep.eq(Amounts.parseOrThrow("EUR:0"));
},
(state) => {
if (state.status !== "ready") expect.fail();
if (state.error) expect.fail();
expect(state.confirm.onClick).not.undefined;
- expect(state.cost).deep.eq(Amounts.parseOrThrow("EUR:1.2"));
- expect(state.fee).deep.eq(Amounts.parseOrThrow("EUR:0.2"));
- expect(state.effective).deep.eq(Amounts.parseOrThrow("EUR:1"));
+ expect(state.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0"));
+ expect(state.cost).deep.eq(Amounts.parseOrThrow("EUR:0"));
+ expect(state.fee).deep.eq(Amounts.parseOrThrow("EUR:0"));
+ expect(state.effective).deep.eq(Amounts.parseOrThrow("EUR:0"));
},
],
TestingContext,
diff --git a/packages/taler-wallet-webextension/src/cta/Deposit/views.tsx b/packages/taler-wallet-webextension/src/cta/Deposit/views.tsx
index c683a755c..3e76b4789 100644
--- a/packages/taler-wallet-webextension/src/cta/Deposit/views.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Deposit/views.tsx
@@ -14,12 +14,13 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { Amounts } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, h, VNode } from "preact";
import { Amount } from "../../components/Amount.js";
-import { Part } from "../../components/Part.js";
+import { AmountField } from "../../components/AmountField.js";
+import { Part, PartPayto } from "../../components/Part.js";
import { Button } from "../../mui/Button.js";
+import { DepositDetails, getAmountWithFee } from "../../wallet/Transaction.js";
import { State } from "./index.js";
/**
@@ -32,29 +33,24 @@ export function ReadyView(state: State.Ready): VNode {
return (
<Fragment>
- <section>
- {Amounts.isNonZero(state.cost) && (
- <Part
- big
- title={i18n.str`Cost`}
- text={<Amount value={state.cost} />}
- kind="negative"
- />
- )}
- {Amounts.isNonZero(state.fee) && (
- <Part
- big
- title={i18n.str`Fee`}
- text={<Amount value={state.fee} />}
- kind="negative"
+ <section style={{ textAlign: "left" }}>
+ <p>
+ <AmountField
+ label={i18n.str`Amount`}
+ handler={state.amount}
+ required
/>
- )}
+ </p>
+ <PartPayto kind="neutral" payto={state.account} />
<Part
- big
- title={i18n.str`To be received`}
- text={<Amount value={state.effective} />}
- kind="positive"
+ title={i18n.str`Details`}
+ text={
+ <DepositDetails
+ amount={getAmountWithFee(state.cost, state.effective, "debit")}
+ />
+ }
/>
+
</section>
<section>
<Button
diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx b/packages/taler-wallet-webextension/src/wallet/Application.tsx
index 1b14236d5..b4044beca 100644
--- a/packages/taler-wallet-webextension/src/wallet/Application.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx
@@ -26,8 +26,10 @@ import {
TalerUri,
TalerUriAction,
TranslatedString,
+ parsePaytoUri,
parseScopeInfoShort,
parseTalerUri,
+ stringifyPaytoUri,
stringifyScopeInfoShort,
stringifyTalerUri,
} from "@gnu-taler/taler-util";
@@ -92,6 +94,7 @@ import { WalletActivity } from "../components/WalletActivity.js";
import { EnabledBySettings } from "../components/EnabledBySettings.js";
import { DevExperimentPage } from "../cta/DevExperiment/index.js";
import { ConfirmAddExchangeView } from "./AddExchange/views.js";
+import { ManageAccountPage } from "./ManageAccount/index.js";
export function Application(): VNode {
const { i18n } = useTranslationContext();
@@ -249,9 +252,17 @@ export function Application(): VNode {
<DestinationSelectionPage
type="send"
scope={s}
- goToWalletBankDeposit={(s) =>
+ goToWalletKnownBankDeposit={(s, p) =>
redirectTo(
- Pages.balanceDeposit({
+ Pages.ctaDeposit({
+ scope: encodeCrockForURI(stringifyScopeInfoShort(s)),
+ account: encodeCrockForURI(stringifyPaytoUri(p)),
+ }),
+ )
+ }
+ goToWalletNewBankDeposit={(s) =>
+ redirectTo(
+ Pages.bankManange({
scope: encodeCrockForURI(stringifyScopeInfoShort(s)),
}),
)
@@ -269,6 +280,34 @@ export function Application(): VNode {
}}
/>
<Route
+ path={Pages.bankManange.pattern}
+ component={({
+ scope,
+ }: {
+ scope?: string;
+ }) => {
+ const s = !scope ? undefined : parseScopeInfoShort(decodeCrockFromURI(scope));
+ if (!s) return <div>missing scope</div>
+
+ return (
+ <WalletTemplate path="balance" goToURL={redirectToURL}>
+ <ManageAccountPage
+ scope={s}
+ onAccountAdded={(account) => redirectTo(Pages.ctaDeposit({
+ scope: encodeCrockForURI(stringifyScopeInfoShort(s)),
+ account: encodeCrockForURI(stringifyPaytoUri(account)),
+ }))}
+ onCancel={() => {
+ redirectTo(Pages.balanceHistory({
+ scope: encodeCrockForURI(stringifyScopeInfoShort(s)),
+ }))
+ }}
+ />
+ </WalletTemplate>
+ );
+ }}
+ />
+ <Route
path={Pages.receiveCashForPurchase.pattern}
component={({ id: _purchaseId }: { id?: string }) => {
return (
@@ -354,24 +393,24 @@ export function Application(): VNode {
return <div>missing scope</div>
}
return <WalletTemplate path="balance" goToURL={redirectToURL}>
- <DepositPage
- scope={s}
- onCancel={(scope: ScopeInfo) => {
- redirectTo(
- Pages.balanceHistory({
- scope: encodeCrockForURI(stringifyScopeInfoShort(scope)),
- }),
- );
- }}
- onSuccess={(scope: ScopeInfo) => {
- redirectTo(
- Pages.balanceHistory({
- scope: encodeCrockForURI(stringifyScopeInfoShort(scope)),
- }),
- );
- }}
- />
- </WalletTemplate>
+ <DepositPage
+ scope={s}
+ onCancel={(scope: ScopeInfo) => {
+ redirectTo(
+ Pages.balanceHistory({
+ scope: encodeCrockForURI(stringifyScopeInfoShort(scope)),
+ }),
+ );
+ }}
+ onSuccess={(scope: ScopeInfo) => {
+ redirectTo(
+ Pages.balanceHistory({
+ scope: encodeCrockForURI(stringifyScopeInfoShort(scope)),
+ }),
+ );
+ }}
+ />
+ </WalletTemplate>
}}
/>
@@ -564,25 +603,35 @@ export function Application(): VNode {
}}
/>
<Route
- path={Pages.ctaDeposit}
+ path={Pages.ctaDeposit.pattern}
component={({
- amount,
- talerUri,
+ scope,
+ account,
}: {
- amount: string;
- talerUri: string;
- }) => (
- <CallToActionTemplate title={i18n.str`Digital cash deposit`}>
+ scope: string,
+ account: string;
+ }) => {
+ const s = parseScopeInfoShort(decodeCrockFromURI(scope))
+ if (!s) {
+ return <div>missing scope</div>
+ }
+ const p = parsePaytoUri(decodeCrockFromURI(account))
+ if (!p) {
+ return <div>missing account</div>
+ }
+
+ return <CallToActionTemplate title={i18n.str`Digital cash deposit`} >
<DepositPageCTA
- amountStr={Amounts.stringify(Amounts.parseOrThrow(amount))}
- talerDepositUri={decodeCrockFromURI(talerUri)}
+ scope={s}
+ account={p}
cancel={() => redirectTo(Pages.balance)}
onSuccess={(tid: string) =>
redirectTo(Pages.balanceTransaction({ tid }))
}
/>
</CallToActionTemplate>
- )}
+ }
+ }
/>
<Route
path={Pages.ctaInvoiceCreate.pattern}
@@ -711,7 +760,7 @@ export function Application(): VNode {
<WalletActivity />
</EnabledBySettings>
</IoCProviderForRuntime>
- </TranslationProvider>
+ </TranslationProvider >
);
}
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
index e26992688..22ad1c1e7 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts
@@ -62,8 +62,8 @@ export namespace State {
export interface AddingAccount {
status: "manage-account";
error: undefined;
- currency: string;
- onAccountAdded: (p: string) => void;
+ scope: ScopeInfo;
+ onAccountAdded: (p: PaytoUri) => void;
onCancel: () => void;
}
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
index 37f078ff6..29f533385 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts
@@ -42,7 +42,6 @@ export function useComponentState({
const zero = Amounts.zeroOfCurrency(scope.currency);
-
const hook = useAsyncAsHook(async () => {
const { balances } = await api.wallet.call(
WalletApiOperation.GetBalances,
@@ -91,9 +90,9 @@ export function useComponentState({
return {
status: "manage-account",
error: undefined,
- currency: scope.currency,
- onAccountAdded: (p: string) => {
- updateAccountFromList(p);
+ scope,
+ onAccountAdded: (p: PaytoUri) => {
+ updateAccountFromList(stringifyPaytoUri(p));
setAddingAccount(false);
hook.retry();
},
diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts
index befff87ff..eeb972c08 100644
--- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/index.ts
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { AmountJson, ScopeInfo } from "@gnu-taler/taler-util";
+import { AmountJson, KnownBankAccountsInfo, PaytoUri, ScopeInfo } from "@gnu-taler/taler-util";
import { ErrorAlertView } from "../../components/CurrentAlerts.js";
import { Loading } from "../../components/Loading.js";
import { ErrorAlert } from "../../context/alert.js";
@@ -37,7 +37,8 @@ interface PropsGet {
interface PropsSend {
type: "send";
scope: ScopeInfo;
- goToWalletBankDeposit: (s:ScopeInfo) => void;
+ goToWalletKnownBankDeposit: (s:ScopeInfo, p: PaytoUri) => void;
+ goToWalletNewBankDeposit: (s:ScopeInfo) => void;
goToWalletWalletSend: (s:ScopeInfo) => void;
}
@@ -69,18 +70,13 @@ export namespace State {
status: "ready";
error: undefined;
type: Props["type"];
- selectCurrency: ButtonHandler;
- previous: Contact[];
+ onSelectAccount: (p:PaytoUri) => void;
+ previous: KnownBankAccountsInfo[];
goToBank: ButtonHandler;
goToWallet: ButtonHandler;
}
}
-export type Contact = {
- icon_type: string;
- name: string;
- description: string;
-};
const viewMapping: StateViewMap<State> = {
loading: Loading,
diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts
index e138b28fb..de2d439b6 100644
--- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/state.ts
@@ -15,9 +15,9 @@
*/
import {
- AmountJson,
- Amounts,
ExchangeUpdateStatus,
+ KnownBankAccountsInfo,
+ PaytoUri,
ScopeType,
parseScopeInfoShort,
stringifyScopeInfoShort
@@ -29,43 +29,24 @@ import { alertFromError, useAlertContext } from "../../context/alert.js";
import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { RecursiveState, assertUnreachable } from "../../utils/index.js";
-import { Contact, Props, State } from "./index.js";
+import { Props, State } from "./index.js";
export function useComponentState(props: Props): RecursiveState<State> {
const api = useBackendContext();
const { pushAlertOnError } = useAlertContext();
+ const { i18n } = useTranslationContext();
const [scope, setScope] = useState(props.scope);
- // const scopeStr = !scope ? undefined : stringifyScopeInfoShort(scope);
- // useEffect(() => {
- // if (!scope) return;
- // if (!amount) {
- // setAmount(Amounts.zeroOfCurrency(scope.currency));
- // }
- // }, [scopeStr]);
+ const hook = useAsyncAsHook(async () => {
+ const resp = await api.wallet.call(
+ WalletApiOperation.ListKnownBankAccounts,
+ {},
+ );
+ return resp
+ });
- //FIXME: get this information from wallet
- // eslint-disable-next-line no-constant-condition
- const previous: Contact[] = true
- ? []
- : [
- {
- name: "International Bank",
- icon_type: "bank",
- description: "account ending with 3454",
- },
- {
- name: "Max",
- icon_type: "bank",
- description: "account ending with 3454",
- },
- {
- name: "Alex",
- icon_type: "bank",
- description: "account ending with 3454",
- },
- ];
+ const previous: KnownBankAccountsInfo[] = props.type === "send" && hook && !hook.hasError ? hook.response.accounts : [];
if (!scope) {
return () => {
@@ -144,14 +125,12 @@ export function useComponentState(props: Props): RecursiveState<State> {
status: "ready",
error: undefined,
previous,
- selectCurrency: {
- onClick: pushAlertOnError(async () => {
- setScope(undefined);
- }),
- },
+ onSelectAccount: pushAlertOnError(async (account: PaytoUri) => {
+ props.goToWalletKnownBankDeposit(scope, account);
+ }),
goToBank: {
onClick: pushAlertOnError(async () => {
- props.goToWalletBankDeposit(scope);
+ props.goToWalletNewBankDeposit(scope);
}),
},
goToWallet: {
@@ -166,16 +145,12 @@ export function useComponentState(props: Props): RecursiveState<State> {
status: "ready",
error: undefined,
previous,
- selectCurrency: {
- onClick: pushAlertOnError(async () => {
- setScope(undefined);
- }),
- },
goToBank: {
onClick: pushAlertOnError(async () => {
props.goToWalletManualWithdraw(scope);
}),
},
+ onSelectAccount: () => { },
goToWallet: {
onClick: pushAlertOnError(async () => {
props.goToWalletWalletInvoice(scope);
diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/stories.tsx b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/stories.tsx
index 0e68f2019..c530a7020 100644
--- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/stories.tsx
@@ -30,14 +30,12 @@ export const GetCash = tests.createExample(ReadyView, {
goToBank: {},
goToWallet: {},
previous: [],
- selectCurrency: {},
type: "get",
});
export const SendCash = tests.createExample(ReadyView, {
goToBank: {},
goToWallet: {},
previous: [],
- selectCurrency: {},
type: "send",
});
diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx
index cc368992d..cf34ceb35 100644
--- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx
@@ -14,11 +14,10 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+import { KnownBankAccountsInfo, PaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { styled } from "@linaria/react";
import { Fragment, h, VNode } from "preact";
-import { AmountField } from "../../components/AmountField.js";
-import { EnabledBySettings } from "../../components/EnabledBySettings.js";
import { SelectList } from "../../components/SelectList.js";
import {
Input,
@@ -33,7 +32,7 @@ import { Pages } from "../../NavigationBar.js";
import arrowIcon from "../../svg/chevron-down.inline.svg";
import bankIcon from "../../svg/ri-bank-line.inline.svg";
import { assertUnreachable } from "../../utils/index.js";
-import { Contact, State } from "./index.js";
+import { State } from "./index.js";
export function SelectCurrencyView({
currencies,
@@ -81,7 +80,6 @@ const Container = styled.div`
const ContactTable = styled.table`
width: 100%;
& > tr > td {
- padding: 8px;
& > div:not([data-disabled]):hover {
background-color: lightblue;
}
@@ -266,6 +264,7 @@ export function ReadyGetView({
}
export function ReadySendView({
goToBank,
+ onSelectAccount,
goToWallet,
previous,
}: State.Ready): VNode {
@@ -291,6 +290,9 @@ export function ReadySendView({
<td>
<RowExample
info={info}
+ onClick={() => {
+ onSelectAccount(info.uri)
+ }}
// disabled={!amountHandler.onInput}
/>
</td>
@@ -331,31 +333,31 @@ export function ReadySendView({
function RowExample({
info,
disabled,
+ onClick
}: {
- info: Contact;
+ info: KnownBankAccountsInfo;
disabled?: boolean;
+ onClick?: () => void;
}): VNode {
- const icon = info.icon_type === "bank" ? bankIcon : undefined;
+
+
return (
- <MediaExample data-disabled={disabled}>
+ <MediaExample data-disabled={disabled} onClick={onClick}>
<MediaLeft>
<CircleDiv>
- {icon !== undefined ? (
<SvgIcon
- title={info.name}
+ title={info.alias}
dangerouslySetInnerHTML={{
- __html: icon,
+ __html: bankIcon,
}}
color="currentColor"
/>
- ) : (
- <span>A</span>
- )}
+
</CircleDiv>
</MediaLeft>
<MediaBody>
- <span>{info.name}</span>
- <LightText>{info.description}</LightText>
+ <span>{info.alias}</span>
+ <LightText>{describeAccount(info.uri)}</LightText>
</MediaBody>
<MediaRight>
<SvgIcon
@@ -368,3 +370,21 @@ function RowExample({
</MediaExample>
);
}
+
+
+function describeAccount(p: PaytoUri): string {
+ if (!p.isKnown) {
+ return stringifyPaytoUri(p)
+ }
+ switch (p.targetType) {
+ case "iban": {
+ return p.iban
+ }
+ case "x-taler-bank": {
+ return `${p.host}/${p.account}`
+ }
+ case "bitcoin": {
+ return `${p.address}`
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts b/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts
index 3a00d48ce..a76d77709 100644
--- a/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/index.ts
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { KnownBankAccountsInfo } from "@gnu-taler/taler-util";
+import { KnownBankAccountsInfo, PaytoUri, ScopeInfo } from "@gnu-taler/taler-util";
import { ErrorAlertView } from "../../components/CurrentAlerts.js";
import { Loading } from "../../components/Loading.js";
import { ErrorAlert } from "../../context/alert.js";
@@ -28,8 +28,8 @@ import { useComponentState } from "./state.js";
import { ReadyView } from "./views.js";
export interface Props {
- currency: string;
- onAccountAdded: (uri: string) => void;
+ scope: ScopeInfo;
+ onAccountAdded: (uri: PaytoUri) => void;
onCancel: () => void;
}
diff --git a/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
index a7b2fe90f..09abf92ac 100644
--- a/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
@@ -29,7 +29,7 @@ import { AccountByType, Props, State } from "./index.js";
import { useSettings } from "../../hooks/useSettings.js";
export function useComponentState({
- currency,
+ scope,
onAccountAdded,
onCancel,
}: Props): State {
@@ -37,7 +37,7 @@ export function useComponentState({
const { pushAlertOnError } = useAlertContext();
const { i18n } = useTranslationContext();
const hook = useAsyncAsHook(() =>
- api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency }),
+ api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency: scope.currency }),
);
const accountType: Record<string, string> = {
iban: "IBAN",
@@ -80,10 +80,10 @@ export function useComponentState({
const normalizedPayto = stringifyPaytoUri(uri);
await api.wallet.call(WalletApiOperation.AddKnownBankAccounts, {
alias,
- currency,
+ currency: scope.currency,
payto: normalizedPayto,
});
- onAccountAdded(payto);
+ onAccountAdded(uri);
}
const paytoUriError = found ? "that account is already present" : undefined;
@@ -112,7 +112,7 @@ export function useComponentState({
return {
status: "ready",
error: undefined,
- currency,
+ currency:scope.currency,
accountType: {
list: accountType,
value: type,
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index df025f570..73c26eaef 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -1799,7 +1799,7 @@ function TrackingDepositDetails({
);
}
-function DepositDetails({ amount }: { amount: AmountWithFee }): VNode {
+export function DepositDetails({ amount }: { amount: AmountWithFee }): VNode {
const { i18n } = useTranslationContext();
return (