gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] 01/02: withdraw design


From: gnunet
Subject: [taler-wallet-core] 01/02: withdraw design
Date: Mon, 13 Sep 2021 18:33:24 +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 c24db59be8b2eba013cba3f65d14be8e700bc206
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Mon Sep 13 13:32:58 2021 -0300

    withdraw design
---
 .../src/components/CheckboxOutlined.tsx            |  57 +++
 .../src/components/ExchangeToS.tsx                 |  51 +++
 .../src/components/styled/index.tsx                | 198 ++++++++-
 .../src/cta/Withdraw.stories.tsx                   | 491 ++++++++++++++++++++-
 .../taler-wallet-webextension/src/cta/Withdraw.tsx | 152 ++++++-
 5 files changed, 926 insertions(+), 23 deletions(-)

diff --git 
a/packages/taler-wallet-webextension/src/components/CheckboxOutlined.tsx 
b/packages/taler-wallet-webextension/src/components/CheckboxOutlined.tsx
new file mode 100644
index 00000000..e596797c
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/components/CheckboxOutlined.tsx
@@ -0,0 +1,57 @@
+/*
+ This file is part of GNU Taler
+ (C) 2019 Taler Systems SA
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { JSX } from "preact/jsx-runtime";
+import { Outlined, StyledCheckboxLabel } from "./styled/index";
+
+interface Props {
+  enabled: boolean;
+  onToggle: () => void;
+  label: string;
+  name: string;
+}
+
+
+const Tick = () => <svg
+  xmlns="http://www.w3.org/2000/svg";
+  viewBox="0 0 24 24"
+  aria-hidden="true"
+  focusable="false"
+  style={{ backgroundColor: 'green' }}
+>
+  <path
+    fill="none"
+    stroke="white"
+    stroke-width="3"
+    d="M1.73 12.91l6.37 6.37L22.79 4.59"
+  />
+</svg>
+
+export function CheckboxOutlined({ name, enabled, onToggle, label }: Props): 
JSX.Element {
+  return (
+    <Outlined>
+      <StyledCheckboxLabel onClick={onToggle}>
+        <span>
+          <input type="checkbox" name={name} checked={enabled} 
disabled={false} />
+          <div>
+            <Tick />
+          </div>
+          <label for={name}>{label}</label>
+        </span>
+      </StyledCheckboxLabel>
+    </Outlined>
+  );
+}
diff --git a/packages/taler-wallet-webextension/src/components/ExchangeToS.tsx 
b/packages/taler-wallet-webextension/src/components/ExchangeToS.tsx
new file mode 100644
index 00000000..7e029d47
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/components/ExchangeToS.tsx
@@ -0,0 +1,51 @@
+import { Fragment, VNode } from "preact"
+import { useState } from "preact/hooks"
+import { JSXInternal } from "preact/src/jsx"
+
+export function ExchangeXmlTos({ doc }: { doc: Document }) {
+  const termsNode = doc.querySelector('[ids=terms-of-service]')
+  if (!termsNode) {
+    return <div>not found</div>
+  }
+  return <Fragment>
+    {Array.from(termsNode.children).map(renderChild)}
+  </Fragment>
+}
+
+function renderChild(child: Element): VNode {
+  const children = Array.from(child.children)
+  switch (child.nodeName) {
+    case 'title': return <header>{child.textContent}</header>
+    case '#text': return <Fragment />
+    case 'paragraph': return <p>{child.textContent}</p>
+    case 'section': {
+      return <AnchorWithOpenState href={`#terms-${child.getAttribute('ids')}`}>
+        {children.map(renderChild)}
+      </AnchorWithOpenState>
+    }
+    case 'bullet_list': {
+      return <ul>{children.map(renderChild)}</ul>
+    }
+    case 'enumerated_list': {
+      return <ol>{children.map(renderChild)}</ol>
+    }
+    case 'list_item': {
+      return <li>{children.map(renderChild)}</li>
+    }
+    case 'block_quote': {
+      return <div>{children.map(renderChild)}</div>
+    }
+    default: return <div style={{ color: 'red', display: 'hidden' }}>unknown 
tag {child.nodeName} <a></a></div>
+  }
+}
+
+function AnchorWithOpenState(props: 
JSXInternal.HTMLAttributes<HTMLAnchorElement>) {
+  const [open, setOpen] = useState<boolean>(false)
+  function doClick(e: JSXInternal.TargetedMouseEvent<HTMLAnchorElement>) {
+    setOpen(!open);
+    e.stopPropagation();
+    e.preventDefault();
+  }
+  return <a data-open={JSON.stringify(open)} onClick={doClick} {...props} />
+}
+
diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx 
b/packages/taler-wallet-webextension/src/components/styled/index.tsx
index 553726de..f4b8c088 100644
--- a/packages/taler-wallet-webextension/src/components/styled/index.tsx
+++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx
@@ -12,6 +12,10 @@ export const PaymentStatus = styled.div<{ color: string }>`
 `
 
 export const WalletAction = styled.section`
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  align-items: center;
   max-width: 50%;
 
   margin: auto;
@@ -20,6 +24,9 @@ export const WalletAction = styled.section`
   & h1:first-child {
     margin-top: 0; 
   }
+  section {
+    margin-bottom: 2em;
+  }
 `
 export const WalletActionOld = styled.section`
   border: solid 5px black;
@@ -211,6 +218,51 @@ export const Button = styled.button<{ upperCased?: boolean 
}>`
   }
 `;
 
+export const Link = styled.a<{ upperCased?: boolean }>`
+  display: inline-block;
+  zoom: 1;
+  line-height: normal;
+  white-space: nowrap;
+  vertical-align: middle;
+  text-align: center;
+  cursor: pointer;
+  user-select: none;
+  box-sizing: border-box;
+  text-transform: ${({ upperCased }) => upperCased ? 'uppercase' : 'none'};
+
+  font-family: inherit;
+  font-size: 100%;
+  padding: 0.5em 1em;
+  background-color: transparent;
+  text-decoration: none;
+
+  :focus {
+    outline: 0;
+  }
+
+  &:disabled {
+    border: none;
+    background-image: none;
+    /* csslint ignore:start */
+    filter: alpha(opacity=40);
+    /* csslint ignore:end */
+    opacity: 0.4;
+    cursor: not-allowed;
+    box-shadow: none;
+    pointer-events: none;
+  }
+
+  :hover {
+    text-decoration: underline;
+    /* filter: alpha(opacity=90);
+    background-image: linear-gradient(
+      transparent,
+      rgba(0, 0, 0, 0.05) 40%,
+      rgba(0, 0, 0, 0.1)
+    ); */
+  }
+`;
+
 export const FontIcon = styled.div`
   font-family: monospace;
   font-size: x-large;
@@ -220,7 +272,7 @@ export const FontIcon = styled.div`
 `
 export const ButtonBox = styled(Button)`
   padding: .5em;
-  width: 2em;
+  width: fit-content;
   height: 2em;
 
   & > ${FontIcon} {
@@ -255,6 +307,9 @@ export const ButtonBoxPrimary = styled(ButtonBox)`
 export const ButtonSuccess = styled(ButtonVariant)`
   background-color: #388e3c;
 `
+export const LinkSuccess = styled(Link)`
+  color: #388e3c;
+`
 export const ButtonBoxSuccess = styled(ButtonBox)`
   color: #388e3c;
   border-color: #388e3c;
@@ -504,3 +559,144 @@ export const NiceSelect = styled.div`
     display: none;
   }
 `
+
+export const Outlined = styled.div`
+  border: 2px solid #388e3c;
+  padding: 0.5em 1em;
+  width: fit-content;
+  border-radius: 2px;
+  color: #388e3c;
+`
+
+/* { width: "1.5em", height: "1.5em", verticalAlign: "middle" } */
+export const CheckboxSuccess = styled.input`
+  vertical-align: center;
+
+`
+
+export const TermsSection = styled.a`
+  border: 1px solid black;
+  border-radius: 5px;
+  padding: 1em;
+  margin-top: 2px;
+  margin-bottom: 2px;
+  text-decoration: none;
+  color: inherit;
+  flex-direction: column;
+  
+  display: flex;
+  &[data-open="true"] {
+    display: flex; 
+  }
+  &[data-open="false"] > *:not(:first-child) {
+    display: none; 
+  }
+
+  header {
+    display: flex;
+    flex-direction: row;
+    font-weight: bold;
+    justify-content: space-between;
+    height: auto;
+  }
+
+  &[data-open="true"] header:after  {
+    content: '\\2227';
+  }
+  &[data-open="false"] header:after  {
+    content: '\\2228';
+  }
+`;
+
+export const TermsOfService = styled.div`
+  display: flex;
+  flex-direction: column;
+  text-align: left;
+
+  & > header {
+    text-align: center;
+    font-size: 2em;
+  }
+
+  a {
+    border: 1px solid black;
+    border-radius: 5px;
+    padding: 1em;
+    margin-top: 2px;
+    margin-bottom: 2px;
+    text-decoration: none;
+    color: inherit;
+    flex-direction: column;
+    
+    display: flex;
+    &[data-open="true"] {
+      display: flex; 
+    }
+    &[data-open="false"] > *:not(:first-child) {
+      display: none; 
+    }
+
+    header {
+      display: flex;
+      flex-direction: row;
+      font-weight: bold;
+      justify-content: space-between;
+      height: auto;
+    }
+
+    &[data-open="true"] header:after  {
+      content: '\\2227';
+    }
+    &[data-open="false"] header:after  {
+      content: '\\2228';
+    }
+  }
+
+`
+export const StyledCheckboxLabel = styled.div`
+  color: green;
+  text-transform: uppercase;
+  /* font-weight: bold; */
+  text-align: center;
+  span {
+
+    input {
+      display: none;
+      opacity: 0;
+      width: 1em;
+      height: 1em;
+    }
+    div {
+      display: inline-grid;
+      width: 1em;
+      height: 1em;
+      margin-right: 1em;
+      border-radius: 2px;
+      border: 2px solid currentColor;
+  
+      svg {
+        transition: transform 0.1s ease-in 25ms;
+        transform: scale(0);
+        transform-origin: bottom left;
+      }
+    }
+    label {
+      padding: 0px;
+      font-size: small;
+    }
+  }
+
+  input:checked + div svg {
+    transform: scale(1);
+  }
+  input:disabled + div {
+    color: #959495;
+  };
+  input:disabled + div + label {
+    color: #959495;
+  };
+  input:focus + div + label {
+    box-shadow: 0 0 0 0.05em #fff, 0 0 0.15em 0.1em currentColor;
+  }
+
+`
\ No newline at end of file
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx 
b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
index a89a18c1..022b9245 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
@@ -22,6 +22,7 @@
 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 { getMaxListeners } from 'process';
 import { createExample } from '../test-utils';
 import { View as TestedComponent } from './Withdraw';
 
@@ -33,20 +34,462 @@ export default {
   },
 };
 
-export const WithdrawWithFee = createExample(TestedComponent, {
+const termsXml = `<?xml version="1.0" encoding="utf-8"?>
+<document source="/home/grothoff/research/taler/exchange/contrib/tos/tos.rst">
+    <section ids="terms-of-service" names="terms\ of\ service">
+        <title>Terms Of Service</title>
+        <paragraph>Last Updated: 12.4.2019</paragraph>
+        <paragraph>Welcome! Taler Systems SA (“we,” “our,” or “us”) provides a 
payment service
+            through our Internet presence (collectively the “Services”). 
Before using our
+            Services, please read the Terms of Service (the “Terms” or the 
“Agreement”)
+            carefully.</paragraph>
+        <section ids="overview" names="overview">
+            <title>Overview</title>
+            <paragraph>This section provides a brief summary of the highlights 
of this
+                Agreement. Please note that when you accept this Agreement, 
you are accepting
+                all of the terms and conditions and not just this section. We 
and possibly
+                other third parties provide Internet services which interact 
with the Taler
+                Wallet’s self-hosted personal payment application. When using 
the Taler Wallet
+                to interact with our Services, you are agreeing to our Terms, 
so please read
+                carefully.</paragraph>
+            <section ids="highlights" names="highlights:">
+                <title>Highlights:</title>
+                <block_quote>
+                    <bullet_list bullet="•">
+                        <list_item>
+                            <paragraph>You are responsible for keeping the 
data in your Taler Wallet at all times
+                                under your control. Any losses arising from 
you not being in control of
+                                your private information are your 
problem.</paragraph>
+                        </list_item>
+                        <list_item>
+                            <paragraph>We will try to transfer funds we hold 
in escrow for our users to any legal
+                                recipient to the best of our ability within 
the limitations of the law and
+                                our implementation. However, the Services 
offered today are highly
+                                experimental and the set of recipients of 
funds is severely restricted.</paragraph>
+                        </list_item>
+                        <list_item>
+                            <paragraph>For our Services, we may charge 
transaction fees. The specific fee structure
+                                is provided based on the Taler protocol and 
should be shown to you when you
+                                withdraw electronic coins using a Taler 
Wallet. You agree and understand
+                                that the Taler protocol allows for the fee 
structure to change.</paragraph>
+                        </list_item>
+                        <list_item>
+                            <paragraph>You agree to not intentionally 
overwhelm our systems with requests and
+                                follow responsible disclosure if you find 
security issues in our services.</paragraph>
+                        </list_item>
+                        <list_item>
+                            <paragraph>We cannot be held accountable for our 
Services not being available due to
+                                circumstances beyond our control. If we modify 
or terminate our services,
+                                we will try to give you the opportunity to 
recover your funds. However,
+                                given the experimental state of the Services 
today, this may not be
+                                possible. You are strongly advised to limit 
your use of the Service
+                                to small-scale experiments expecting total 
loss of all funds.</paragraph>
+                        </list_item>
+                    </bullet_list>
+                </block_quote>
+                <paragraph>These terms outline approved uses of our Services. 
The Services and these
+                    Terms are still at an experimental stage. If you have any 
questions or
+                    comments related to this Agreement, please send us a 
message to
+                    <reference 
refuri="mailto:legal@taler-systems.com";>legal@taler-systems.com</reference>. If 
you do not agree to this Agreement, you must not
+                    use our Services.</paragraph>
+            </section>
+        </section>
+        <section ids="how-you-accept-this-policy" names="how\ you\ accept\ 
this\ policy">
+            <title>How you accept this policy</title>
+            <paragraph>By sending funds to us (to top-up your Taler Wallet), 
you acknowledge that you
+                have read, understood, and agreed to these Terms. We reserve 
the right to
+                change these Terms at any time. If you disagree with the 
change, we may in the
+                future offer you with an easy option to recover your unspent 
funds. However,
+                in the current experimental period you acknowledge that this 
feature is not
+                yet available, resulting in your funds being lost unless you 
accept the new
+                Terms. If you continue to use our Services other than to 
recover your unspent
+                funds, your continued use of our Services following any such 
change will
+                signify your acceptance to be bound by the then current Terms. 
Please check
+                the effective date above to determine if there have been any 
changes since you
+                have last reviewed these Terms.</paragraph>
+        </section>
+        <section ids="services" names="services">
+            <title>Services</title>
+            <paragraph>We will try to transfer funds that we hold in escrow 
for our users to any
+                legal recipient to the best of our ability and within the 
limitations of the
+                law and our implementation. However, the Services offered 
today are highly
+                experimental and the set of recipients of funds is severely 
restricted.  The
+                Taler Wallet can be loaded by exchanging fiat currencies 
against electronic
+                coins. We are providing this exchange service. Once your Taler 
Wallet is
+                loaded with electronic coins they can be spent for purchases 
if the seller is
+                accepting Taler as a means of payment. We are not guaranteeing 
that any seller
+                is accepting Taler at all or a particular seller.  The seller 
or recipient of
+                deposits of electronic coins must specify the target account, 
as per the
+                design of the Taler protocol. They are responsible for 
following the protocol
+                and specifying the correct bank account, and are solely liable 
for any losses
+                that may arise from specifying the wrong account. We will 
allow the government
+                to link wire transfers to the underlying contract hash. It is 
the
+                responsibility of recipients to preserve the full contracts 
and to pay
+                whatever taxes and charges may be applicable. Technical issues 
may lead to
+                situations where we are unable to make transfers at all or 
lead to incorrect
+                transfers that cannot be reversed. We will only refuse to 
execute transfers if
+                the transfers are prohibited by a competent legal authority 
and we are ordered
+                to do so.</paragraph>
+        </section>
+        <section ids="fees" names="fees">
+            <title>Fees</title>
+            <paragraph>You agree to pay the fees for exchanges and withdrawals 
completed via the
+                Taler Wallet (“Fees”) as defined by us, which we may change 
from time to
+                time. With the exception of wire transfer fees, Taler 
transaction fees are set
+                for any electronic coin at the time of withdrawal and fixed 
throughout the
+                validity period of the respective electronic coin. Your wallet 
should obtain
+                and display applicable fees when withdrawing funds. Fees for 
coins obtained as
+                change may differ from the fees applicable to the original 
coin. Wire transfer
+                fees that are independent from electronic coins may change 
annually.  You
+                authorize us to charge or deduct applicable fees owed in 
connection with
+                deposits, exchanges and withdrawals following the rules of the 
Taler protocol.
+                We reserve the right to provide different types of rewards to 
users either in
+                the form of discount for our Services or in any other form at 
our discretion
+                and without prior notice to you.</paragraph>
+        </section>
+        <section ids="eligibility" names="eligibility">
+            <title>Eligibility</title>
+            <paragraph>To be eligible to use our Services, you must be able to 
form legally binding
+                contracts or have the permission of your legal guardian. By 
using our
+                Services, you represent and warrant that you meet all 
eligibility requirements
+                that we outline in these Terms.</paragraph>
+        </section>
+        <section ids="financial-self-responsibility" names="financial\ 
self-responsibility">
+            <title>Financial self-responsibility</title>
+            <paragraph>You will be responsible for maintaining the 
availability, integrity and
+                confidentiality of the data stored in your wallet. When you 
setup a Taler
+                Wallet, you are strongly advised to follow the precautionary 
measures offered
+                by the software to minimize the chances to losse access to or 
control over
+                your Wallet data. We will not be liable for any loss or damage 
arising from
+                your failure to comply with this paragraph.</paragraph>
+        </section>
+        <section ids="copyrights-and-trademarks" names="copyrights\ and\ 
trademarks">
+            <title>Copyrights and trademarks</title>
+            <paragraph>The Taler Wallet is released under the terms of the GNU 
General Public License
+                (GNU GPL). You have the right to access, use, and share the 
Taler Wallet, in
+                modified or unmodified form. However, the GPL is a strong 
copyleft license,
+                which means that any derivative works must be distributed 
under the same
+                license terms as the original software. If you have any 
questions, you should
+                review the GNU GPL’s full terms and conditions at
+                <reference 
refuri="https://www.gnu.org/licenses/gpl-3.0.en.html";>https://www.gnu.org/licenses/gpl-3.0.en.html</reference>.
  “Taler” itself is a trademark
+                of Taler Systems SA. You are welcome to use the name in 
relation to processing
+                payments using the Taler protocol, assuming your use is 
compatible with an
+                official release from the GNU Project that is not older than 
two years.</paragraph>
+        </section>
+        <section ids="your-use-of-our-services" names="your\ use\ of\ our\ 
services">
+            <title>Your use of our services</title>
+            <paragraph>When using our Services, you agree to not take any 
action that intentionally
+                imposes an unreasonable load on our infrastructure. If you 
find security
+                problems in our Services, you agree to first report them to
+                <reference 
refuri="mailto:security@taler-systems.com";>security@taler-systems.com</reference>
 and grant us the right to publish your report. We
+                warrant that we will ourselves publicly disclose any issues 
reported within 3
+                months, and that we will not prosecute anyone reporting 
security issues if
+                they did not exploit the issue beyond a proof-of-concept, and 
followed the
+                above responsible disclosure practice.</paragraph>
+        </section>
+        <section ids="limitation-of-liability-disclaimer-of-warranties" 
names="limitation\ of\ liability\ &amp;\ disclaimer\ of\ warranties">
+            <title>Limitation of liability &amp; disclaimer of 
warranties</title>
+            <paragraph>You understand and agree that we have no control over, 
and no duty to take any
+                action regarding: Failures, disruptions, errors, or delays in 
processing that
+                you may experience while using our Services; The risk of 
failure of hardware,
+                software, and Internet connections; The risk of malicious 
software being
+                introduced or found in the software underlying the Taler 
Wallet; The risk that
+                third parties may obtain unauthorized access to information 
stored within your
+                Taler Wallet, including, but not limited to your Taler Wallet 
coins or backup
+                encryption keys.  You release us from all liability related to 
any losses,
+                damages, or claims arising from:</paragraph>
+            <enumerated_list enumtype="loweralpha" prefix="(" suffix=")">
+                <list_item>
+                    <paragraph>user error such as forgotten passwords, 
incorrectly constructed
+                        transactions;</paragraph>
+                </list_item>
+                <list_item>
+                    <paragraph>server failure or data loss;</paragraph>
+                </list_item>
+                <list_item>
+                    <paragraph>unauthorized access to the Taler Wallet 
application;</paragraph>
+                </list_item>
+                <list_item>
+                    <paragraph>bugs or other errors in the Taler Wallet 
software; and</paragraph>
+                </list_item>
+                <list_item>
+                    <paragraph>any unauthorized third party activities, 
including, but not limited to,
+                        the use of viruses, phishing, brute forcing, or other 
means of attack
+                        against the Taler Wallet. We make no representations 
concerning any
+                        Third Party Content contained in or accessed through 
our Services.</paragraph>
+                </list_item>
+            </enumerated_list>
+            <paragraph>Any other terms, conditions, warranties, or 
representations associated with
+                such content, are solely between you and such organizations 
and/or
+                individuals.</paragraph>
+        </section>
+        <section ids="limitation-of-liability" names="limitation\ of\ 
liability">
+            <title>Limitation of liability</title>
+            <paragraph>To the fullest extent permitted by applicable law, in 
no event will we or any
+                of our officers, directors, representatives, agents, servants, 
counsel,
+                employees, consultants, lawyers, and other personnel 
authorized to act,
+                acting, or purporting to act on our behalf (collectively the 
“Taler Parties”)
+                be liable to you under contract, tort, strict liability, 
negligence, or any
+                other legal or equitable theory, for:</paragraph>
+            <enumerated_list enumtype="loweralpha" prefix="(" suffix=")">
+                <list_item>
+                    <paragraph>any lost profits, data loss, cost of 
procurement of substitute goods or
+* TLSv1.3 (IN), TLS Unknown, Unknown (23):
+                        services, or direct, indirect, incidental, special, 
punitive, compensatory,
+                        or consequential damages of any kind whatsoever 
resulting from:</paragraph>
+                </list_item>
+            </enumerated_list>
+            <block_quote>
+                <enumerated_list enumtype="lowerroman" prefix="(" suffix=")">
+                    <list_item>
+                        <paragraph>your use of, or conduct in connection with, 
our services;</paragraph>
+                    </list_item>
+                    <list_item>
+                        <paragraph>any unauthorized use of your wallet and/or 
private key due to your
+                            failure to maintain the confidentiality of your 
wallet;</paragraph>
+                    </list_item>
+                    <list_item>
+                        <paragraph>any interruption or cessation of 
transmission to or from the services; or</paragraph>
+                    </list_item>
+                    <list_item>
+                        <paragraph>any bugs, viruses, trojan horses, or the 
like that are found in the Taler
+                            Wallet software or that may be transmitted to or 
through our services by
+                            any third party (regardless of the source of 
origination), or</paragraph>
+                    </list_item>
+                </enumerated_list>
+            </block_quote>
+            <enumerated_list enumtype="loweralpha" prefix="(" start="2" 
suffix=")">
+                <list_item>
+                    <paragraph>any direct damages.</paragraph>
+                </list_item>
+            </enumerated_list>
+            <paragraph>These limitations apply regardless of legal theory, 
whether based on tort,
+                strict liability, breach of contract, breach of warranty, or 
any other legal
+                theory, and whether or not we were advised of the possibility 
of such
+                damages. Some jurisdictions do not allow the exclusion or 
limitation of
+                liability for consequential or incidental damages, so the 
above limitation may
+                not apply to you.</paragraph>
+        </section>
+        <section ids="warranty-disclaimer" names="warranty\ disclaimer">
+            <title>Warranty disclaimer</title>
+            <paragraph>Our services are provided “as is” and without warranty 
of any kind. To the
+                maximum extent permitted by law, we disclaim all 
representations and
+                warranties, express or implied, relating to the services and 
underlying
+                software or any content on the services, whether provided or 
owned by us or by
+                any third party, including without limitation, warranties of 
merchantability,
+                fitness for a particular purpose, title, non-infringement, 
freedom from
+                computer virus, and any implied warranties arising from course 
of dealing,
+                course of performance, or usage in trade, all of which are 
expressly
+                disclaimed. In addition, we do not represent or warrant that 
the content
+                accessible via the services is accurate, complete, available, 
current, free of
+                viruses or other harmful components, or that the results of 
using the services
+                will meet your requirements. Some states do not allow the 
disclaimer of
+                implied warranties, so the foregoing disclaimers may not apply 
to you. This
+                paragraph gives you specific legal rights and you may also 
have other legal
+                rights that vary from state to state.</paragraph>
+        </section>
+        <section ids="indemnity" names="indemnity">
+            <title>Indemnity</title>
+            <paragraph>To the extent permitted by applicable law, you agree to 
defend, indemnify, and
+                hold harmless the Taler Parties from and against any and all 
claims, damages,
+                obligations, losses, liabilities, costs or debt, and expenses 
(including, but
+                not limited to, attorney’s fees) arising from: (a) your use of 
and access to
+                the Services; (b) any feedback or submissions you provide to 
us concerning the
+                Taler Wallet; (c) your violation of any term of this 
Agreement; or (d) your
+                violation of any law, rule, or regulation, or the rights of 
any third party.</paragraph>
+        </section>
+        <section ids="time-limitation-on-claims" names="time\ limitation\ on\ 
claims">
+            <title>Time limitation on claims</title>
+            <paragraph>You agree that any claim you may have arising out of or 
related to your
+                relationship with us must be filed within one year after such 
claim arises,
+                otherwise, your claim in permanently barred.</paragraph>
+        </section>
+        <section ids="governing-law" names="governing\ law">
+            <title>Governing law</title>
+            <paragraph>No matter where you’re located, the laws of Switzerland 
will govern these
+                Terms. If any provisions of these Terms are inconsistent with 
any applicable
+                law, those provisions will be superseded or modified only to 
the extent such
+                provisions are inconsistent. The parties agree to submit to 
the ordinary
+                courts in Zurich, Switzerland for exclusive jurisdiction of 
any dispute
+                arising out of or related to your use of the Services or your 
breach of these
+                Terms.</paragraph>
+        </section>
+        <section ids="termination" names="termination">
+            <title>Termination</title>
+            <paragraph>In the event of termination concerning your use of our 
Services, your
+                obligations under this Agreement will still 
continue.</paragraph>
+        </section>
+        <section ids="discontinuance-of-services" names="discontinuance\ of\ 
services">
+            <title>Discontinuance of services</title>
+            <paragraph>We may, in our sole discretion and without cost to you, 
with or without prior
+                notice, and at any time, modify or discontinue, temporarily or 
permanently,
+                any portion of our Services. We will use the Taler protocol’s 
provisions to
+                notify Wallets if our Services are to be discontinued. It is 
your
+                responsibility to ensure that the Taler Wallet is online at 
least once every
+                three months to observe these notifications. We shall not be 
held responsible
+                or liable for any loss of funds in the event that we 
discontinue or depreciate
+                the Services and your Taler Wallet fails to transfer out the 
coins within a
+                three months notification period.</paragraph>
+        </section>
+        <section ids="no-waiver" names="no\ waiver">
+            <title>No waiver</title>
+            <paragraph>Our failure to exercise or delay in exercising any 
right, power, or privilege
+                under this Agreement shall not operate as a waiver; nor shall 
any single or
+                partial exercise of any right, power, or privilege preclude 
any other or
+                further exercise thereof.</paragraph>
+        </section>
+        <section ids="severability" names="severability">
+            <title>Severability</title>
+            <paragraph>If it turns out that any part of this Agreement is 
invalid, void, or for any
+                reason unenforceable, that term will be deemed severable and 
limited or
+                eliminated to the minimum extent necessary.</paragraph>
+        </section>
+        <section ids="force-majeure" names="force\ majeure">
+            <title>Force majeure</title>
+            <paragraph>We shall not be held liable for any delays, failure in 
performance, or
+                interruptions of service which result directly or indirectly 
from any cause or
+                condition beyond our reasonable control, including but not 
limited to: any
+                delay or failure due to any act of God, act of civil or 
military authorities,
+                act of terrorism, civil disturbance, war, strike or other 
labor dispute, fire,
+                interruption in telecommunications or Internet services or 
network provider
+                services, failure of equipment and/or software, other 
catastrophe, or any
+                other occurrence which is beyond our reasonable control and 
shall not affect
+                the validity and enforceability of any remaining 
provisions.</paragraph>
+        </section>
+        <section ids="assignment" names="assignment">
+            <title>Assignment</title>
+            <paragraph>You agree that we may assign any of our rights and/or 
transfer, sub-contract,
+                or delegate any of our obligations under these 
Terms.</paragraph>
+        </section>
+        <section ids="entire-agreement" names="entire\ agreement">
+            <title>Entire agreement</title>
+            <paragraph>This Agreement sets forth the entire understanding and 
agreement as to the
+                subject matter hereof and supersedes any and all prior 
discussions,
+                agreements, and understandings of any kind (including, without 
limitation, any
+                prior versions of this Agreement) and every nature between us. 
Except as
+                provided for above, any modification to this Agreement must be 
in writing and
+                must be signed by both parties.</paragraph>
+        </section>
+        <section ids="questions-or-comments" names="questions\ or\ comments">
+            <title>Questions or comments</title>
+            <paragraph>We welcome comments, questions, concerns, or 
suggestions. Please send us a
+                message on our contact page at <reference 
refuri="mailto:legal@taler-systems.com";>legal@taler-systems.com</reference>.</paragraph>
+        </section>
+    </section>
+</document>
+
+`;
+
+export const WithdrawNewTermsXML = createExample(TestedComponent, {
+  details: {
+    exchangeInfo: {
+      baseUrl: 'exchange.demo.taler.net'
+    } as ExchangeRecord,
+    withdrawFee: {
+      currency: 'USD',
+      fraction: 0,
+      value: 0
+    },
+  } as ExchangeWithdrawDetails,
+  amount: 'USD:2',
+  terms: {
+    value : {
+      type: 'xml',
+      document: new DOMParser().parseFromString(termsXml, "text/xml"),
+    },
+    status: 'new'
+  },
+})
+
+export const WithdrawNewTermsReviewingXML = createExample(TestedComponent, {
+  details: {
+    exchangeInfo: {
+      baseUrl: 'exchange.demo.taler.net'
+    } as ExchangeRecord,
+    withdrawFee: {
+      currency: 'USD',
+      fraction: 0,
+      value: 0
+    },
+  } as ExchangeWithdrawDetails,
+  amount: 'USD:2',
+  terms: {
+    value : {
+      type: 'xml',
+      document: new DOMParser().parseFromString(termsXml, "text/xml"),
+    },
+    status: 'new'
+  },
+  reviewing: true
+})
+
+export const WithdrawNewTermsAcceptedXML = createExample(TestedComponent, {
+  details: {
+    exchangeInfo: {
+      baseUrl: 'exchange.demo.taler.net'
+    } as ExchangeRecord,
+    withdrawFee: {
+      currency: 'USD',
+      fraction: 0,
+      value: 0
+    },
+  } as ExchangeWithdrawDetails,
+  amount: 'USD:2',
+  terms: {
+    value : {
+      type: 'xml',
+      document: new DOMParser().parseFromString(termsXml, "text/xml"),
+    },
+    status: 'new'
+  },
+  accepted: true
+})
+
+export const WithdrawNewTermsShowAfterAcceptedXML = 
createExample(TestedComponent, {
   details: {
     exchangeInfo: {
       baseUrl: 'exchange.demo.taler.net'
     } as ExchangeRecord,
     withdrawFee: {
       currency: 'USD',
-      fraction: amountFractionalBase*0.5,
+      fraction: 0,
+      value: 0
+    },
+  } as ExchangeWithdrawDetails,
+  amount: 'USD:2',
+  terms: {
+    value : {
+      type: 'xml',
+      document: new DOMParser().parseFromString(termsXml, "text/xml"),
+    },
+    status: 'new'
+  },
+  accepted: true,
+  reviewing: true,
+})
+
+export const WithdrawChangedTermsXML = createExample(TestedComponent, {
+  details: {
+    exchangeInfo: {
+      baseUrl: 'exchange.demo.taler.net'
+    } as ExchangeRecord,
+    withdrawFee: {
+      currency: 'USD',
+      fraction: 0,
       value: 0
     },
   } as ExchangeWithdrawDetails,
   amount: 'USD:2',
+  terms: {
+    value : {
+      type: 'xml',
+      document: new DOMParser().parseFromString(termsXml, "text/xml"),
+    },
+    status: 'changed'
+  },
 })
-export const WithdrawWithoutFee = createExample(TestedComponent, {
+
+export const WithdrawNotFoundTermsXML = createExample(TestedComponent, {
   details: {
     exchangeInfo: {
       baseUrl: 'exchange.demo.taler.net'
@@ -58,4 +501,46 @@ export const WithdrawWithoutFee = 
createExample(TestedComponent, {
     },
   } as ExchangeWithdrawDetails,
   amount: 'USD:2',
+  terms: {
+    status: 'notfound'
+  },
 })
+
+export const WithdrawAcceptedTermsXML = createExample(TestedComponent, {
+  details: {
+    exchangeInfo: {
+      baseUrl: 'exchange.demo.taler.net'
+    } as ExchangeRecord,
+    withdrawFee: {
+      currency: 'USD',
+      fraction: amountFractionalBase * 0.5,
+      value: 0
+    },
+  } as ExchangeWithdrawDetails,
+  amount: 'USD:2',
+  terms: {
+    status: 'accepted'
+  },
+})
+
+
+export const WithdrawAcceptedTermsWithoutFee = createExample(TestedComponent, {
+  details: {
+    exchangeInfo: {
+      baseUrl: 'exchange.demo.taler.net'
+    } as ExchangeRecord,
+    withdrawFee: {
+      currency: 'USD',
+      fraction: 0,
+      value: 0
+    },
+  } as ExchangeWithdrawDetails,
+  amount: 'USD:2',
+  terms: {
+    value : {
+      type: 'xml',
+      document: new DOMParser().parseFromString(termsXml, "text/xml"),
+    },
+    status: 'accepted',
+  }
+})
\ No newline at end of file
diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx 
b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
index 9719b8f5..6263285f 100644
--- a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
@@ -24,10 +24,11 @@
 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 { CheckboxOutlined } from '../components/CheckboxOutlined';
+import { ExchangeXmlTos } from '../components/ExchangeToS';
 import { LogoHeader } from '../components/LogoHeader';
 import { Part } from '../components/Part';
-import { ButtonSuccess, WalletAction } from '../components/styled';
+import { ButtonDestructive, ButtonSuccess, ButtonWarning, LinkSuccess, 
TermsOfService, WalletAction } from '../components/styled';
 import {
   acceptWithdrawal, getExchangeWithdrawalInfo, getWithdrawalDetailsForUri, 
onUpdateNotification
 } from "../wxApi";
@@ -40,19 +41,42 @@ interface Props {
 export interface ViewProps {
   details: ExchangeWithdrawDetails;
   amount: string;
-  accept: () => Promise<void>;
-  setCancelled: (b: boolean) => void;
-  setSelecting: (b: boolean) => void;
+  onWithdraw: () => Promise<void>;
+  // setCancelled: (b: boolean) => void;
+  // setSelecting: (b: boolean) => void;
+  onReview: (b: boolean) => void;
+  onAccept: (b: boolean) => void;
+  reviewing: boolean;
+  accepted: boolean;
+  terms: {
+    value?: TermsDocument;
+    status: TermsStatus;
+  }
+
 };
 
+type TermsStatus = 'new' | 'accepted' | 'changed' | 'notfound';
+
+type TermsDocument = TermsDocumentXml | TermsDocumentHtml;
+
+interface TermsDocumentXml {
+  type: 'xml',
+  document: Document,
+}
+
+interface TermsDocumentHtml {
+  type: 'html',
+  href: string,
+}
+
 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) {
+export function View({ details, amount, onWithdraw, terms, reviewing, 
onReview, onAccept, accepted }: ViewProps) {
+  const needsReview = terms.status === 'changed' || terms.status === 'new'
 
   return (
     <WalletAction style={{ textAlign: 'center' }}>
@@ -70,17 +94,101 @@ export function View({ details, amount, accept, 
setCancelled, setSelecting }: Vi
           <Part title="Exchange" text={details.exchangeInfo.baseUrl} 
kind='neutral' big />
         </div>
       </section>
-      <section>
-
-        <div>
-          <ButtonSuccess
+      {!reviewing &&
+        <section>
+          <LinkSuccess
             upperCased
-            disabled={!details.exchangeInfo.baseUrl}
-            onClick={accept}
           >
-            {i18n.str`Accept fees and withdraw`}
-          </ButtonSuccess>
-        </div>
+            {i18n.str`Edit exchange`}
+          </LinkSuccess>
+        </section>
+      }
+      {!reviewing && accepted &&
+        <section>
+          <LinkSuccess
+            upperCased
+            onClick={() => onReview(true)}
+          >
+            {i18n.str`Show terms of service`}
+          </LinkSuccess>
+        </section>
+      }
+      {reviewing &&
+        <section>
+          <TermsOfService>
+            {terms.status !== 'accepted' && terms.value && terms.value.type 
=== 'xml' && <ExchangeXmlTos doc={terms.value.document} />}
+          </TermsOfService>
+        </section>}
+      {reviewing && accepted &&
+        <section>
+          <LinkSuccess
+            upperCased
+            onClick={() => onReview(false)}
+          >
+            {i18n.str`Hide terms of service`}
+          </LinkSuccess>
+        </section>
+      }
+      {(reviewing || accepted) &&
+        <section>
+          <div>
+            <CheckboxOutlined
+              name="terms"
+              enabled={accepted}
+              label={i18n.str`I accept the exchange terms of service`}
+              onToggle={() => {
+                onAccept(!accepted)
+                onReview(false)
+              }}
+            />
+          </div>
+        </section>
+      }
+
+      <section>
+        {terms.status === 'new' && !accepted &&
+          <div>
+            <ButtonSuccess
+              upperCased
+              disabled={!details.exchangeInfo.baseUrl}
+              onClick={() => onReview(true)}
+            >
+              {i18n.str`Review exchange terms of service`}
+            </ButtonSuccess>
+          </div>
+        }
+        {terms.status === 'changed' && !accepted &&
+          <div>
+            <ButtonWarning
+              upperCased
+              disabled={!details.exchangeInfo.baseUrl}
+              onClick={() => onReview(true)}
+            >
+              {i18n.str`Review new version of terms of service`}
+            </ButtonWarning>
+          </div>
+        }
+        {(terms.status === 'accepted' || (needsReview && accepted)) &&
+          <div>
+            <ButtonSuccess
+              upperCased
+              disabled={!details.exchangeInfo.baseUrl}
+              onClick={onWithdraw}
+            >
+              {i18n.str`Confirm withdrawal`}
+            </ButtonSuccess>
+          </div>
+        }
+        {terms.status === 'notfound' &&
+          <div>
+            <ButtonDestructive
+              upperCased
+              disabled={true}
+            >
+              {i18n.str`Exchange doesn't have terms of service`}
+            </ButtonDestructive>
+          </div>
+        }
       </section>
     </WalletAction>
   )
@@ -93,6 +201,8 @@ export function WithdrawPage({ talerWithdrawUri, ...rest }: 
Props): JSX.Element
   const [selecting, setSelecting] = useState(false);
   const [error, setError] = useState<boolean>(false);
   const [updateCounter, setUpdateCounter] = useState(1);
+  const [reviewing, setReviewing] = useState<boolean>(false)
+  const [accepted, setAccepted] = useState<boolean>(false)
 
   useEffect(() => {
     return onUpdateNotification(() => {
@@ -132,7 +242,7 @@ export function WithdrawPage({ talerWithdrawUri, ...rest }: 
Props): JSX.Element
     return <span><i18n.Translate>missing withdraw uri</i18n.Translate></span>;
   }
 
-  const accept = async (): Promise<void> => {
+  const onWithdraw = async (): Promise<void> => {
     if (!details) {
       throw Error("can't accept, no exchange selected");
     }
@@ -157,9 +267,13 @@ export function WithdrawPage({ talerWithdrawUri, ...rest 
}: Props): JSX.Element
     return <span><i18n.Translate>Getting withdrawal 
details.</i18n.Translate></span>;
   }
 
-  return <View accept={accept}
-    setCancelled={setCancelled} setSelecting={setSelecting}
+  return <View onWithdraw={onWithdraw}
+    // setCancelled={setCancelled} setSelecting={setSelecting}
     details={details} amount={uriInfo.amount}
+    terms={{} as any}
+    accepted={accepted} onAccept={setAccepted}
+    reviewing={reviewing} onReview={setReviewing}
+  // terms={[]}
   />
 }
 

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