gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: first approach to new design


From: gnunet
Subject: [taler-wallet-core] branch master updated: first approach to new design for withdraw
Date: Wed, 08 Sep 2021 20:35:52 +0200

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

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

The following commit(s) were added to refs/heads/master by this push:
     new 217f3439 first approach to new design for withdraw
217f3439 is described below

commit 217f34397f95fc988280eee9c376efe0781c69ea
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Wed Sep 8 15:30:32 2021 -0300

    first approach to new design for withdraw
---
 packages/taler-util/src/walletTypes.ts             |  13 +-
 .../taler-wallet-core/src/operations/withdraw.ts   |   2 +-
 packages/taler-wallet-core/src/wallet.ts           |   5 +
 .../.storybook/preview.js                          |   1 -
 .../src/components/Part.tsx                        |  16 +++
 .../src/components/styled/index.tsx                |  19 ++-
 packages/taler-wallet-webextension/src/cta/Pay.tsx |   4 +-
 .../src/cta/Withdraw.stories.tsx                   |  34 +++--
 .../taler-wallet-webextension/src/cta/Withdraw.tsx | 148 ++++++++++-----------
 .../src/wallet/Transaction.tsx                     |  12 +-
 packages/taler-wallet-webextension/src/wxApi.ts    |  12 ++
 11 files changed, 160 insertions(+), 106 deletions(-)

diff --git a/packages/taler-util/src/walletTypes.ts 
b/packages/taler-util/src/walletTypes.ts
index 6e71de6e..7ec182fa 100644
--- a/packages/taler-util/src/walletTypes.ts
+++ b/packages/taler-util/src/walletTypes.ts
@@ -713,6 +713,17 @@ export const codecForGetWithdrawalDetailsForUri = (): 
Codec<GetWithdrawalDetails
     .property("talerWithdrawUri", codecForString())
     .build("GetWithdrawalDetailsForUriRequest");
 
+export interface GetExchangeWithdrawalInfo {
+  exchangeBaseUrl: string;
+  amount: AmountJson;
+}
+
+export const codecForGetExchangeWithdrawalInfo = (): 
Codec<GetExchangeWithdrawalInfo> =>
+  buildCodecForObject<GetExchangeWithdrawalInfo>()
+    .property("exchangeBaseUrl", codecForString())
+    .property("amount", codecForAmountJson())
+    .build("GetExchangeWithdrawalInfo");
+
 export interface AbortProposalRequest {
   proposalId: string;
 }
@@ -791,7 +802,7 @@ export interface MakeSyncSignatureRequest {
 /**
  * Planchet for a coin during refresh.
  */
- export interface RefreshPlanchetInfo {
+export interface RefreshPlanchetInfo {
   /**
    * Public key for the coin.
    */
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts 
b/packages/taler-wallet-core/src/operations/withdraw.ts
index e6b6e874..620ad88b 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -92,7 +92,7 @@ interface DenominationSelectionInfo {
  *
  * Sent to the wallet frontend to be rendered and shown to the user.
  */
-interface ExchangeWithdrawDetails {
+export interface ExchangeWithdrawDetails {
   /**
    * Exchange that the reserve will be created at.
    */
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index fec7e615..cbaf03c3 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -28,6 +28,7 @@ import {
   codecForDeleteTransactionRequest,
   codecForRetryTransactionRequest,
   codecForSetWalletDeviceIdRequest,
+  codecForGetExchangeWithdrawalInfo,
   durationFromSpec,
   durationMin,
   getDurationRemaining,
@@ -693,6 +694,10 @@ async function dispatchRequestInternal(
       const req = codecForGetWithdrawalDetailsForUri().decode(payload);
       return await getWithdrawalDetailsForUri(ws, req.talerWithdrawUri);
     }
+    case "getExchangeWithdrawalInfo": {
+      const req = codecForGetExchangeWithdrawalInfo().decode(payload);
+      return await getExchangeWithdrawalInfo(ws, req.exchangeBaseUrl, 
req.amount);
+    }
     case "acceptManualWithdrawal": {
       const req = codecForAcceptManualWithdrawalRequet().decode(payload);
       const res = await acceptManualWithdrawal(
diff --git a/packages/taler-wallet-webextension/.storybook/preview.js 
b/packages/taler-wallet-webextension/.storybook/preview.js
index 48866346..0efb9630 100644
--- a/packages/taler-wallet-webextension/.storybook/preview.js
+++ b/packages/taler-wallet-webextension/.storybook/preview.js
@@ -119,7 +119,6 @@ export const decorators = [
           margin: 0;
           font-size: 100%;
           padding: 0;
-          background-color: #f8faf7;
           font-family: Arial, Helvetica, sans-serif;
         }`}
         </style>
diff --git a/packages/taler-wallet-webextension/src/components/Part.tsx 
b/packages/taler-wallet-webextension/src/components/Part.tsx
new file mode 100644
index 00000000..87b16de8
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/components/Part.tsx
@@ -0,0 +1,16 @@
+import { AmountLike } from "@gnu-taler/taler-util";
+import { ExtraLargeText, LargeText, SmallLightText } from "./styled";
+
+export type Kind = 'positive' | 'negative' | 'neutral';
+interface Props {
+  title: string, text: AmountLike, kind: Kind, big?: boolean
+}
+export function Part({ text, title, kind, big }: Props) {
+  const Text = big ? ExtraLargeText : LargeText;
+  return <div style={{ margin: '1em' }}>
+    <SmallLightText style={{ margin: '.5em' }}>{title}</SmallLightText>
+    <Text style={{ color: kind == 'positive' ? 'green' : (kind == 'negative' ? 
'red' : 'black') }}>
+      {text}
+    </Text>
+  </div>
+}
diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx 
b/packages/taler-wallet-webextension/src/components/styled/index.tsx
index de045584..553726de 100644
--- a/packages/taler-wallet-webextension/src/components/styled/index.tsx
+++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx
@@ -12,6 +12,16 @@ export const PaymentStatus = styled.div<{ color: string }>`
 `
 
 export const WalletAction = styled.section`
+  max-width: 50%;
+
+  margin: auto;
+  height: 100%;
+  
+  & h1:first-child {
+    margin-top: 0; 
+  }
+`
+export const WalletActionOld = styled.section`
   border: solid 5px black;
   border-radius: 10px;
   margin-left: auto;
@@ -152,7 +162,7 @@ export const PopupBox = styled.div<{ noPadding?: boolean }>`
 
 `
 
-export const Button = styled.button`
+export const Button = styled.button<{ upperCased?: boolean }>`
   display: inline-block;
   zoom: 1;
   line-height: normal;
@@ -162,6 +172,7 @@ export const Button = styled.button`
   cursor: pointer;
   user-select: none;
   box-sizing: border-box;
+  text-transform: ${({ upperCased }) => upperCased ? 'uppercase' : 'none'};
 
   font-family: inherit;
   font-size: 100%;
@@ -242,11 +253,11 @@ export const ButtonBoxPrimary = styled(ButtonBox)`
 `
 
 export const ButtonSuccess = styled(ButtonVariant)`
-  background-color: rgb(28, 184, 65);
+  background-color: #388e3c;
 `
 export const ButtonBoxSuccess = styled(ButtonBox)`
-  color: rgb(28, 184, 65);
-  border-color: rgb(28, 184, 65);
+  color: #388e3c;
+  border-color: #388e3c;
 `
 
 export const ButtonWarning = styled(ButtonVariant)`
diff --git a/packages/taler-wallet-webextension/src/cta/Pay.tsx 
b/packages/taler-wallet-webextension/src/cta/Pay.tsx
index 24c76ce6..758bc4b5 100644
--- a/packages/taler-wallet-webextension/src/cta/Pay.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Pay.tsx
@@ -136,7 +136,9 @@ export function PayPage({ talerPayUri }: Props): 
JSX.Element {
       setPayResult(res);
     } catch (e) {
       console.error(e);
-      setPayErrMsg(e.message);
+      if (e instanceof Error) {
+        setPayErrMsg(e.message);
+      }
     }
 
   }
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx 
b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
index 747f855f..a89a18c1 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
@@ -19,6 +19,9 @@
 * @author Sebastian Javier Marchano (sebasjm)
 */
 
+import { amountFractionalBase, Amounts } from '@gnu-taler/taler-util';
+import { ExchangeRecord } from '@gnu-taler/taler-wallet-core';
+import { ExchangeWithdrawDetails } from 
'@gnu-taler/taler-wallet-core/src/operations/withdraw';
 import { createExample } from '../test-utils';
 import { View as TestedComponent } from './Withdraw';
 
@@ -30,16 +33,29 @@ export default {
   },
 };
 
-export const CompleteWithExchange = createExample(TestedComponent, {
+export const WithdrawWithFee = createExample(TestedComponent, {
   details: {
-    amount: 'USD:2',
-    possibleExchanges: [],
-  },
-  selectedExchange: 'Some exchange'
+    exchangeInfo: {
+      baseUrl: 'exchange.demo.taler.net'
+    } as ExchangeRecord,
+    withdrawFee: {
+      currency: 'USD',
+      fraction: amountFractionalBase*0.5,
+      value: 0
+    },
+  } as ExchangeWithdrawDetails,
+  amount: 'USD:2',
 })
-export const CompleteWithoutExchange = createExample(TestedComponent, {
+export const WithdrawWithoutFee = createExample(TestedComponent, {
   details: {
-    amount: 'USD:2',
-    possibleExchanges: [],
-  },
+    exchangeInfo: {
+      baseUrl: 'exchange.demo.taler.net'
+    } as ExchangeRecord,
+    withdrawFee: {
+      currency: 'USD',
+      fraction: 0,
+      value: 0
+    },
+  } as ExchangeWithdrawDetails,
+  amount: 'USD:2',
 })
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx 
b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
index d5f3c89a..9719b8f5 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
@@ -21,98 +21,78 @@
  * @author Florian Dold
  */
 
-import { i18n } from '@gnu-taler/taler-util'
-import { renderAmount } from "../renderHtml";
-
-import { useState, useEffect } from "preact/hooks";
+import { AmountLike, Amounts, i18n, WithdrawUriInfoResponse } from 
'@gnu-taler/taler-util';
+import { ExchangeWithdrawDetails } from 
'@gnu-taler/taler-wallet-core/src/operations/withdraw';
+import { useEffect, useState } from "preact/hooks";
+import { JSX } from "preact/jsx-runtime";
+import { LogoHeader } from '../components/LogoHeader';
+import { Part } from '../components/Part';
+import { ButtonSuccess, WalletAction } from '../components/styled';
 import {
-  acceptWithdrawal,
-  onUpdateNotification,
-  getWithdrawalDetailsForUri,
+  acceptWithdrawal, getExchangeWithdrawalInfo, getWithdrawalDetailsForUri, 
onUpdateNotification
 } from "../wxApi";
-import { h } from 'preact';
-import { WithdrawUriInfoResponse } from "@gnu-taler/taler-util";
-import { JSX } from "preact/jsx-runtime";
-import { WalletAction } from '../components/styled';
+
 
 interface Props {
   talerWithdrawUri?: string;
 }
 
 export interface ViewProps {
-  details: WithdrawUriInfoResponse;
-  selectedExchange?: string;
+  details: ExchangeWithdrawDetails;
+  amount: string;
   accept: () => Promise<void>;
   setCancelled: (b: boolean) => void;
   setSelecting: (b: boolean) => void;
 };
 
-export function View({ details, selectedExchange, accept, setCancelled, 
setSelecting }: ViewProps) {
+function amountToString(text: AmountLike) {
+  const aj = Amounts.jsonifyAmount(text)
+  const amount = Amounts.stringifyValue(aj)
+  return `${amount} ${aj.currency}`
+}
+
+
+export function View({ details, amount, accept, setCancelled, setSelecting }: 
ViewProps) {
 
   return (
-    <WalletAction>
-      <div style="border-bottom: 3px dashed #aa3939; margin-bottom: 2em;">
-        <h1 style="font-family: monospace; font-size: 250%;">
-          <span style="color: #aa3939;">❰</span>Taler Wallet<span 
style="color: #aa3939;">❱</span>
-        </h1>
-      </div>
-      <div class="fade">
+    <WalletAction style={{ textAlign: 'center' }}>
+      <LogoHeader />
+      <h2>
+        {i18n.str`Digital cash withdrawal`}
+      </h2>
+      <section>
+        <div>
+          <Part title="Total to withdraw" 
text={amountToString(Amounts.sub(Amounts.parseOrThrow(amount), 
details.withdrawFee).amount)} kind='positive' />
+          <Part title="Chosen amount" text={amountToString(amount)} 
kind='neutral' />
+          {Amounts.isNonZero(details.withdrawFee) &&
+            <Part title="Exchange fee" 
text={amountToString(details.withdrawFee)} kind='negative' />
+          }
+          <Part title="Exchange" text={details.exchangeInfo.baseUrl} 
kind='neutral' big />
+        </div>
+      </section>
+      <section>
+
         <div>
-          <h1><i18n.Translate>Digital Cash Withdrawal</i18n.Translate></h1>
-          <p><i18n.Translate>
-            You are about to withdraw{" "}
-            <strong>{renderAmount(details.amount)}</strong> from your bank 
account
-            into your wallet.
-          </i18n.Translate></p>
-          {selectedExchange ? (
-            <p><i18n.Translate>
-              The exchange <strong>{selectedExchange}</strong> will be used as 
the
-              Taler payment service provider.
-            </i18n.Translate></p>
-          ) : null}
-
-          <div>
-            <button
-              class="pure-button button-success"
-              disabled={!selectedExchange}
-              onClick={() => accept()}
-            >
-              {i18n.str`Accept fees and withdraw`}
-            </button>
-            <p>
-              <span
-                role="button"
-                tabIndex={0}
-                style={{ textDecoration: "underline", cursor: "pointer" }}
-                onClick={() => setSelecting(true)}
-              >
-                {i18n.str`Chose different exchange provider`}
-              </span>
-              <br />
-              <span
-                role="button"
-                tabIndex={0}
-                style={{ textDecoration: "underline", cursor: "pointer" }}
-                onClick={() => setCancelled(true)}
-              >
-                {i18n.str`Cancel withdraw operation`}
-              </span>
-            </p>
-          </div>
+          <ButtonSuccess
+            upperCased
+            disabled={!details.exchangeInfo.baseUrl}
+            onClick={accept}
+          >
+            {i18n.str`Accept fees and withdraw`}
+          </ButtonSuccess>
         </div>
-      </div>
+      </section>
     </WalletAction>
   )
 }
 
 export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): 
JSX.Element {
-  const [details, setDetails] = useState<WithdrawUriInfoResponse | 
undefined>(undefined);
-  const [selectedExchange, setSelectedExchange] = useState<string | 
undefined>(undefined);
+  const [uriInfo, setUriInfo] = useState<WithdrawUriInfoResponse | 
undefined>(undefined);
+  const [details, setDetails] = useState<ExchangeWithdrawDetails | 
undefined>(undefined);
   const [cancelled, setCancelled] = useState(false);
   const [selecting, setSelecting] = useState(false);
   const [error, setError] = useState<boolean>(false);
   const [updateCounter, setUpdateCounter] = useState(1);
-  const [state, setState] = useState(1)
 
   useEffect(() => {
     return onUpdateNotification(() => {
@@ -127,47 +107,59 @@ export function WithdrawPage({ talerWithdrawUri, ...rest 
}: Props): JSX.Element
     const fetchData = async (): Promise<void> => {
       try {
         const res = await getWithdrawalDetailsForUri({ talerWithdrawUri });
-        setDetails(res);
-        if (res.defaultExchangeBaseUrl) {
-          setSelectedExchange(res.defaultExchangeBaseUrl);
-        }
+        setUriInfo(res);
       } catch (e) {
         console.error('error', JSON.stringify(e, undefined, 2))
         setError(true)
       }
     };
     fetchData();
-  }, [selectedExchange, selecting, talerWithdrawUri, updateCounter, state]);
+  }, [selecting, talerWithdrawUri, updateCounter]);
+
+  useEffect(() => {
+    async function fetchData() {
+      if (!uriInfo || !uriInfo.defaultExchangeBaseUrl) return
+      const res = await getExchangeWithdrawalInfo({
+        exchangeBaseUrl: uriInfo.defaultExchangeBaseUrl,
+        amount: Amounts.parseOrThrow(uriInfo.amount)
+      })
+      setDetails(res)
+    }
+    fetchData()
+  }, [uriInfo])
 
   if (!talerWithdrawUri) {
     return <span><i18n.Translate>missing withdraw uri</i18n.Translate></span>;
   }
 
   const accept = async (): Promise<void> => {
-    if (!selectedExchange) {
+    if (!details) {
       throw Error("can't accept, no exchange selected");
     }
-    console.log("accepting exchange", selectedExchange);
-    const res = await acceptWithdrawal(talerWithdrawUri, selectedExchange);
+    console.log("accepting exchange", details.exchangeInfo.baseUrl);
+    const res = await acceptWithdrawal(talerWithdrawUri, 
details.exchangeInfo.baseUrl);
     console.log("accept withdrawal response", res);
     if (res.confirmTransferUrl) {
       document.location.href = res.confirmTransferUrl;
     }
   };
 
-  if (!details) {
-    return <span><i18n.Translate>Loading...</i18n.Translate></span>;
-  }
   if (cancelled) {
     return <span><i18n.Translate>Withdraw operation has been 
cancelled.</i18n.Translate></span>;
   }
   if (error) {
     return <span><i18n.Translate>This URI is not valid 
anymore.</i18n.Translate></span>;
   }
+  if (!uriInfo) {
+    return <span><i18n.Translate>Loading...</i18n.Translate></span>;
+  }
+  if (!details) {
+    return <span><i18n.Translate>Getting withdrawal 
details.</i18n.Translate></span>;
+  }
 
   return <View accept={accept}
     setCancelled={setCancelled} setSelecting={setSelecting}
-    details={details} selectedExchange={selectedExchange}
+    details={details} amount={uriInfo.amount}
   />
 }
 
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx 
b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index cc5430d0..43575372 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -24,6 +24,7 @@ import { Pages } from "../NavigationBar";
 import emptyImg from "../../static/img/empty.png"
 import { Button, ButtonBox, ButtonBoxDestructive, ButtonDestructive, 
ButtonPrimary, ExtraLargeText, FontIcon, LargeText, ListOfProducts, PopupBox, 
Row, RowBorderGray, SmallLightText, WalletBox } from "../components/styled";
 import { ErrorMessage } from "../components/ErrorMessage";
+import { Part } from "../components/Part";
 
 export function TransactionPage({ tid }: { tid: string; }): JSX.Element {
   const [transaction, setTransaction] = useState<
@@ -60,7 +61,6 @@ export interface WalletTransactionProps {
   onBack: () => void,
 }
 
-
 export function TransactionView({ transaction, onDelete, onRetry, onBack }: 
WalletTransactionProps) {
 
   function Status() {
@@ -90,16 +90,6 @@ export function TransactionView({ transaction, onDelete, 
onRetry, onBack }: Wall
       </footer>
     </WalletBox>
   }
-  type Kind = 'positive' | 'negative' | 'neutral';
-  function Part({ text, title, kind, big }: { title: string, text: AmountLike, 
kind: Kind, big?: boolean }) {
-    const Text = big ? ExtraLargeText : LargeText;
-    return <div style={{ margin: '1em' }}>
-      <SmallLightText style={{ margin: '.5em' }}>{title}</SmallLightText>
-      <Text style={{ color: kind == 'positive' ? 'green' : (kind == 'negative' 
? 'red' : 'black') }}>
-        {text}
-      </Text>
-    </div>
-  }
 
   function amountToString(text: AmountLike) {
     const aj = Amounts.jsonifyAmount(text)
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts 
b/packages/taler-wallet-webextension/src/wxApi.ts
index 52ce27f2..acb28ffe 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -38,9 +38,11 @@ import {
   DeleteTransactionRequest,
   RetryTransactionRequest,
   SetWalletDeviceIdRequest,
+  GetExchangeWithdrawalInfo,
 } from "@gnu-taler/taler-util";
 import { AddBackupProviderRequest, BackupProviderState, OperationFailedError, 
RemoveBackupProviderRequest } from "@gnu-taler/taler-wallet-core";
 import { BackupInfo } from "@gnu-taler/taler-wallet-core";
+import { ExchangeWithdrawDetails } from 
"@gnu-taler/taler-wallet-core/src/operations/withdraw";
 
 export interface ExtendedPermissionsResponse {
   newValue: boolean;
@@ -281,6 +283,16 @@ export function getWithdrawalDetailsForUri(
   return callBackend("getWithdrawalDetailsForUri", req);
 }
 
+
+/**
+ * Get diagnostics information
+ */
+ export function getExchangeWithdrawalInfo(
+  req: GetExchangeWithdrawalInfo,
+): Promise<ExchangeWithdrawDetails> {
+  return callBackend("getExchangeWithdrawalInfo", req);
+}
+
 export function prepareTip(req: PrepareTipRequest): Promise<PrepareTipResult> {
   return callBackend("prepareTip", req);
 }

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