gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated (f16d2e52 -> 7a2fe801)


From: gnunet
Subject: [taler-wallet-core] branch master updated (f16d2e52 -> 7a2fe801)
Date: Wed, 04 May 2022 21:27:03 +0200

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

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

    from f16d2e52 wallet-core: implement batch withdrawal
     new 44911184 add restricted option to manual withdraw
     new 7a2fe801 add age restriction option to withdraw cta

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 packages/taler-util/src/talerCrypto.ts             |  6 +--
 packages/taler-util/src/talerTypes.ts              |  7 ++-
 packages/taler-util/src/walletTypes.ts             |  2 +
 packages/taler-wallet-cli/src/index.ts             |  2 +
 .../src/util/coinSelection.test.ts                 | 42 +++++++++++++++++
 packages/taler-wallet-core/src/wallet.ts           |  5 ++
 .../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 ++
 17 files changed, 226 insertions(+), 30 deletions(-)

diff --git a/packages/taler-util/src/talerCrypto.ts 
b/packages/taler-util/src/talerCrypto.ts
index 228dc326..e27e329a 100644
--- a/packages/taler-util/src/talerCrypto.ts
+++ b/packages/taler-util/src/talerCrypto.ts
@@ -664,7 +664,6 @@ export function hashDenomPub(pub: DenominationPubKey): 
Uint8Array {
     const hashInputBuf = new ArrayBuffer(pubBuf.length + 4 + 4);
     const uint8ArrayBuf = new Uint8Array(hashInputBuf);
     const dv = new DataView(hashInputBuf);
-    logger.info("age_mask", pub.age_mask);
     dv.setUint32(0, pub.age_mask ?? 0);
     dv.setUint32(4, DenomKeyType.toIntTag(pub.cipher));
     uint8ArrayBuf.set(pubBuf, 8);
@@ -680,8 +679,7 @@ export function hashDenomPub(pub: DenominationPubKey): 
Uint8Array {
     return nacl.hash(uint8ArrayBuf);
   } else {
     throw Error(
-      `unsupported cipher (${
-        (pub as DenominationPubKey).cipher
+      `unsupported cipher (${(pub as DenominationPubKey).cipher
       }), unable to hash`,
     );
   }
@@ -785,7 +783,7 @@ export enum TalerSignaturePurpose {
 export class SignaturePurposeBuilder {
   private chunks: Uint8Array[] = [];
 
-  constructor(private purposeNum: number) {}
+  constructor(private purposeNum: number) { }
 
   put(bytes: Uint8Array): SignaturePurposeBuilder {
     this.chunks.push(Uint8Array.from(bytes));
diff --git a/packages/taler-util/src/talerTypes.ts 
b/packages/taler-util/src/talerTypes.ts
index ffc1f516..b21c6cae 100644
--- a/packages/taler-util/src/talerTypes.ts
+++ b/packages/taler-util/src/talerTypes.ts
@@ -47,7 +47,7 @@ import {
 } from "./time.js";
 import { codecForAmountString } from "./amounts.js";
 import { strcmp } from "./helpers.js";
-import { Edx25519PublicKey } from "./talerCrypto.js";
+import { AgeCommitmentProof, Edx25519PublicKey } from "./talerCrypto.js";
 
 /**
  * Denomination as found in the /keys response from the exchange.
@@ -954,6 +954,11 @@ export interface CoinDumpJson {
      * Suspended coins are not considered for payments.
      */
     coin_suspended: boolean;
+
+    /**
+     * Information about the age restriction
+     */
+    ageCommitmentProof: AgeCommitmentProof | undefined;
   }>;
 }
 
diff --git a/packages/taler-util/src/walletTypes.ts 
b/packages/taler-util/src/walletTypes.ts
index d8696377..a8946fbb 100644
--- a/packages/taler-util/src/walletTypes.ts
+++ b/packages/taler-util/src/walletTypes.ts
@@ -738,6 +738,7 @@ export const codecForGetExchangeTosRequest = (): 
Codec<GetExchangeTosRequest> =>
 export interface AcceptManualWithdrawalRequest {
   exchangeBaseUrl: string;
   amount: string;
+  restrictAge?: number,
 }
 
 export const codecForAcceptManualWithdrawalRequet =
@@ -745,6 +746,7 @@ export const codecForAcceptManualWithdrawalRequet =
     buildCodecForObject<AcceptManualWithdrawalRequest>()
       .property("exchangeBaseUrl", codecForString())
       .property("amount", codecForString())
+      .property("restrictAge", codecOptional(codecForNumber()))
       .build("AcceptManualWithdrawalRequest");
 
 export interface GetWithdrawalDetailsForAmountRequest {
diff --git a/packages/taler-wallet-cli/src/index.ts 
b/packages/taler-wallet-cli/src/index.ts
index a4c99902..5ba6e4bf 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -775,6 +775,7 @@ advancedCli
   .requiredOption("amount", ["--amount"], clk.STRING, {
     help: "Amount to withdraw",
   })
+  .maybeOption("restrictAge", ["--restrict-age"], clk.INT)
   .action(async (args) => {
     await withWallet(args, async (wallet) => {
       const exchangeBaseUrl = args.withdrawManually.exchange;
@@ -796,6 +797,7 @@ advancedCli
         {
           amount,
           exchangeBaseUrl,
+          restrictAge: parseInt(String(args.withdrawManually.restrictAge), 10),
         },
       );
       const reservePub = resp.reservePub;
diff --git a/packages/taler-wallet-core/src/util/coinSelection.test.ts 
b/packages/taler-wallet-core/src/util/coinSelection.test.ts
index dc64a57d..ca7b76eb 100644
--- a/packages/taler-wallet-core/src/util/coinSelection.test.ts
+++ b/packages/taler-wallet-core/src/util/coinSelection.test.ts
@@ -43,6 +43,20 @@ function fakeAci(current: string, feeDeposit: string): 
AvailableCoinInfo {
   };
 }
 
+function fakeAciWithAgeRestriction(current: string, feeDeposit: string): 
AvailableCoinInfo {
+  return {
+    availableAmount: a(current),
+    coinPub: "foobar",
+    denomPub: {
+      cipher: DenomKeyType.Rsa,
+      rsa_public_key: "foobar",
+      age_mask: 2446657,
+    },
+    feeDeposit: a(feeDeposit),
+    exchangeBaseUrl: "https://example.com/";,
+  };
+}
+
 test("it should be able to pay if merchant takes the fees", (t) => {
   const acis: AvailableCoinInfo[] = [
     fakeAci("EUR:1.0", "EUR:0.1"),
@@ -267,3 +281,31 @@ test("coin selection 9", (t) => {
   );
   t.pass();
 });
+
+
+test("it should be able to use unrestricted coins for age restricted 
contract", (t) => {
+  const acis: AvailableCoinInfo[] = [
+    fakeAciWithAgeRestriction("EUR:1.0", "EUR:0.2"),
+    fakeAciWithAgeRestriction("EUR:0.2", "EUR:0.2"),
+  ];
+  const res = selectPayCoins({
+    candidates: {
+      candidateCoins: acis,
+      wireFeesPerExchange: {},
+    },
+    contractTermsAmount: a("EUR:1.2"),
+    depositFeeLimit: a("EUR:0.4"),
+    wireFeeLimit: a("EUR:0"),
+    wireFeeAmortization: 1,
+    requiredMinimumAge: 13
+  });
+  if (!res) {
+    t.fail();
+    return;
+  }
+  t.true(res.coinContributions.length === 2);
+  t.true(
+    Amounts.cmp(Amounts.sum(res.coinContributions).amount, "EUR:1.2") === 0,
+  );
+  t.pass();
+});
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index fb61ae0d..053a0763 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -454,11 +454,14 @@ async function acceptManualWithdrawal(
   ws: InternalWalletState,
   exchangeBaseUrl: string,
   amount: AmountJson,
+  restrictAge?: number,
+
 ): Promise<AcceptManualWithdrawalResult> {
   try {
     const resp = await createReserve(ws, {
       amount,
       exchange: exchangeBaseUrl,
+      restrictAge
     });
     const exchangePaytoUris = await ws.db
       .mktx((x) => ({
@@ -690,6 +693,7 @@ async function dumpCoins(ws: InternalWalletState): 
Promise<CoinDumpJson> {
           remaining_value: Amounts.stringify(c.currentAmount),
           withdrawal_reserve_pub: withdrawalReservePub,
           coin_suspended: c.suspended,
+          ageCommitmentProof: c.ageCommitmentProof,
         });
       }
     });
@@ -801,6 +805,7 @@ async function dispatchRequestInternal(
         ws,
         req.exchangeBaseUrl,
         Amounts.parseOrThrow(req.amount),
+        req.restrictAge
       );
       return res;
     }
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]