gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 02/02: calculate using server


From: gnunet
Subject: [taler-wallet-core] 02/02: calculate using server
Date: Sat, 01 Apr 2023 00:09:50 +0200

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

commit f947c8e54919343ac4f5f951d2f701651c06dd52
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Mar 31 19:09:41 2023 -0300

    calculate using server
---
 packages/demobank-ui/src/declaration.d.ts          |   8 ++
 packages/demobank-ui/src/hooks/circuit.ts          | 105 +++++++++++++++++++++
 packages/demobank-ui/src/pages/BusinessAccount.tsx |  95 +++++++++----------
 3 files changed, 155 insertions(+), 53 deletions(-)

diff --git a/packages/demobank-ui/src/declaration.d.ts 
b/packages/demobank-ui/src/declaration.d.ts
index 4d8484a4f..a37485272 100644
--- a/packages/demobank-ui/src/declaration.d.ts
+++ b/packages/demobank-ui/src/declaration.d.ts
@@ -329,6 +329,14 @@ namespace SandboxBackend {
       // where to send cashouts.
       cashout_address: string;
     }
+    interface CashoutEstimate {
+      // Amount that the user will get deducted from their regional
+      // bank account, according to the 'amount_credit' value.
+      amount_debit: Amount;
+      // Amount that the user will receive in their fiat
+      // bank account, according to 'amount_debit'.
+      amount_credit: Amount;
+    }
     interface CashoutRequest {
       // Optional subject to associate to the
       // cashout operation.  This data will appear
diff --git a/packages/demobank-ui/src/hooks/circuit.ts 
b/packages/demobank-ui/src/hooks/circuit.ts
index 137a7aee2..f90469e24 100644
--- a/packages/demobank-ui/src/hooks/circuit.ts
+++ b/packages/demobank-ui/src/hooks/circuit.ts
@@ -32,6 +32,7 @@ import {
 
 // FIX default import https://github.com/microsoft/TypeScript/issues/49189
 import _useSWR, { SWRHook } from "swr";
+import { AmountJson, Amounts } from "@gnu-taler/taler-util";
 const useSWR = _useSWR as unknown as SWRHook;
 
 export function useAdminAccountAPI(): AdminAccountAPI {
@@ -215,6 +216,23 @@ export interface CircuitAccountAPI {
 async function getBusinessStatus(
   request: ReturnType<typeof useApiContext>["request"],
   basicAuth: { username: string; password: string },
+): Promise<boolean> {
+  try {
+    const url = getInitialBackendBaseURL();
+    const result = await request<SandboxBackend.Circuit.CircuitAccountData>(
+      url,
+      `circuit-api/accounts/${basicAuth.username}`,
+      { basicAuth },
+    );
+    return result.ok;
+  } catch (error) {
+    return false;
+  }
+}
+
+async function getEstimationByCredit(
+  request: ReturnType<typeof useApiContext>["request"],
+  basicAuth: { username: string; password: string },
 ): Promise<boolean> {
   try {
     const url = getInitialBackendBaseURL();
@@ -227,6 +245,93 @@ async function getBusinessStatus(
   }
 }
 
+export type TransferCalculation = {
+  debit: AmountJson;
+  credit: AmountJson;
+  beforeFee: AmountJson;
+};
+type EstimatorFunction = (
+  amount: AmountJson,
+  sellFee: AmountJson,
+  sellRate: number,
+) => Promise<TransferCalculation>;
+
+type CashoutEstimators = {
+  estimateByCredit: EstimatorFunction;
+  estimateByDebit: EstimatorFunction;
+};
+
+export function useEstimator(): CashoutEstimators {
+  const { state } = useBackendContext();
+  const { request } = useApiContext();
+  const basicAuth =
+    state.status === "loggedOut"
+      ? undefined
+      : { username: state.username, password: state.password };
+  return {
+    estimateByCredit: async (amount, fee, rate) => {
+      const zeroBalance = Amounts.zeroOfCurrency(fee.currency);
+      const zeroFiat = Amounts.zeroOfCurrency(fee.currency);
+      const zeroCalc = {
+        debit: zeroBalance,
+        credit: zeroFiat,
+        beforeFee: zeroBalance,
+      };
+      const url = getInitialBackendBaseURL();
+      const result = await request<SandboxBackend.Circuit.CashoutEstimate>(
+        url,
+        `circuit-api/cashouts/estimates`,
+        {
+          basicAuth,
+          params: {
+            amount_credit: Amounts.stringify(amount),
+          },
+        },
+      );
+      // const credit = Amounts.parseOrThrow(result.data.data.amount_credit);
+      const credit = amount;
+      const _credit = { ...credit, currency: fee.currency };
+      const beforeFee = Amounts.sub(_credit, fee).amount;
+
+      const debit = Amounts.parseOrThrow(result.data.amount_debit);
+      return {
+        debit,
+        beforeFee,
+        credit,
+      };
+    },
+    estimateByDebit: async (amount, fee, rate) => {
+      const zeroBalance = Amounts.zeroOfCurrency(fee.currency);
+      const zeroFiat = Amounts.zeroOfCurrency(fee.currency);
+      const zeroCalc = {
+        debit: zeroBalance,
+        credit: zeroFiat,
+        beforeFee: zeroBalance,
+      };
+      const url = getInitialBackendBaseURL();
+      const result = await request<SandboxBackend.Circuit.CashoutEstimate>(
+        url,
+        `circuit-api/cashouts/estimates`,
+        {
+          basicAuth,
+          params: {
+            amount_debit: Amounts.stringify(amount),
+          },
+        },
+      );
+      const credit = Amounts.parseOrThrow(result.data.amount_credit);
+      const _credit = { ...credit, currency: fee.currency };
+      const debit = amount;
+      const beforeFee = Amounts.sub(_credit, fee).amount;
+      return {
+        debit,
+        beforeFee,
+        credit,
+      };
+    },
+  };
+}
+
 export function useBusinessAccountFlag(): boolean | undefined {
   const [isBusiness, setIsBusiness] = useState<boolean | undefined>();
   const { state } = useBackendContext();
diff --git a/packages/demobank-ui/src/pages/BusinessAccount.tsx 
b/packages/demobank-ui/src/pages/BusinessAccount.tsx
index 4c322764e..262376fa2 100644
--- a/packages/demobank-ui/src/pages/BusinessAccount.tsx
+++ b/packages/demobank-ui/src/pages/BusinessAccount.tsx
@@ -34,6 +34,7 @@ import { useAccountDetails } from "../hooks/access.js";
 import {
   useCashoutDetails,
   useCircuitAccountAPI,
+  useEstimator,
   useRatiosAndFeeConfig,
 } from "../hooks/circuit.js";
 import {
@@ -230,7 +231,10 @@ function CreateCashout({
   const ratiosResult = useRatiosAndFeeConfig();
   const result = useAccountDetails(account);
   const [error, saveError] = useState<ErrorMessage | undefined>();
-
+  const {
+    estimateByCredit: calculateFromCredit,
+    estimateByDebit: calculateFromDebit,
+  } = useEstimator();
   const [form, setForm] = useState<Partial<FormType>>({ isDebit: true });
 
   const { createCashout } = useCircuitAccountAPI();
@@ -256,21 +260,45 @@ function CreateCashout({
 
   if (!sellRate || sellRate < 0) return <div>error rate</div>;
 
-  const amount = Amounts.parse(`${balance.currency}:${form.amount}`);
+  const amount = Amounts.parseOrThrow(
+    `${!form.isDebit ? fiatCurrency : balance.currency}:${
+      !form.amount ? "0" : form.amount
+    }`,
+  );
 
   useEffect(() => {
-    if (!amount) {
-      setCalc(zeroCalc);
-    } else {
-      if (form.isDebit) {
-        calculateFromDebit(amount, sellFee, sellRate).then((r) => {
+    if (form.isDebit) {
+      calculateFromDebit(amount, sellFee, sellRate)
+        .then((r) => {
           setCalc(r);
+          saveError(undefined);
+        })
+        .catch((error) => {
+          saveError(
+            error instanceof RequestError
+              ? buildRequestErrorMessage(i18n, error.cause)
+              : {
+                  title: i18n.str`Could not estimate the cashout`,
+                  description: error.message,
+                },
+          );
         });
-      } else {
-        calculateFromCredit(amount, sellFee, sellRate).then((r) => {
+    } else {
+      calculateFromCredit(amount, sellFee, sellRate)
+        .then((r) => {
           setCalc(r);
+          saveError(undefined);
+        })
+        .catch((error) => {
+          saveError(
+            error instanceof RequestError
+              ? buildRequestErrorMessage(i18n, error.cause)
+              : {
+                  title: i18n.str`Could not estimate the cashout`,
+                  description: error.message,
+                },
+          );
         });
-      }
     }
   }, [form.amount, form.isDebit]);
 
@@ -326,14 +354,10 @@ function CreateCashout({
               type="text"
               readonly
               class="currency-indicator"
-              size={
-                !form.isDebit ? fiatCurrency.length : balance.currency.length
-              }
-              maxLength={
-                !form.isDebit ? fiatCurrency.length : balance.currency.length
-              }
+              size={amount?.currency.length ?? 0}
+              maxLength={amount?.currency.length ?? 0}
               tabIndex={-1}
-              value={!form.isDebit ? fiatCurrency : balance.currency}
+              value={amount?.currency ?? ""}
             />
             &nbsp;
             <input
@@ -588,9 +612,7 @@ function CreateCashout({
               if (errors) return;
               try {
                 const res = await createCashout({
-                  amount_credit: `${fiatCurrency}:${Amounts.stringifyValue(
-                    calc.credit,
-                  )}`,
+                  amount_credit: Amounts.stringify(calc.credit),
                   amount_debit: Amounts.stringify(calc.debit),
                   subject: form.subject,
                   tan_channel: form.channel,
@@ -842,39 +864,6 @@ function truncate(a: AmountJson): AmountJson {
   return Amounts.parseOrThrow(truncated);
 }
 
-type TransferCalculation = {
-  debit: AmountJson;
-  credit: AmountJson;
-  beforeFee: AmountJson;
-};
-
-async function calculateFromDebit(
-  amount: AmountJson,
-  sellFee: AmountJson,
-  sellRate: number,
-): Promise<TransferCalculation> {
-  const debit = amount;
-
-  const beforeFee = truncate(Amounts.divide(debit, 1 / sellRate));
-
-  const credit = Amounts.sub(beforeFee, sellFee).amount;
-  return { debit, credit, beforeFee };
-}
-
-async function calculateFromCredit(
-  amount: AmountJson,
-  sellFee: AmountJson,
-  sellRate: number,
-): Promise<TransferCalculation> {
-  const credit = amount;
-
-  const beforeFee = Amounts.add(credit, sellFee).amount;
-
-  const debit = truncate(Amounts.divide(beforeFee, sellRate));
-
-  return { debit, credit, beforeFee };
-}
-
 export function assertUnreachable(x: never): never {
   throw new Error("Didn't expect to get here");
 }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]