gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 02/02: add age restriction option to withdraw cta


From: gnunet
Subject: [taler-wallet-core] 02/02: add age restriction option to withdraw cta
Date: Wed, 04 May 2022 21:27:05 +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 7a2fe8018faa4666ff681072682f16f8fb1bfc13
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Wed May 4 16:25:53 2022 -0300

    add age restriction option to withdraw cta
---
 .../src/components/Checkbox.tsx                    |  4 +-
 .../src/components/SelectList.tsx                  |  7 ++-
 .../src/cta/Pay.stories.tsx                        | 36 +++++++++++++++
 packages/taler-wallet-webextension/src/cta/Pay.tsx | 27 ++++++-----
 .../src/cta/Withdraw.stories.tsx                   | 53 ++++++++++++++++++++++
 .../taler-wallet-webextension/src/cta/Withdraw.tsx | 38 +++++++++++++++-
 .../taler-wallet-webextension/src/mui/handlers.ts  |  2 +-
 .../src/wallet/CreateManualWithdraw.test.ts        |  4 +-
 .../src/wallet/DepositPage.test.ts                 |  2 +
 .../src/wallet/DeveloperPage.tsx                   | 15 ++++--
 packages/taler-wallet-webextension/src/wxApi.ts    |  4 ++
 11 files changed, 167 insertions(+), 25 deletions(-)

diff --git a/packages/taler-wallet-webextension/src/components/Checkbox.tsx 
b/packages/taler-wallet-webextension/src/components/Checkbox.tsx
index 0eb087b0..2e14f336 100644
--- a/packages/taler-wallet-webextension/src/components/Checkbox.tsx
+++ b/packages/taler-wallet-webextension/src/components/Checkbox.tsx
@@ -17,8 +17,8 @@
 import { h, VNode } from "preact";
 
 interface Props {
-  enabled: boolean;
-  onToggle: () => void;
+  enabled?: boolean;
+  onToggle?: () => void;
   label: VNode;
   name: string;
   description?: VNode;
diff --git a/packages/taler-wallet-webextension/src/components/SelectList.tsx 
b/packages/taler-wallet-webextension/src/components/SelectList.tsx
index aa17d82b..9271240f 100644
--- a/packages/taler-wallet-webextension/src/components/SelectList.tsx
+++ b/packages/taler-wallet-webextension/src/components/SelectList.tsx
@@ -20,7 +20,7 @@ import { NiceSelect } from "./styled/index.js";
 
 interface Props {
   value?: string;
-  onChange: (s: string) => void;
+  onChange?: (s: string) => void;
   label: VNode;
   list: {
     [label: string]: string;
@@ -28,6 +28,7 @@ interface Props {
   name: string;
   description?: string;
   canBeNull?: boolean;
+  maxWidth?: boolean;
 }
 
 export function SelectList({
@@ -36,6 +37,7 @@ export function SelectList({
   list,
   onChange,
   label,
+  maxWidth,
   description,
   canBeNull,
 }: Props): VNode {
@@ -53,8 +55,9 @@ export function SelectList({
         <select
           name={name}
           value={value}
+          style={maxWidth ? { width: "100%" } : undefined}
           onChange={(e) => {
-            onChange(e.currentTarget.value);
+            if (onChange) onChange(e.currentTarget.value);
           }}
         >
           {value === undefined ||
diff --git a/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx 
b/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx
index 3656bbbd..76bfa3ab 100644
--- a/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx
@@ -101,6 +101,42 @@ export const NoEnoughBalance = 
createExample(TestedComponent, {
   goToWalletManualWithdraw: () => null,
 });
 
+export const EnoughBalanceButRestricted = createExample(TestedComponent, {
+  state: {
+    status: "ready",
+    hook: undefined,
+    amount: Amounts.parseOrThrow("USD:10"),
+    balance: {
+      currency: "USD",
+      fraction: 40000000,
+      value: 19,
+    },
+    payHandler: {
+      onClick: async () => {
+        null;
+      },
+    },
+    totalFees: Amounts.parseOrThrow("USD:0"),
+    payResult: undefined,
+    uri: "",
+    payStatus: {
+      status: PreparePayResultType.InsufficientBalance,
+      noncePriv: "",
+      proposalId: "proposal1234",
+      contractTerms: {
+        merchant: {
+          name: "someone",
+        },
+        summary: "some beers",
+        amount: "USD:10",
+      } as Partial<ContractTerms> as any,
+      amountRaw: "USD:10",
+    },
+  },
+  goBack: () => null,
+  goToWalletManualWithdraw: () => null,
+});
+
 export const PaymentPossible = createExample(TestedComponent, {
   state: {
     status: "ready",
diff --git a/packages/taler-wallet-webextension/src/cta/Pay.tsx 
b/packages/taler-wallet-webextension/src/cta/Pay.tsx
index 0e253014..4f44ebab 100644
--- a/packages/taler-wallet-webextension/src/cta/Pay.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Pay.tsx
@@ -542,23 +542,22 @@ function ButtonsSection({
       );
     }
     if (payStatus.status === PreparePayResultType.InsufficientBalance) {
+      let BalanceMessage = "";
+      if (!state.balance) {
+        BalanceMessage = i18n.str`You have no balance for this currency. 
Withdraw digital cash first.`;
+      } else {
+        const balanceShouldBeEnough =
+          Amounts.cmp(state.balance, state.amount) !== -1;
+        if (balanceShouldBeEnough) {
+          BalanceMessage = i18n.str`Could not find enough coins to pay this 
order. Even if you have enough ${state.balance.currency} some restriction may 
apply.`;
+        } else {
+          BalanceMessage = i18n.str`Your current balance is not enough for 
this order.`;
+        }
+      }
       return (
         <Fragment>
           <section>
-            {state.balance ? (
-              <WarningBox>
-                <i18n.Translate>
-                  Your balance of {<Amount value={state.balance} />} is not
-                  enough to pay for this purchase
-                </i18n.Translate>
-              </WarningBox>
-            ) : (
-              <WarningBox>
-                <i18n.Translate>
-                  Your balance is not enough to pay for this purchase.
-                </i18n.Translate>
-              </WarningBox>
-            )}
+            <WarningBox>{BalanceMessage}</WarningBox>
           </section>
           <section>
             <ButtonSuccess
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx 
b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
index b77e98a1..79f9c220 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
@@ -50,12 +50,24 @@ const normalTosState = {
   reviewing: false,
 };
 
+const ageRestrictionOptions: Record<string, string> = "6:12:18"
+  .split(":")
+  .reduce((p, c) => ({ ...p, [c]: `under ${c}` }), {});
+
+ageRestrictionOptions["0"] = "Not restricted";
+
+const ageRestrictionSelectField = {
+  list: ageRestrictionOptions,
+  value: "0",
+};
+
 export const TermsOfServiceNotYetLoaded = createExample(TestedComponent, {
   state: {
     hook: undefined,
     status: "success",
     cancelEditExchange: nullHandler,
     confirmEditExchange: nullHandler,
+    ageRestriction: ageRestrictionSelectField,
     chosenAmount: {
       currency: "USD",
       value: 2,
@@ -91,6 +103,7 @@ export const WithSomeFee = createExample(TestedComponent, {
     status: "success",
     cancelEditExchange: nullHandler,
     confirmEditExchange: nullHandler,
+    ageRestriction: ageRestrictionSelectField,
     chosenAmount: {
       currency: "USD",
       value: 2,
@@ -127,6 +140,7 @@ export const WithoutFee = createExample(TestedComponent, {
     status: "success",
     cancelEditExchange: nullHandler,
     confirmEditExchange: nullHandler,
+    ageRestriction: ageRestrictionSelectField,
     chosenAmount: {
       currency: "USD",
       value: 2,
@@ -163,6 +177,7 @@ export const EditExchangeUntouched = 
createExample(TestedComponent, {
     status: "success",
     cancelEditExchange: nullHandler,
     confirmEditExchange: nullHandler,
+    ageRestriction: ageRestrictionSelectField,
     chosenAmount: {
       currency: "USD",
       value: 2,
@@ -199,6 +214,7 @@ export const EditExchangeModified = 
createExample(TestedComponent, {
     status: "success",
     cancelEditExchange: nullHandler,
     confirmEditExchange: nullHandler,
+    ageRestriction: ageRestrictionSelectField,
     chosenAmount: {
       currency: "USD",
       value: 2,
@@ -236,3 +252,40 @@ export const CompletedWithoutBankURL = 
createExample(TestedComponent, {
     hook: undefined,
   },
 });
+
+export const WithAgeRestrictionSelected = createExample(TestedComponent, {
+  state: {
+    hook: undefined,
+    status: "success",
+    cancelEditExchange: nullHandler,
+    confirmEditExchange: nullHandler,
+    ageRestriction: ageRestrictionSelectField,
+    chosenAmount: {
+      currency: "USD",
+      value: 2,
+      fraction: 10000000,
+    },
+    doWithdrawal: nullHandler,
+    editExchange: nullHandler,
+    exchange: {
+      list: exchangeList,
+      value: "exchange.demo.taler.net",
+      onChange: async () => {
+        null;
+      },
+    },
+    showExchangeSelection: false,
+    mustAcceptFirst: false,
+    withdrawalFee: {
+      currency: "USD",
+      fraction: 0,
+      value: 0,
+    },
+    toBeReceived: {
+      currency: "USD",
+      fraction: 0,
+      value: 2,
+    },
+    tosProps: normalTosState,
+  },
+});
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx 
b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
index cd0ba2cc..c4bc3457 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
@@ -35,6 +35,7 @@ import { SelectList } from "../components/SelectList.js";
 import {
   ButtonSuccess,
   ButtonWarning,
+  Input,
   LinkSuccess,
   SubTitle,
   SuccessBox,
@@ -43,12 +44,18 @@ import {
 import { useTranslationContext } from "../context/translation.js";
 import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
 import { buildTermsOfServiceState } from "../utils/index.js";
-import { ButtonHandler, SelectFieldHandler } from "../mui/handlers.js";
+import {
+  ButtonHandler,
+  SelectFieldHandler,
+  ToggleHandler,
+} from "../mui/handlers.js";
 import * as wxApi from "../wxApi.js";
 import {
   Props as TermsOfServiceSectionProps,
   TermsOfServiceSection,
 } from "./TermsOfServiceSection.js";
+import { startOfWeekYear } from "date-fns/esm";
+import { Checkbox } from "../components/Checkbox.js";
 
 interface Props {
   talerWithdrawUri?: string;
@@ -97,6 +104,8 @@ type Success = {
   doWithdrawal: ButtonHandler;
   tosProps?: TermsOfServiceSectionProps;
   mustAcceptFirst: boolean;
+
+  ageRestriction: SelectFieldHandler;
 };
 
 export function useComponentState(
@@ -106,6 +115,7 @@ export function useComponentState(
   const [customExchange, setCustomExchange] = useState<string | undefined>(
     undefined,
   );
+  const [ageRestricted, setAgeRestricted] = useState(0);
 
   /**
    * Ask the wallet about the withdraw URI
@@ -228,6 +238,7 @@ export function useComponentState(
       const res = await api.acceptWithdrawal(
         talerWithdrawUri,
         selectedExchange,
+        !ageRestricted ? undefined : ageRestricted,
       );
       if (res.confirmTransferUrl) {
         document.location.href = res.confirmTransferUrl;
@@ -320,6 +331,14 @@ export function useComponentState(
     termsState !== undefined &&
     (termsState.status === "changed" || termsState.status === "new");
 
+  const ageRestrictionOptions: Record<string, string> | undefined = "6:12:18"
+    .split(":")
+    .reduce((p, c) => ({ ...p, [c]: `under ${c}` }), {});
+
+  if (ageRestrictionOptions) {
+    ageRestrictionOptions["0"] = "Not restricted";
+  }
+
   return {
     status: "success",
     hook: undefined,
@@ -331,6 +350,11 @@ export function useComponentState(
     toBeReceived,
     withdrawalFee,
     chosenAmount: amount,
+    ageRestriction: {
+      list: ageRestrictionOptions,
+      value: String(ageRestricted),
+      onChange: async (v) => setAgeRestricted(parseInt(v, 10)),
+    },
     doWithdrawal: {
       onClick:
         doingWithdraw || (mustAcceptFirst && !reviewed)
@@ -486,6 +510,18 @@ export function View({ state }: { state: State }): VNode {
           </LinkSuccess>
         )}
       </section>
+      <section>
+        <Input>
+          <SelectList
+            label={<i18n.Translate>Age restriction</i18n.Translate>}
+            list={state.ageRestriction.list}
+            name="age"
+            maxWidth
+            value={state.ageRestriction.value}
+            onChange={state.ageRestriction.onChange}
+          />
+        </Input>
+      </section>
       {state.tosProps && <TermsOfServiceSection {...state.tosProps} />}
       {state.tosProps ? (
         <section>
diff --git a/packages/taler-wallet-webextension/src/mui/handlers.ts 
b/packages/taler-wallet-webextension/src/mui/handlers.ts
index 60cfee42..646bdcf1 100644
--- a/packages/taler-wallet-webextension/src/mui/handlers.ts
+++ b/packages/taler-wallet-webextension/src/mui/handlers.ts
@@ -17,7 +17,7 @@ export interface ToggleHandler {
 }
 
 export interface SelectFieldHandler {
-  onChange: (value: string) => Promise<void>;
+  onChange?: (value: string) => Promise<void>;
   error?: string;
   value: string;
   isDirty?: boolean;
diff --git 
a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts 
b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts
index a4b333f0..7a9a5314 100644
--- a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts
+++ b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.test.ts
@@ -87,7 +87,7 @@ describe("CreateManualWithdraw states", () => {
       const { exchange, currency } = getLastResultOrThrow()
 
       expect(exchange.value).equal("url2")
-
+      if (currency.onChange === undefined) expect.fail();
       currency.onChange("USD")
     }
 
@@ -111,6 +111,7 @@ describe("CreateManualWithdraw states", () => {
       expect(exchange.value).equal("url2")
       expect(currency.value).equal("ARS")
 
+      if (exchange.onChange === undefined) expect.fail();
       exchange.onChange("url1")
     }
 
@@ -205,6 +206,7 @@ async function defaultTestForInputSelect(awaiter: () => 
Promise<void>, getField:
       throw new Error('no enough values')
     }
     nextValue = keys[nextIdx]
+    if (field.onChange === undefined) expect.fail();
     field.onChange(nextValue)
   }
 
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage.test.ts 
b/packages/taler-wallet-webextension/src/wallet/DepositPage.test.ts
index c863b27d..5fc55934 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage.test.ts
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage.test.ts
@@ -258,6 +258,7 @@ describe("DepositPage states", () => {
       expect(r.depositHandler.onClick).undefined;
       expect(r.totalFee).deep.eq(Amounts.parseOrThrow(`${currency}:0`))
 
+      if (r.account.onChange === undefined) expect.fail();
       r.account.onChange("1")
     }
 
@@ -290,6 +291,7 @@ describe("DepositPage states", () => {
       expect(r.totalToDeposit).deep.eq(Amounts.parseOrThrow(`${currency}:7`))
       expect(r.depositHandler.onClick).undefined;
 
+      if (r.account.onChange === undefined) expect.fail();
       r.account.onChange("0")
     }
 
diff --git a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx 
b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
index 829e60b4..c4725a8d 100644
--- a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
@@ -81,6 +81,7 @@ export function DeveloperPage(): VNode {
 
 type CoinsInfo = CoinDumpJson["coins"];
 type CalculatedCoinfInfo = {
+  ageKeysCount: number | undefined;
   denom_value: number;
   remain_value: number;
   status: string;
@@ -132,11 +133,13 @@ export function View({
   const money_by_exchange = coins.reduce(
     (prev, cur) => {
       const denom = Amounts.parseOrThrow(cur.denom_value);
+      console.log(cur);
       if (!prev[cur.exchange_base_url]) {
         prev[cur.exchange_base_url] = [];
         currencies[cur.exchange_base_url] = denom.currency;
       }
       prev[cur.exchange_base_url].push({
+        ageKeysCount: cur.ageCommitmentProof?.proof.privateKeys.length,
         denom_value: parseFloat(Amounts.stringifyValue(denom)),
         remain_value: parseFloat(
           Amounts.stringifyValue(Amounts.parseOrThrow(cur.remaining_value)),
@@ -305,7 +308,7 @@ function ShowAllCoins({
       <p>
         <b>{ex}</b>: {total} {currencies[ex]}
       </p>
-      <p>
+      <p onClick={() => setCollapsedUnspent(true)}>
         <b>
           <i18n.Translate>usable coins</i18n.Translate>
         </b>
@@ -313,7 +316,7 @@ function ShowAllCoins({
       {collapsedUnspent ? (
         <div onClick={() => setCollapsedUnspent(false)}>click to show</div>
       ) : (
-        <table onClick={() => setCollapsedUnspent(true)}>
+        <table>
           <tr>
             <td>
               <i18n.Translate>id</i18n.Translate>
@@ -330,6 +333,9 @@ function ShowAllCoins({
             <td>
               <i18n.Translate>from refresh?</i18n.Translate>
             </td>
+            <td>
+              <i18n.Translate>age key count</i18n.Translate>
+            </td>
           </tr>
           {coins.usable.map((c, idx) => {
             return (
@@ -339,12 +345,13 @@ function ShowAllCoins({
                 <td>{c.remain_value}</td>
                 <td>{c.status}</td>
                 <td>{c.from_refresh ? "true" : "false"}</td>
+                <td>{String(c.ageKeysCount)}</td>
               </tr>
             );
           })}
         </table>
       )}
-      <p>
+      <p onClick={() => setCollapsedSpent(true)}>
         <i18n.Translate>spent coins</i18n.Translate>
       </p>
       {collapsedSpent ? (
@@ -352,7 +359,7 @@ function ShowAllCoins({
           <i18n.Translate>click to show</i18n.Translate>
         </div>
       ) : (
-        <table onClick={() => setCollapsedSpent(true)}>
+        <table>
           <tr>
             <td>
               <i18n.Translate>id</i18n.Translate>
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts 
b/packages/taler-wallet-webextension/src/wxApi.ts
index b4882664..dd4eb2cf 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -324,10 +324,12 @@ export function preparePay(talerPayUri: string): 
Promise<PreparePayResult> {
 export function acceptWithdrawal(
   talerWithdrawUri: string,
   selectedExchange: string,
+  restrictAge?: number,
 ): Promise<AcceptWithdrawalResponse> {
   return callBackend("acceptBankIntegratedWithdrawal", {
     talerWithdrawUri,
     exchangeBaseUrl: selectedExchange,
+    restrictAge
   });
 }
 
@@ -340,10 +342,12 @@ export function acceptWithdrawal(
 export function acceptManualWithdrawal(
   exchangeBaseUrl: string,
   amount: string,
+  restrictAge?: number,
 ): Promise<AcceptManualWithdrawalResult> {
   return callBackend("acceptManualWithdrawal", {
     amount,
     exchangeBaseUrl,
+    restrictAge
   });
 }
 

-- 
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]