withdraw design
This commit is contained in:
parent
217f34397f
commit
c24db59be8
@ -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>
|
||||
);
|
||||
}
|
@ -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} />
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
`
|
@ -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,353 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
export const WithdrawWithFee = 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',
|
||||
})
|
||||
export const WithdrawWithoutFee = 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\ &\ disclaimer\ of\ warranties">
|
||||
<title>Limitation of liability & 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'
|
||||
@ -58,4 +392,155 @@ export const WithdrawWithoutFee = createExample(TestedComponent, {
|
||||
},
|
||||
} 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: 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 WithdrawNotFoundTermsXML = createExample(TestedComponent, {
|
||||
details: {
|
||||
exchangeInfo: {
|
||||
baseUrl: 'exchange.demo.taler.net'
|
||||
} as ExchangeRecord,
|
||||
withdrawFee: {
|
||||
currency: 'USD',
|
||||
fraction: 0,
|
||||
value: 0
|
||||
},
|
||||
} 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',
|
||||
}
|
||||
})
|
@ -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>
|
||||
{!reviewing &&
|
||||
<section>
|
||||
<LinkSuccess
|
||||
upperCased
|
||||
>
|
||||
{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={accept}
|
||||
onClick={() => onReview(true)}
|
||||
>
|
||||
{i18n.str`Accept fees and withdraw`}
|
||||
{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={[]}
|
||||
/>
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user