From 93f1f9867a6f5681df847d60efca4828f5d49deb Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 9 Aug 2024 11:07:06 -0300 Subject: scoped p2p --- .../src/cta/InvoiceCreate/index.ts | 7 +- .../src/cta/InvoiceCreate/state.ts | 82 ++++++++++-------- .../src/cta/InvoiceCreate/stories.tsx | 7 ++ .../src/cta/InvoiceCreate/views.tsx | 9 ++ .../src/cta/TransferCreate/index.ts | 6 +- .../src/cta/TransferCreate/state.ts | 98 +++++----------------- .../src/cta/TransferCreate/stories.tsx | 7 ++ .../src/cta/TransferCreate/views.tsx | 9 ++ 8 files changed, 104 insertions(+), 121 deletions(-) (limited to 'packages/taler-wallet-webextension/src/cta') diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts index 1ca7481be..dbca08b2b 100644 --- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts +++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/index.ts @@ -14,12 +14,12 @@ GNU Taler; see the file COPYING. If not, see */ -import { AmountJson, AmountString } from "@gnu-taler/taler-util"; +import { AmountJson, AmountString, 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 { State as SelectExchangeState } from "../../hooks/useSelectedExchange.js"; -import { ButtonHandler, TextFieldHandler } from "../../mui/handlers.js"; +import { AmountFieldHandler, ButtonHandler, TextFieldHandler } from "../../mui/handlers.js"; import { compose, StateViewMap } from "../../utils/index.js"; import { ExchangeSelectionPage } from "../../wallet/ExchangeSelection/index.js"; import { NoExchangesView } from "../../wallet/ExchangeSelection/views.js"; @@ -27,7 +27,7 @@ import { useComponentState } from "./state.js"; import { ReadyView } from "./views.js"; export interface Props { - amount: AmountString; + scope: ScopeInfo; onClose: () => Promise; onSuccess: (tx: string) => Promise; } @@ -59,6 +59,7 @@ export namespace State { status: "ready"; doSelectExchange: ButtonHandler; create: ButtonHandler; + amount: AmountFieldHandler; subject: TextFieldHandler; expiration: TextFieldHandler; toBeReceived: AmountJson; diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts index baaa9a3dd..d2db4f44c 100644 --- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts +++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/state.ts @@ -15,7 +15,7 @@ */ /* eslint-disable react-hooks/rules-of-hooks */ -import { Amounts, TalerProtocolTimestamp } from "@gnu-taler/taler-util"; +import { AmountJson, Amounts, AmountString, TalerProtocolTimestamp } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { isFuture, parse } from "date-fns"; import { useState } from "preact/hooks"; @@ -28,11 +28,10 @@ import { RecursiveState } from "../../utils/index.js"; import { Props, State } from "./index.js"; export function useComponentState({ - amount: amountStr, + scope, onClose, onSuccess, }: Props): RecursiveState { - const amount = Amounts.parseOrThrow(amountStr); const api = useBackendContext(); const { pushAlertOnError } = useAlertContext(); @@ -72,12 +71,14 @@ export function useComponentState({ const exchangeList = hook.response.exchanges; return () => { + const [amount, setAmount] = useState(Amounts.zeroOfCurrency(scope.currency)); const [subject, setSubject] = useState(); const [timestamp, setTimestamp] = useState(); const { pushAlertOnError } = useAlertContext(); + const amountStr = Amounts.stringify(amount) const selectedExchange = useSelectedExchange({ - currency: amount.currency, + currency: scope.currency, defaultExchange: undefined, list: exchangeList, }); @@ -97,39 +98,41 @@ export function useComponentState({ }, ); return resp; - }); - - if (!hook) { - return { - status: "loading", - error: undefined, - }; - } - - if (hook.hasError) { - return { - status: "error", - retry: { - onClick: pushAlertOnError(async () => { - hook.retry(); - }), - }, - error: alertFromError( - i18n, - i18n.str`Could not load the invoice status`, - hook, - ), - }; - // return { - // status: "loading-uri", - // error: hook, - // }; - } - - const { amountEffective, amountRaw } = hook.response; - const requestAmount = Amounts.parseOrThrow(amountRaw); - const toBeReceived = Amounts.parseOrThrow(amountEffective); - + },[amountStr]); + + // if (!hook) { + // return { + // status: "loading", + // error: undefined, + // }; + // } + + // if (hook.hasError) { + // return { + // status: "error", + // retry: { + // onClick: pushAlertOnError(async () => { + // hook.retry(); + // }), + // }, + // error: alertFromError( + // i18n, + // i18n.str`Could not load the invoice status`, + // hook, + // ), + // }; + // // return { + // // status: "loading-uri", + // // error: hook, + // // }; + // } + + // const { amountEffective, amountRaw } = hook.response; + // const requestAmount = Amounts.parseOrThrow(amountRaw); + // const toBeReceived = Amounts.parseOrThrow(amountEffective); + const requestAmount = !hook || hook.hasError ? Amounts.zeroOfCurrency(scope.currency) : Amounts.parseOrThrow(hook.response.amountRaw); + const toBeReceived = !hook || hook.hasError ? Amounts.zeroOfCurrency(scope.currency) : Amounts.parseOrThrow(hook.response.amountEffective); + let purse_expiration: TalerProtocolTimestamp | undefined = undefined; let timestampError: string | undefined = undefined; @@ -174,6 +177,11 @@ export function useComponentState({ return { status: "ready", + amount: { + value: amount, + onInput: pushAlertOnError(async (e) => setAmount(e)), + error: Amounts.isZero(amount) ? "Can't be zero" : undefined, + }, subject: { error: subject === undefined diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/stories.tsx b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/stories.tsx index 779f130aa..9822f7c91 100644 --- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/stories.tsx +++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/stories.tsx @@ -33,6 +33,13 @@ export const Ready = tests.createExample(ReadyView, { value: 1, fraction: 0, }, + amount: { + value: { + currency: "ARS", + value: 1, + fraction: 0, + } + }, expiration: { value: "2/12/12", }, diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/views.tsx b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/views.tsx index e2c37fbba..86bac5a16 100644 --- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/views.tsx +++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/views.tsx @@ -27,10 +27,12 @@ import { InvoiceCreationDetails, } from "../../wallet/Transaction.js"; import { State } from "./index.js"; +import { AmountField } from "../../components/AmountField.js"; export function ReadyView({ exchangeUrl, subject, + amount, expiration, create, toBeReceived, @@ -86,6 +88,13 @@ export function ReadyView({ kind="neutral" big /> +

+ +

Promise; onSuccess: (tx: string) => Promise; } @@ -54,6 +55,7 @@ export namespace State { export interface Ready extends BaseInfo { status: "ready"; create: ButtonHandler; + amount: AmountFieldHandler; toBeReceived: AmountJson; debitAmount: AmountJson; subject: TextFieldHandler; diff --git a/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts b/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts index f15d48c23..1a8f318c0 100644 --- a/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts +++ b/packages/taler-wallet-webextension/src/cta/TransferCreate/state.ts @@ -15,64 +15,42 @@ */ import { - AmountString, + AmountJson, Amounts, - TalerErrorCode, - TalerProtocolTimestamp, + TalerProtocolTimestamp } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { isFuture, parse } from "date-fns"; -import { useState } from "preact/hooks"; +import { useEffect, useState } from "preact/hooks"; import { alertFromError, useAlertContext } from "../../context/alert.js"; import { useBackendContext } from "../../context/backend.js"; import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js"; -import { BackgroundError, WxApiType } from "../../wxApi.js"; import { Props, State } from "./index.js"; export function useComponentState({ - amount: amountStr, + scope, onClose, onSuccess, }: Props): State { const api = useBackendContext(); const { pushAlertOnError } = useAlertContext(); - const amount = Amounts.parseOrThrow(amountStr); + // const amount = Amounts.parseOrThrow(amountStr); const { i18n } = useTranslationContext(); + const [amount, setAmount] = useState(Amounts.zeroOfCurrency(scope.currency)); const [subject, setSubject] = useState(); const [timestamp, setTimestamp] = useState(); + const amountStr = Amounts.stringify(amount) const hook = useAsyncAsHook(async () => { - const resp = await checkPeerPushDebitAndCheckMax(api, amountStr); - return resp; - }); - - if (!hook) { - return { - status: "loading", - error: undefined, - }; - } - if (hook.hasError) { - return { - status: "error", - retry: { - onClick: pushAlertOnError(async () => { - hook.retry(); - }), - }, - error: alertFromError( - i18n, - i18n.str`Could not load the max amount to transfer`, - hook, - ), - }; - } + return await api.wallet.call(WalletApiOperation.CheckPeerPushDebit, { + amount: amountStr, + }); + }, [amountStr]); - const { amountEffective, amountRaw } = hook.response; - const debitAmount = Amounts.parseOrThrow(amountEffective); - const toBeReceived = Amounts.parseOrThrow(amountRaw); + const debitAmount = !hook || hook.hasError ? Amounts.zeroOfCurrency(scope.currency) : Amounts.parseOrThrow(hook.response.amountEffective); + const toBeReceived = !hook || hook.hasError ? Amounts.zeroOfCurrency(scope.currency) : Amounts.parseOrThrow(hook.response.amountRaw); let purse_expiration: TalerProtocolTimestamp | undefined = undefined; let timestampError: string | undefined = undefined; @@ -112,13 +90,18 @@ export function useComponentState({ } const unableToCreate = - !subject || Amounts.isZero(amount) || !purse_expiration; + !subject || Amounts.isZero(amount) || Amounts.isZero(debitAmount) || !purse_expiration; return { status: "ready", cancel: { onClick: pushAlertOnError(onClose), }, + amount: { + value: amount, + onInput: pushAlertOnError(async (e) => setAmount(e)), + error: Amounts.isZero(amount) ? "Can't be zero" : undefined, + }, subject: { error: subject === undefined @@ -145,46 +128,3 @@ export function useComponentState({ }; } -async function checkPeerPushDebitAndCheckMax( - api: WxApiType, - amountState: AmountString, -) { - // FIXME : https://bugs.gnunet.org/view.php?id=7872 - try { - return await api.wallet.call(WalletApiOperation.CheckPeerPushDebit, { - amount: amountState, - }); - } catch (e) { - if (!(e instanceof BackgroundError)) { - throw e; - } - if ( - !e.hasErrorCode( - TalerErrorCode.WALLET_PEER_PUSH_PAYMENT_INSUFFICIENT_BALANCE, - ) - ) { - throw e; - } - const material = Amounts.parseOrThrow( - e.errorDetail.insufficientBalanceDetails.balanceMaterial, - ); - const amount = Amounts.parseOrThrow(amountState); - const gap = Amounts.sub( - amount, - Amounts.parseOrThrow( - e.errorDetail.insufficientBalanceDetails.maxEffectiveSpendAmount, - ), - ).amount; - const newAmount = Amounts.sub(material, gap).amount; - if (Amounts.cmp(newAmount, amount) === 0) { - //insufficient balance and the exception didn't give - //a good response that allow us to try again - throw e; - } - if (Amounts.cmp(newAmount, amount) === 1) { - //how can this happen? - throw e; - } - return checkPeerPushDebitAndCheckMax(api, Amounts.stringify(newAmount)); - } -} diff --git a/packages/taler-wallet-webextension/src/cta/TransferCreate/stories.tsx b/packages/taler-wallet-webextension/src/cta/TransferCreate/stories.tsx index 8e9fbbe63..9ba806ba4 100644 --- a/packages/taler-wallet-webextension/src/cta/TransferCreate/stories.tsx +++ b/packages/taler-wallet-webextension/src/cta/TransferCreate/stories.tsx @@ -33,6 +33,13 @@ export const Ready = tests.createExample(ReadyView, { value: 1, fraction: 0, }, + amount: { + value: { + currency: "ARS", + value: 1, + fraction: 0, + } + }, expiration: { value: "20/1/2022", }, diff --git a/packages/taler-wallet-webextension/src/cta/TransferCreate/views.tsx b/packages/taler-wallet-webextension/src/cta/TransferCreate/views.tsx index bc855f33d..269f39fbe 100644 --- a/packages/taler-wallet-webextension/src/cta/TransferCreate/views.tsx +++ b/packages/taler-wallet-webextension/src/cta/TransferCreate/views.tsx @@ -25,9 +25,11 @@ import { TransferCreationDetails, } from "../../wallet/Transaction.js"; import { State } from "./index.js"; +import { AmountField } from "../../components/AmountField.js"; export function ReadyView({ subject, + amount, expiration, toBeReceived, debitAmount, @@ -60,6 +62,13 @@ export function ReadyView({ return (

+

+ +