From 88618df7b870732f4f29a80686dd4f4cf20887f8 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 22 Nov 2022 15:43:39 -0300 Subject: amount field --- .../src/wallet/CreateManualWithdraw.stories.tsx | 58 ----- .../src/wallet/CreateManualWithdraw.test.ts | 232 ----------------- .../src/wallet/CreateManualWithdraw.tsx | 282 --------------------- .../src/wallet/DepositPage/index.ts | 3 +- .../src/wallet/DepositPage/state.ts | 55 ++-- .../src/wallet/DepositPage/stories.tsx | 6 +- .../src/wallet/DepositPage/test.ts | 14 +- .../src/wallet/DepositPage/views.tsx | 7 +- .../src/wallet/DestinationSelection.tsx | 33 +-- .../src/wallet/ExchangeSelection/state.ts | 13 +- .../src/wallet/ManualWithdrawPage.tsx | 141 ----------- .../src/wallet/index.stories.tsx | 2 - 12 files changed, 62 insertions(+), 784 deletions(-) delete mode 100644 packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx delete mode 100644 packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts delete mode 100644 packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx delete mode 100644 packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx (limited to 'packages/taler-wallet-webextension/src/wallet') diff --git a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx deleted file mode 100644 index 2154d35de..000000000 --- a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.stories.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - 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 - */ - -/** - * - * @author Sebastian Javier Marchano (sebasjm) - */ - -import { createExample } from "../test-utils.js"; -import { CreateManualWithdraw as TestedComponent } from "./CreateManualWithdraw.js"; - -export default { - title: "wallet/manual withdraw/creation", - component: TestedComponent, - argTypes: {}, -}; - -// , -const exchangeUrlWithCurrency = { - "http://exchange.taler:8081": "COL", - "http://exchange.tal": "EUR", -}; - -export const WithoutAnyExchangeKnown = createExample(TestedComponent, { - exchangeUrlWithCurrency: {}, -}); - -export const InitialState = createExample(TestedComponent, { - exchangeUrlWithCurrency, -}); - -export const WithAmountInitialized = createExample(TestedComponent, { - initialAmount: "10", - exchangeUrlWithCurrency, -}); - -export const WithExchangeError = createExample(TestedComponent, { - error: "The exchange url seems invalid", - exchangeUrlWithCurrency, -}); - -export const WithAmountError = createExample(TestedComponent, { - initialAmount: "e", - exchangeUrlWithCurrency, -}); diff --git a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts deleted file mode 100644 index 37c50285b..000000000 --- a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts +++ /dev/null @@ -1,232 +0,0 @@ -/* - 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 - */ - -/** - * - * @author Sebastian Javier Marchano (sebasjm) - */ - -import { expect } from "chai"; -import { SelectFieldHandler, TextFieldHandler } from "../mui/handlers.js"; -import { mountHook } from "../test-utils.js"; -import { useComponentState } from "./CreateManualWithdraw.js"; - -const exchangeListWithARSandUSD = { - url1: "USD", - url2: "ARS", - url3: "ARS", -}; - -const exchangeListEmpty = {}; - -describe("CreateManualWithdraw states", () => { - it("should set noExchangeFound when exchange list is empty", () => { - const { pullLastResultOrThrow } = mountHook(() => - useComponentState(exchangeListEmpty, undefined, undefined), - ); - - const { noExchangeFound } = pullLastResultOrThrow(); - - expect(noExchangeFound).equal(true); - }); - - it("should set noExchangeFound when exchange list doesn't include selected currency", () => { - const { pullLastResultOrThrow } = mountHook(() => - useComponentState(exchangeListWithARSandUSD, undefined, "COL"), - ); - - const { noExchangeFound } = pullLastResultOrThrow(); - - expect(noExchangeFound).equal(true); - }); - - it("should select the first exchange from the list", () => { - const { pullLastResultOrThrow } = mountHook(() => - useComponentState(exchangeListWithARSandUSD, undefined, undefined), - ); - - const { exchange } = pullLastResultOrThrow(); - - expect(exchange.value).equal("url1"); - }); - - it("should select the first exchange with the selected currency", () => { - const { pullLastResultOrThrow } = mountHook(() => - useComponentState(exchangeListWithARSandUSD, undefined, "ARS"), - ); - - const { exchange } = pullLastResultOrThrow(); - - expect(exchange.value).equal("url2"); - }); - - it("should change the exchange when currency change", async () => { - const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() => - useComponentState(exchangeListWithARSandUSD, undefined, "ARS"), - ); - - { - const { exchange, currency } = pullLastResultOrThrow(); - - expect(exchange.value).equal("url2"); - if (currency.onChange === undefined) expect.fail(); - currency.onChange("USD"); - } - - expect(await waitForStateUpdate()).true; - - { - const { exchange } = pullLastResultOrThrow(); - expect(exchange.value).equal("url1"); - } - }); - - it("should change the currency when exchange change", async () => { - const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() => - useComponentState(exchangeListWithARSandUSD, undefined, "ARS"), - ); - - { - const { exchange, currency } = pullLastResultOrThrow(); - - expect(exchange.value).equal("url2"); - expect(currency.value).equal("ARS"); - - if (exchange.onChange === undefined) expect.fail(); - exchange.onChange("url1"); - } - - expect(await waitForStateUpdate()).true; - - { - const { exchange, currency } = pullLastResultOrThrow(); - - expect(exchange.value).equal("url1"); - expect(currency.value).equal("USD"); - } - }); - - it("should update parsed amount when amount change", async () => { - const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() => - useComponentState(exchangeListWithARSandUSD, undefined, "ARS"), - ); - - { - const { amount, parsedAmount } = pullLastResultOrThrow(); - - expect(parsedAmount).equal(undefined); - - expect(amount.onInput).not.undefined; - if (!amount.onInput) return; - amount.onInput("12"); - } - - expect(await waitForStateUpdate()).true; - - { - const { parsedAmount } = pullLastResultOrThrow(); - - expect(parsedAmount).deep.equals({ - value: 12, - fraction: 0, - currency: "ARS", - }); - } - }); - - it("should have an amount field", async () => { - const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() => - useComponentState(exchangeListWithARSandUSD, undefined, "ARS"), - ); - - await defaultTestForInputText( - waitForStateUpdate, - () => pullLastResultOrThrow().amount, - ); - }); - - it("should have an exchange selector ", async () => { - const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() => - useComponentState(exchangeListWithARSandUSD, undefined, "ARS"), - ); - - await defaultTestForInputSelect( - waitForStateUpdate, - () => pullLastResultOrThrow().exchange, - ); - }); - - it("should have a currency selector ", async () => { - const { pullLastResultOrThrow, waitForStateUpdate } = mountHook(() => - useComponentState(exchangeListWithARSandUSD, undefined, "ARS"), - ); - - await defaultTestForInputSelect( - waitForStateUpdate, - () => pullLastResultOrThrow().currency, - ); - }); -}); - -async function defaultTestForInputText( - awaiter: () => Promise, - getField: () => TextFieldHandler, -): Promise { - let nextValue = ""; - { - const field = getField(); - const initialValue = field.value; - nextValue = `${initialValue} something else`; - expect(field.onInput).not.undefined; - if (!field.onInput) return; - field.onInput(nextValue); - } - - expect(await awaiter()).true; - - { - const field = getField(); - expect(field.value).equal(nextValue); - } -} - -async function defaultTestForInputSelect( - awaiter: () => Promise, - getField: () => SelectFieldHandler, -): Promise { - let nextValue = ""; - - { - const field = getField(); - const initialValue = field.value; - const keys = Object.keys(field.list); - const nextIdx = keys.indexOf(initialValue) + 1; - if (keys.length < nextIdx) { - throw new Error("no enough values"); - } - nextValue = keys[nextIdx]; - if (field.onChange === undefined) expect.fail(); - field.onChange(nextValue); - } - - expect(await awaiter()).true; - - { - const field = getField(); - - expect(field.value).equal(nextValue); - } -} diff --git a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx deleted file mode 100644 index dd80faccd..000000000 --- a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx +++ /dev/null @@ -1,282 +0,0 @@ -/* - 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 - */ - -/** - * - * @author Sebastian Javier Marchano (sebasjm) - */ - -import { AmountJson, Amounts } from "@gnu-taler/taler-util"; -import { Fragment, h, VNode } from "preact"; -import { useState } from "preact/hooks"; -import { ErrorMessage } from "../components/ErrorMessage.js"; -import { SelectList } from "../components/SelectList.js"; -import { - BoldLight, - Centered, - Input, - InputWithLabel, - LightText, - LinkPrimary, - SubTitle, -} from "../components/styled/index.js"; -import { useTranslationContext } from "../context/translation.js"; -import { Button } from "../mui/Button.js"; -import { SelectFieldHandler, TextFieldHandler } from "../mui/handlers.js"; -import { Pages } from "../NavigationBar.js"; - -export interface Props { - error: string | undefined; - initialAmount?: string; - exchangeUrlWithCurrency: Record; - onCreate: (exchangeBaseUrl: string, amount: AmountJson) => Promise; - initialCurrency?: string; -} - -export interface State { - noExchangeFound: boolean; - parsedAmount: AmountJson | undefined; - amount: TextFieldHandler; - currency: SelectFieldHandler; - exchange: SelectFieldHandler; -} - -export function useComponentState( - exchangeUrlWithCurrency: Record, - initialAmount: string | undefined, - initialCurrency: string | undefined, -): State { - const exchangeSelectList = Object.keys(exchangeUrlWithCurrency); - const currencySelectList = Object.values(exchangeUrlWithCurrency); - const exchangeMap = exchangeSelectList.reduce( - (p, c) => ({ ...p, [c]: `${c} (${exchangeUrlWithCurrency[c]})` }), - {} as Record, - ); - const currencyMap = currencySelectList.reduce( - (p, c) => ({ ...p, [c]: c }), - {} as Record, - ); - - const foundExchangeForCurrency = exchangeSelectList.findIndex( - (e) => exchangeUrlWithCurrency[e] === initialCurrency, - ); - - const initialExchange = - foundExchangeForCurrency !== -1 - ? exchangeSelectList[foundExchangeForCurrency] - : !initialCurrency && exchangeSelectList.length > 0 - ? exchangeSelectList[0] - : undefined; - - const [exchange, setExchange] = useState(initialExchange || ""); - const [currency, setCurrency] = useState( - initialExchange ? exchangeUrlWithCurrency[initialExchange] : "", - ); - - const [amount, setAmount] = useState(initialAmount || ""); - const parsedAmount = Amounts.parse(`${currency}:${amount}`); - - async function changeExchange(exchange: string): Promise { - setExchange(exchange); - setCurrency(exchangeUrlWithCurrency[exchange]); - } - - async function changeCurrency(currency: string): Promise { - setCurrency(currency); - const found = Object.entries(exchangeUrlWithCurrency).find( - (e) => e[1] === currency, - ); - - if (found) { - setExchange(found[0]); - } else { - setExchange(""); - } - } - return { - noExchangeFound: initialExchange === undefined, - currency: { - list: currencyMap, - value: currency, - onChange: changeCurrency, - }, - exchange: { - list: exchangeMap, - value: exchange, - onChange: changeExchange, - }, - amount: { - value: amount, - onInput: async (e: string) => setAmount(e), - }, - parsedAmount, - }; -} - -export function CreateManualWithdraw({ - initialAmount, - exchangeUrlWithCurrency, - error, - initialCurrency, - onCreate, -}: Props): VNode { - const { i18n } = useTranslationContext(); - - const state = useComponentState( - exchangeUrlWithCurrency, - initialAmount, - initialCurrency, - ); - - if (state.noExchangeFound) { - if (initialCurrency) { - return ( -
- - - Manual Withdrawal for {initialCurrency} - - - - - Choose a exchange from where the coins will be withdrawn. The - exchange will send the coins to this wallet after receiving a wire - transfer with the correct subject. - - - - - - No exchange found for {initialCurrency} - - - - Add Exchange - - -
- ); - } - return ( -
- - - Manual Withdrawal for {state.currency.value} - - - - - Choose a exchange from where the coins will be withdrawn. The - exchange will send the coins to this wallet after receiving a wire - transfer with the correct subject. - - - - - No exchange configured - - - Add Exchange - - -
- ); - } - - return ( - -
- {error && ( - Can't create the reserve - } - description={error} - /> - )} - - - Manual Withdrawal for {state.currency.value} - - - - - Choose a exchange from where the coins will be withdrawn. The - exchange will send the coins to this wallet after receiving a wire - transfer with the correct subject. - - -

- - Currency} - name="currency" - {...state.currency} - /> - - - Exchange} - name="exchange" - {...state.exchange} - /> - -

- - Add Exchange - -
- {state.currency.value && ( - - -
- {state.currency.value} - state.amount.onInput(e.currentTarget.value)} - /> -
-
- )} -

-
-
-
- -
-
- ); -} diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts index 373045833..3f23515b2 100644 --- a/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts +++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/index.ts @@ -18,6 +18,7 @@ import { AmountJson, PaytoUri } from "@gnu-taler/taler-util"; import { Loading } from "../../components/Loading.js"; import { HookError } from "../../hooks/useAsyncAsHook.js"; import { + AmountFieldHandler, ButtonHandler, SelectFieldHandler, TextFieldHandler, @@ -98,7 +99,7 @@ export namespace State { totalFee: AmountJson; totalToDeposit: AmountJson; - amount: TextFieldHandler; + amount: AmountFieldHandler; account: SelectFieldHandler; cancelHandler: ButtonHandler; depositHandler: ButtonHandler; diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts index 91883c823..bbf2c2771 100644 --- a/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts +++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/state.ts @@ -52,9 +52,13 @@ export function useComponentState( }); const initialValue = - parsed !== undefined ? Amounts.stringifyValue(parsed) : "0"; + parsed !== undefined + ? parsed + : currency !== undefined + ? Amounts.zeroOfCurrency(currency) + : undefined; // const [accountIdx, setAccountIdx] = useState(0); - const [amount, setAmount] = useState(initialValue); + const [amount, setAmount] = useState(initialValue ?? ({} as any)); const [selectedAccount, setSelectedAccount] = useState(); const [fee, setFee] = useState(undefined); @@ -81,7 +85,7 @@ export function useComponentState( } const { accounts, balances } = hook.response; - const parsedAmount = Amounts.parse(`${currency}:${amount}`); + // const parsedAmount = Amounts.parse(`${currency}:${amount}`); if (addingAccount) { return { @@ -129,8 +133,8 @@ export function useComponentState( const firstAccount = accounts[0].uri; const currentAccount = !selectedAccount ? firstAccount : selectedAccount; - if (fee === undefined && parsedAmount) { - getFeeForAmount(currentAccount, parsedAmount, api).then((initialFee) => { + if (fee === undefined) { + getFeeForAmount(currentAccount, amount, api).then((initialFee) => { setFee(initialFee); }); return { @@ -143,9 +147,9 @@ export function useComponentState( async function updateAccountFromList(accountStr: string): Promise { const uri = !accountStr ? undefined : parsePaytoUri(accountStr); - if (uri && parsedAmount) { + if (uri) { try { - const result = await getFeeForAmount(uri, parsedAmount, api); + const result = await getFeeForAmount(uri, amount, api); setSelectedAccount(uri); setFee(result); } catch (e) { @@ -155,17 +159,15 @@ export function useComponentState( } } - async function updateAmount(numStr: string): Promise { - const parsed = Amounts.parse(`${currency}:${numStr}`); - if (parsed) { - try { - const result = await getFeeForAmount(currentAccount, parsed, api); - setAmount(numStr); - setFee(result); - } catch (e) { - setAmount(numStr); - setFee(undefined); - } + async function updateAmount(newAmount: AmountJson): Promise { + // const parsed = Amounts.parse(`${currency}:${numStr}`); + try { + const result = await getFeeForAmount(currentAccount, newAmount, api); + setAmount(newAmount); + setFee(result); + } catch (e) { + setAmount(newAmount); + setFee(undefined); } } @@ -175,32 +177,29 @@ export function useComponentState( : Amounts.zeroOfCurrency(currency); const totalToDeposit = - parsedAmount && fee !== undefined - ? Amounts.sub(parsedAmount, totalFee).amount + fee !== undefined + ? Amounts.sub(amount, totalFee).amount : Amounts.zeroOfCurrency(currency); const isDirty = amount !== initialValue; const amountError = !isDirty ? undefined - : !parsedAmount - ? "Invalid amount" - : Amounts.cmp(balance, parsedAmount) === -1 + : Amounts.cmp(balance, amount) === -1 ? `Too much, your current balance is ${Amounts.stringifyValue(balance)}` : undefined; const unableToDeposit = - !parsedAmount || //no amount specified Amounts.isZero(totalToDeposit) || //deposit may be zero because of fee fee === undefined || //no fee calculated yet amountError !== undefined; //amount field may be invalid async function doSend(): Promise { - if (!parsedAmount || !currency) return; + if (!currency) return; const depositPaytoUri = stringifyPaytoUri(currentAccount); - const amount = Amounts.stringify(parsedAmount); + const amountStr = Amounts.stringify(amount); await api.wallet.call(WalletApiOperation.CreateDepositGroup, { - amount, + amount: amountStr, depositPaytoUri, }); onSuccess(currency); @@ -211,7 +210,7 @@ export function useComponentState( error: undefined, currency, amount: { - value: String(amount), + value: amount, onInput: updateAmount, error: amountError, }, diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/stories.tsx b/packages/taler-wallet-webextension/src/wallet/DepositPage/stories.tsx index f03788d4e..75c544c84 100644 --- a/packages/taler-wallet-webextension/src/wallet/DepositPage/stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/stories.tsx @@ -52,7 +52,7 @@ export const WithNoAccountForIBAN = createExample(ReadyView, { onInput: async () => { null; }, - value: "10:USD", + value: Amounts.parseOrThrow("USD:10"), }, onAddAccount: {}, cancelHandler: {}, @@ -87,7 +87,7 @@ export const WithIBANAccountTypeSelected = createExample(ReadyView, { onInput: async () => { null; }, - value: "10:USD", + value: Amounts.parseOrThrow("USD:10"), }, onAddAccount: {}, cancelHandler: {}, @@ -123,7 +123,7 @@ export const NewBitcoinAccountTypeSelected = createExample(ReadyView, { onInput: async () => { null; }, - value: "10:USD", + value: Amounts.parseOrThrow("USD:10"), }, cancelHandler: {}, depositHandler: { diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts b/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts index 17e17d185..3f08c678c 100644 --- a/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts +++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/test.ts @@ -194,7 +194,7 @@ describe("DepositPage states", () => { expect(r.cancelHandler.onClick).not.undefined; expect(r.currency).eq(currency); expect(r.account.value).eq(stringifyPaytoUri(ibanPayto.uri)); - expect(r.amount.value).eq("0"); + expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0")); expect(r.depositHandler.onClick).undefined; } @@ -269,7 +269,7 @@ describe("DepositPage states", () => { expect(r.cancelHandler.onClick).not.undefined; expect(r.currency).eq(currency); expect(r.account.value).eq(stringifyPaytoUri(talerBankPayto.uri)); - expect(r.amount.value).eq("0"); + expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0")); expect(r.depositHandler.onClick).undefined; expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`)); expect(r.account.onChange).not.undefined; @@ -285,7 +285,7 @@ describe("DepositPage states", () => { expect(r.cancelHandler.onClick).not.undefined; expect(r.currency).eq(currency); expect(r.account.value).eq(accountSelected); - expect(r.amount.value).eq("0"); + expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0")); expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`)); expect(r.depositHandler.onClick).undefined; } @@ -423,7 +423,7 @@ describe("DepositPage states", () => { expect(r.cancelHandler.onClick).not.undefined; expect(r.currency).eq(currency); expect(r.account.value).eq(stringifyPaytoUri(talerBankPayto.uri)); - expect(r.amount.value).eq("0"); + expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0")); expect(r.depositHandler.onClick).undefined; expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`)); expect(r.account.onChange).not.undefined; @@ -439,13 +439,13 @@ describe("DepositPage states", () => { expect(r.cancelHandler.onClick).not.undefined; expect(r.currency).eq(currency); expect(r.account.value).eq(accountSelected); - expect(r.amount.value).eq("0"); + expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:0")); expect(r.depositHandler.onClick).undefined; expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`)); expect(r.amount.onInput).not.undefined; if (!r.amount.onInput) return; - r.amount.onInput("10"); + r.amount.onInput(Amounts.parseOrThrow("EUR:10")); } expect(await waitForStateUpdate()).true; @@ -456,7 +456,7 @@ describe("DepositPage states", () => { expect(r.cancelHandler.onClick).not.undefined; expect(r.currency).eq(currency); expect(r.account.value).eq(accountSelected); - expect(r.amount.value).eq("10"); + expect(r.amount.value).deep.eq(Amounts.parseOrThrow("EUR:10")); expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:3`)); expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:7`)); expect(r.depositHandler.onClick).not.undefined; diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage/views.tsx b/packages/taler-wallet-webextension/src/wallet/DepositPage/views.tsx index 771db828d..6a28f31e1 100644 --- a/packages/taler-wallet-webextension/src/wallet/DepositPage/views.tsx +++ b/packages/taler-wallet-webextension/src/wallet/DepositPage/views.tsx @@ -173,25 +173,22 @@ export function ReadyView(state: State.Ready): VNode { Amount} - currency={state.currency} handler={state.amount} /> Deposit fee} - currency={state.currency} handler={{ - value: Amounts.stringifyValue(state.totalFee), + value: state.totalFee, }} /> Total deposit} - currency={state.currency} handler={{ - value: Amounts.stringifyValue(state.totalToDeposit), + value: state.totalToDeposit, }} /> diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx b/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx index ba1a560ef..7e4c775e6 100644 --- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx +++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx @@ -33,9 +33,7 @@ import { useTranslationContext } from "../context/translation.js"; import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js"; import { Button } from "../mui/Button.js"; import { Grid } from "../mui/Grid.js"; -import { TextFieldHandler } from "../mui/handlers.js"; import { Paper } from "../mui/Paper.js"; -import { TextField } from "../mui/TextField.js"; import { Pages } from "../NavigationBar.js"; import arrowIcon from "../svg/chevron-down.svg"; import bankIcon from "../svg/ri-bank-line.svg"; @@ -279,12 +277,13 @@ export function DestinationSelectionGetCash({ const parsedInitialAmount = !initialAmount ? undefined : Amounts.parse(initialAmount); - const parsedInitialAmountValue = !parsedInitialAmount - ? "0" - : Amounts.stringifyValue(parsedInitialAmount); + const [currency, setCurrency] = useState(parsedInitialAmount?.currency); - const [amount, setAmount] = useState(parsedInitialAmountValue); + const [amount, setAmount] = useState( + parsedInitialAmount ?? Amounts.zeroOfCurrency(currency ?? "KUDOS"), + ); + const { i18n } = useTranslationContext(); const previous1: Contact[] = []; const previous2: Contact[] = [ @@ -313,10 +312,8 @@ export function DestinationSelectionGetCash({ ); } - const currencyAndAmount = `${currency}:${amount}`; - const parsedAmount = Amounts.parse(currencyAndAmount); - // const dirty = parsedInitialAmountValue !== amount; - const invalid = !parsedAmount || Amounts.isZero(parsedAmount); + const currencyAndAmount = Amounts.stringify(amount); + const invalid = Amounts.isZero(amount); return (

@@ -325,7 +322,6 @@ export function DestinationSelectionGetCash({ Amount} - currency={currency} required handler={{ onInput: async (s) => setAmount(s), @@ -416,12 +412,12 @@ export function DestinationSelectionSendCash({ const parsedInitialAmount = !initialAmount ? undefined : Amounts.parse(initialAmount); - const parsedInitialAmountValue = !parsedInitialAmount - ? "" - : Amounts.stringifyValue(parsedInitialAmount); + const currency = parsedInitialAmount?.currency; - const [amount, setAmount] = useState(parsedInitialAmountValue); + const [amount, setAmount] = useState( + parsedInitialAmount ?? Amounts.zeroOfCurrency(currency ?? "KUDOS"), + ); const { i18n } = useTranslationContext(); const previous1: Contact[] = []; const previous2: Contact[] = [ @@ -450,9 +446,9 @@ export function DestinationSelectionSendCash({ ); } - const currencyAndAmount = `${currency}:${amount}`; - const parsedAmount = Amounts.parse(currencyAndAmount); - const invalid = !parsedAmount || Amounts.isZero(parsedAmount); + const currencyAndAmount = Amounts.stringify(amount); + //const parsedAmount = Amounts.parse(currencyAndAmount); + const invalid = Amounts.isZero(amount); return (

@@ -462,7 +458,6 @@ export function DestinationSelectionSendCash({
Amount} - currency={currency} required handler={{ onInput: async (s) => setAmount(s), diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts index 39fbb6ce2..63d545b97 100644 --- a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts @@ -44,21 +44,22 @@ export function useComponentState( const comparingExchanges = selectedIdx !== initialValue; - const initialExchange = - comparingExchanges ? exchanges[initialValue] : undefined; + const initialExchange = comparingExchanges + ? exchanges[initialValue] + : undefined; const hook = useAsyncAsHook(async () => { const selected = !selectedExchange ? undefined : await api.wallet.call(WalletApiOperation.GetExchangeDetailedInfo, { - exchangeBaseUrl: selectedExchange.exchangeBaseUrl, - }); + exchangeBaseUrl: selectedExchange.exchangeBaseUrl, + }); const original = !initialExchange ? undefined : await api.wallet.call(WalletApiOperation.GetExchangeDetailedInfo, { - exchangeBaseUrl: initialExchange.exchangeBaseUrl, - }); + exchangeBaseUrl: initialExchange.exchangeBaseUrl, + }); return { exchanges, diff --git a/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx b/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx deleted file mode 100644 index e2284a466..000000000 --- a/packages/taler-wallet-webextension/src/wallet/ManualWithdrawPage.tsx +++ /dev/null @@ -1,141 +0,0 @@ -/* - 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 { - AcceptManualWithdrawalResult, - AmountJson, - Amounts, - NotificationType, - parsePaytoUri, - PaytoUri, -} from "@gnu-taler/taler-util"; -import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; -import { h, VNode } from "preact"; -import { useEffect, useState } from "preact/hooks"; -import { Loading } from "../components/Loading.js"; -import { LoadingError } from "../components/LoadingError.js"; -import { useTranslationContext } from "../context/translation.js"; -import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js"; -import { wxApi } from "../wxApi.js"; -import { CreateManualWithdraw } from "./CreateManualWithdraw.js"; -import { ReserveCreated } from "./ReserveCreated.js"; - -interface Props { - amount?: string; - onCancel: () => Promise; -} - -export function ManualWithdrawPage({ amount, onCancel }: Props): VNode { - const [success, setSuccess] = useState< - | { - response: AcceptManualWithdrawalResult; - exchangeBaseUrl: string; - amount: AmountJson; - paytoURI: PaytoUri | undefined; - payto: string; - } - | undefined - >(undefined); - const [error, setError] = useState(undefined); - - const state = useAsyncAsHook(() => - wxApi.wallet.call(WalletApiOperation.ListExchanges, {}), - ); - useEffect(() => { - return wxApi.listener.onUpdateNotification( - [NotificationType.ExchangeAdded], - state?.retry, - ); - }); - const { i18n } = useTranslationContext(); - - async function doCreate( - exchangeBaseUrl: string, - amount: AmountJson, - ): Promise { - try { - const response = await wxApi.wallet.call( - WalletApiOperation.AcceptManualWithdrawal, - { - exchangeBaseUrl: exchangeBaseUrl, - amount: Amounts.stringify(amount), - }, - ); - const payto = response.exchangePaytoUris[0]; - const paytoURI = parsePaytoUri(payto); - setSuccess({ exchangeBaseUrl, response, amount, paytoURI, payto }); - } catch (e) { - if (e instanceof Error) { - setError(e.message); - } else { - setError("unexpected error"); - } - setSuccess(undefined); - } - } - - if (success) { - return ( - - ); - } - - if (!state) { - return ; - } - if (state.hasError) { - return ( - - Could not load the list of known exchanges - - } - error={state} - /> - ); - } - - const exchangeList = state.response.exchanges.reduce( - (p, c) => ({ - ...p, - [c.exchangeBaseUrl]: c.currency || "??", - }), - {} as Record, - ); - - const parsedAmount = !amount ? undefined : Amounts.parse(amount); - const currency = parsedAmount?.currency; - const amountValue = !parsedAmount - ? undefined - : Amounts.stringifyValue(parsedAmount); - return ( - - ); -} diff --git a/packages/taler-wallet-webextension/src/wallet/index.stories.tsx b/packages/taler-wallet-webextension/src/wallet/index.stories.tsx index 42808b573..ef1295846 100644 --- a/packages/taler-wallet-webextension/src/wallet/index.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/index.stories.tsx @@ -20,7 +20,6 @@ */ import * as a1 from "./Backup.stories.js"; -import * as a3 from "./CreateManualWithdraw.stories.js"; import * as a4 from "./DepositPage/stories.js"; import * as a5 from "./ExchangeAddConfirm.stories.js"; import * as a6 from "./ExchangeAddSetUrl.stories.js"; @@ -40,7 +39,6 @@ import * as a20 from "./ManageAccount/stories.js"; export default [ a1, - a3, a4, a5, a6, -- cgit v1.2.3