aboutsummaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2023-03-31 19:09:41 -0300
committerSebastian <sebasjm@gmail.com>2023-03-31 19:09:41 -0300
commitf947c8e54919343ac4f5f951d2f701651c06dd52 (patch)
tree870c39a2214f1183113469b19b3111d79b69d68a /packages
parent8701ae100ec1e2733b8e9b7006a706d1c9fe32a8 (diff)
calculate using server
Diffstat (limited to 'packages')
-rw-r--r--packages/demobank-ui/src/declaration.d.ts8
-rw-r--r--packages/demobank-ui/src/hooks/circuit.ts105
-rw-r--r--packages/demobank-ui/src/pages/BusinessAccount.tsx95
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 {
@@ -218,6 +219,23 @@ async function getBusinessStatus(
): 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();
const result = await request<
HttpResponseOk<SandboxBackend.Circuit.CircuitAccountData>
>(url, `circuit-api/accounts/${basicAuth.username}`, { basicAuth });
@@ -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");
}