add exchange feature

This commit is contained in:
Sebastian 2021-11-22 17:34:27 -03:00
parent a35604fd56
commit 829a59e1a2
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
23 changed files with 1700 additions and 1124 deletions

View File

@ -42,6 +42,7 @@ export enum Pages {
transaction = "/transaction/:tid",
provider_detail = "/provider/:pid",
provider_add = "/provider/add",
exchange_add = "/exchange/add",
reset_required = "/reset-required",
payback = "/payback",

View File

@ -48,8 +48,8 @@ export function CheckboxOutlined({
label,
}: Props): VNode {
return (
<Outlined>
<StyledCheckboxLabel onClick={onToggle}>
<StyledCheckboxLabel onClick={onToggle}>
<Outlined>
<span>
<input
type="checkbox"
@ -62,7 +62,7 @@ export function CheckboxOutlined({
</div>
<label for={name}>{label}</label>
</span>
</StyledCheckboxLabel>
</Outlined>
</Outlined>
</StyledCheckboxLabel>
);
}

View File

@ -476,6 +476,14 @@ const ButtonVariant = styled(Button)`
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
`;
export const LinkDestructive = styled(Link)`
background-color: rgb(202, 60, 60);
`;
export const LinkPrimary = styled(Link)`
color: rgb(66, 184, 221);
`;
export const ButtonPrimary = styled(ButtonVariant)<{ small?: boolean }>`
font-size: ${({ small }) => (small ? "small" : "inherit")};
background-color: rgb(66, 184, 221);
@ -892,12 +900,14 @@ export const StyledCheckboxLabel = styled.div`
text-transform: uppercase;
/* font-weight: bold; */
text-align: center;
cursor: pointer;
span {
input {
display: none;
opacity: 0;
width: 1em;
height: 1em;
cursor: pointer;
}
div {
display: inline-grid;
@ -916,6 +926,7 @@ export const StyledCheckboxLabel = styled.div`
label {
padding: 0px;
font-size: small;
cursor: pointer;
}
}

View File

@ -0,0 +1,129 @@
import { i18n } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { CheckboxOutlined } from "../components/CheckboxOutlined";
import { ExchangeXmlTos } from "../components/ExchangeToS";
import {
ButtonSuccess,
ButtonWarning,
LinkSuccess,
TermsOfService,
WarningBox,
} from "../components/styled";
import { TermsState } from "../utils";
interface Props {
reviewing: boolean;
reviewed: boolean;
terms: TermsState;
onReview?: (b: boolean) => void;
onAccept: (b: boolean) => void;
}
export function TermsOfServiceSection({
reviewed,
reviewing,
terms,
onAccept,
onReview,
}: Props): VNode {
if (!reviewing) {
if (!reviewed) {
if (!onReview) {
return <section>Terms of service status: {terms.status}</section>;
}
return (
<Fragment>
{terms.status === "new" && (
<section>
<ButtonSuccess upperCased onClick={() => onReview(true)}>
{i18n.str`Review exchange terms of service`}
</ButtonSuccess>
</section>
)}
{terms.status === "changed" && (
<section>
<ButtonWarning upperCased onClick={() => onReview(true)}>
{i18n.str`Review new version of terms of service`}
</ButtonWarning>
</section>
)}
</Fragment>
);
}
return (
<Fragment>
{onReview && (
<section>
<LinkSuccess upperCased onClick={() => onReview(true)}>
{i18n.str`Show terms of service`}
</LinkSuccess>
</section>
)}
<section>
<CheckboxOutlined
name="terms"
enabled={reviewed}
label={i18n.str`I accept the exchange terms of service`}
onToggle={() => {
console.log("asdasd", reviewed);
onAccept(!reviewed);
if (onReview) onReview(false);
}}
/>
</section>
</Fragment>
);
}
return (
<Fragment>
{terms.status !== "notfound" && !terms.content && (
<section>
<WarningBox>
The exchange reply with a empty terms of service
</WarningBox>
</section>
)}
{terms.status !== "accepted" && terms.content && (
<section>
{terms.content.type === "xml" && (
<TermsOfService>
<ExchangeXmlTos doc={terms.content.document} />
</TermsOfService>
)}
{terms.content.type === "plain" && (
<div style={{ textAlign: "left" }}>
<pre>{terms.content.content}</pre>
</div>
)}
{terms.content.type === "html" && (
<iframe src={terms.content.href.toString()} />
)}
{terms.content.type === "pdf" && (
<a href={terms.content.location.toString()} download="tos.pdf">
Download Terms of Service
</a>
)}
</section>
)}
{reviewed && onReview && (
<section>
<LinkSuccess upperCased onClick={() => onReview(false)}>
{i18n.str`Hide terms of service`}
</LinkSuccess>
</section>
)}
{terms.status !== "notfound" && (
<section>
<CheckboxOutlined
name="terms"
enabled={reviewed}
label={i18n.str`I accept the exchange terms of service`}
onToggle={() => {
onAccept(!reviewed);
if (onReview) onReview(false);
}}
/>
</section>
)}
</Fragment>
);
}

View File

@ -21,6 +21,7 @@
import { amountFractionalBase } from "@gnu-taler/taler-util";
import { createExample } from "../test-utils";
import { termsHtml, termsPdf, termsPlain, termsXml } from "./termsExample";
import { View as TestedComponent } from "./Withdraw";
export default {
@ -31,751 +32,6 @@ export default {
},
};
const termsHtml = `<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Terms Of Service &#8212; Taler Terms of Service</title>
</head><body>
<div>
Terms of service
</div>
<div>
A complete separated html with it's own design
</div>
</body>
</html>
`;
const termsPlain = `
Terms Of Service
****************
Last Updated: 12.4.2019
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.
Overview
========
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 Wallets 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.
Highlights:
-----------
* 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.
* 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.
* 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.
* You agree to not intentionally overwhelm our systems with
requests and follow responsible disclosure if you find security
issues in our services.
* 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.
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 legal@taler-systems.com. If you do not agree to this
Agreement, you must not use our Services.
How you accept this policy
==========================
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.
Services
========
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.
Fees
====
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.
Eligibility
===========
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.
Financial self-responsibility
=============================
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.
Copyrights and trademarks
=========================
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 GPLs full terms and
conditions at https://www.gnu.org/licenses/gpl-3.0.en.html. “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.
Your use of our services
========================
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 security@taler-systems.com 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.
Limitation of liability & disclaimer of warranties
==================================================
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:
1. user error such as forgotten passwords, incorrectly constructed
transactions;
2. server failure or data loss;
3. unauthorized access to the Taler Wallet application;
4. bugs or other errors in the Taler Wallet software; and
5. 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.
Any other terms, conditions, warranties, or representations associated
with such content, are solely between you and such organizations
and/or individuals.
Limitation of liability
=======================
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:
1. any lost profits, data loss, cost of procurement of substitute
goods or services, or direct, indirect, incidental, special,
punitive, compensatory, or consequential damages of any kind
whatsoever resulting from:
1. your use of, or conduct in connection with, our services;
2. any unauthorized use of your wallet and/or private key due to
your failure to maintain the confidentiality of your wallet;
3. any interruption or cessation of transmission to or from the
services; or
4. 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
2. any direct damages.
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.
Warranty disclaimer
===================
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.
Indemnity
=========
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, attorneys 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.
Time limitation on claims
=========================
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.
Governing law
=============
No matter where youre 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.
Termination
===========
In the event of termination concerning your use of our Services, your
obligations under this Agreement will still continue.
Discontinuance of services
==========================
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 protocols 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.
No waiver
=========
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.
Severability
============
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.
Force majeure
=============
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.
Assignment
==========
You agree that we may assign any of our rights and/or transfer, sub-
contract, or delegate any of our obligations under these Terms.
Entire agreement
================
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.
Questions or comments
=====================
We welcome comments, questions, concerns, or suggestions. Please send
us a message on our contact page at legal@taler-systems.com.
`;
const termsXml = `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE document PUBLIC "+//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML" "http://docutils.sourceforge.net/docs/ref/docutils.dtd">
<!-- Generated by Docutils 0.14 -->
<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
Wallets 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 GPLs 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
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, attorneys 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 youre 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 protocols 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 NewTerms = createExample(TestedComponent, {
knownExchanges: [
{
@ -805,11 +61,12 @@ export const NewTerms = createExample(TestedComponent, {
null;
},
terms: {
value: {
content: {
type: "xml",
document: new DOMParser().parseFromString(termsXml, "text/xml"),
},
status: "new",
version: "",
},
});
@ -842,11 +99,12 @@ export const TermsReviewingPLAIN = createExample(TestedComponent, {
null;
},
terms: {
value: {
content: {
type: "plain",
content: termsPlain,
},
status: "new",
version: "",
},
reviewing: true,
});
@ -880,32 +138,18 @@ export const TermsReviewingHTML = createExample(TestedComponent, {
null;
},
terms: {
value: {
content: {
type: "html",
href: new URL(
`data:text/html;base64,${Buffer.from(termsHtml).toString("base64")}`,
),
},
version: "",
status: "new",
},
reviewing: true,
});
const termsPdf = `
%PDF-1.2
9 0 obj << >>
stream
BT/ 9 Tf(This is the Exchange TERMS OF SERVICE)' ET
endstream
endobj
4 0 obj << /Type /Page /Parent 5 0 R /Contents 9 0 R >> endobj
5 0 obj << /Kids [4 0 R ] /Count 1 /Type /Pages /MediaBox [ 0 0 180 20 ] >> endobj
3 0 obj << /Pages 5 0 R /Type /Catalog >> endobj
trailer
<< /Root 3 0 R >>
%%EOF
`;
export const TermsReviewingPDF = createExample(TestedComponent, {
knownExchanges: [
{
@ -935,13 +179,14 @@ export const TermsReviewingPDF = createExample(TestedComponent, {
null;
},
terms: {
value: {
content: {
type: "pdf",
location: new URL(
`data:text/html;base64,${Buffer.from(termsPdf).toString("base64")}`,
),
},
status: "new",
version: "",
},
reviewing: true,
});
@ -975,11 +220,12 @@ export const TermsReviewingXML = createExample(TestedComponent, {
null;
},
terms: {
value: {
content: {
type: "xml",
document: new DOMParser().parseFromString(termsXml, "text/xml"),
},
status: "new",
version: "",
},
reviewing: true,
});
@ -1012,11 +258,12 @@ export const NewTermsAccepted = createExample(TestedComponent, {
null;
},
terms: {
value: {
content: {
type: "xml",
document: new DOMParser().parseFromString(termsXml, "text/xml"),
},
status: "new",
version: "",
},
reviewed: true,
});
@ -1050,10 +297,11 @@ export const TermsShowAgainXML = createExample(TestedComponent, {
null;
},
terms: {
value: {
content: {
type: "xml",
document: new DOMParser().parseFromString(termsXml, "text/xml"),
},
version: "",
status: "new",
},
reviewed: true,
@ -1089,10 +337,11 @@ export const TermsChanged = createExample(TestedComponent, {
null;
},
terms: {
value: {
content: {
type: "xml",
document: new DOMParser().parseFromString(termsXml, "text/xml"),
},
version: "",
status: "changed",
},
});
@ -1126,7 +375,9 @@ export const TermsNotFound = createExample(TestedComponent, {
null;
},
terms: {
content: undefined,
status: "notfound",
version: "",
},
});
@ -1160,6 +411,8 @@ export const TermsAlreadyAccepted = createExample(TestedComponent, {
},
terms: {
status: "accepted",
content: undefined,
version: "",
},
});
@ -1192,10 +445,11 @@ export const WithoutFee = createExample(TestedComponent, {
null;
},
terms: {
value: {
content: {
type: "xml",
document: new DOMParser().parseFromString(termsXml, "text/xml"),
},
status: "accepted",
version: "",
},
});

View File

@ -25,14 +25,11 @@ import {
AmountJson,
Amounts,
ExchangeListItem,
GetExchangeTosResult,
i18n,
WithdrawUriInfoResponse,
} from "@gnu-taler/taler-util";
import { VNode, h, Fragment } from "preact";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { CheckboxOutlined } from "../components/CheckboxOutlined";
import { ExchangeXmlTos } from "../components/ExchangeToS";
import { LogoHeader } from "../components/LogoHeader";
import { Part } from "../components/Part";
import { SelectList } from "../components/SelectList";
@ -40,19 +37,13 @@ import {
ButtonSuccess,
ButtonWarning,
LinkSuccess,
TermsOfService,
WalletAction,
WarningText,
} from "../components/styled";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
import {
acceptWithdrawal,
getExchangeTos,
getExchangeWithdrawalInfo,
getWithdrawalDetailsForUri,
listExchanges,
setExchangeTosAccepted,
} from "../wxApi";
import { amountToString, buildTermsOfServiceState, TermsState } from "../utils";
import * as wxApi from "../wxApi";
import { TermsOfServiceSection } from "./TermsOfServiceSection";
interface Props {
talerWithdrawUri?: string;
@ -60,7 +51,7 @@ interface Props {
export interface ViewProps {
withdrawalFee: AmountJson;
exchangeBaseUrl: string;
exchangeBaseUrl?: string;
amount: AmountJson;
onSwitchExchange: (ex: string) => void;
onWithdraw: () => Promise<void>;
@ -69,53 +60,10 @@ export interface ViewProps {
reviewing: boolean;
reviewed: boolean;
confirmed: boolean;
terms: {
value?: TermsDocument;
status: TermsStatus;
};
terms: TermsState;
knownExchanges: ExchangeListItem[];
}
type TermsStatus = "new" | "accepted" | "changed" | "notfound";
type TermsDocument =
| TermsDocumentXml
| TermsDocumentHtml
| TermsDocumentPlain
| TermsDocumentJson
| TermsDocumentPdf;
interface TermsDocumentXml {
type: "xml";
document: Document;
}
interface TermsDocumentHtml {
type: "html";
href: URL;
}
interface TermsDocumentPlain {
type: "plain";
content: string;
}
interface TermsDocumentJson {
type: "json";
data: any;
}
interface TermsDocumentPdf {
type: "pdf";
location: URL;
}
function amountToString(text: AmountJson): string {
const aj = Amounts.jsonifyAmount(text);
const amount = Amounts.stringifyValue(aj);
return `${amount} ${aj.currency}`;
}
export function View({
withdrawalFee,
exchangeBaseUrl,
@ -162,7 +110,9 @@ export function View({
kind="negative"
/>
)}
<Part title="Exchange" text={exchangeBaseUrl} kind="neutral" big />
{exchangeBaseUrl && (
<Part title="Exchange" text={exchangeBaseUrl} kind="neutral" big />
)}
</section>
{!reviewing && (
<section>
@ -190,13 +140,6 @@ export function View({
)}
</section>
)}
{!reviewing && reviewed && (
<section>
<LinkSuccess upperCased onClick={() => onReview(true)}>
{i18n.str`Show terms of service`}
</LinkSuccess>
</section>
)}
{terms.status === "notfound" && (
<section>
<WarningText>
@ -204,79 +147,14 @@ export function View({
</WarningText>
</section>
)}
{reviewing && (
<section>
{terms.status !== "accepted" &&
terms.value &&
terms.value.type === "xml" && (
<TermsOfService>
<ExchangeXmlTos doc={terms.value.document} />
</TermsOfService>
)}
{terms.status !== "accepted" &&
terms.value &&
terms.value.type === "plain" && (
<div style={{ textAlign: "left" }}>
<pre>{terms.value.content}</pre>
</div>
)}
{terms.status !== "accepted" &&
terms.value &&
terms.value.type === "html" && (
<iframe src={terms.value.href.toString()} />
)}
{terms.status !== "accepted" &&
terms.value &&
terms.value.type === "pdf" && (
<a href={terms.value.location.toString()} download="tos.pdf">
Download Terms of Service
</a>
)}
</section>
)}
{reviewing && reviewed && (
<section>
<LinkSuccess upperCased onClick={() => onReview(false)}>
{i18n.str`Hide terms of service`}
</LinkSuccess>
</section>
)}
{(reviewing || reviewed) && (
<section>
<CheckboxOutlined
name="terms"
enabled={reviewed}
label={i18n.str`I accept the exchange terms of service`}
onToggle={() => {
onAccept(!reviewed);
onReview(false);
}}
/>
</section>
)}
{/**
* Main action section
*/}
<TermsOfServiceSection
reviewed={reviewed}
reviewing={reviewing}
terms={terms}
onAccept={onAccept}
onReview={onReview}
/>
<section>
{terms.status === "new" && !reviewed && !reviewing && (
<ButtonSuccess
upperCased
disabled={!exchangeBaseUrl}
onClick={() => onReview(true)}
>
{i18n.str`Review exchange terms of service`}
</ButtonSuccess>
)}
{terms.status === "changed" && !reviewed && !reviewing && (
<ButtonWarning
upperCased
disabled={!exchangeBaseUrl}
onClick={() => onReview(true)}
>
{i18n.str`Review new version of terms of service`}
</ButtonWarning>
)}
{(terms.status === "accepted" || (needsReview && reviewed)) && (
<ButtonSuccess
upperCased
@ -310,15 +188,15 @@ export function WithdrawPageWithParsedURI({
const [customExchange, setCustomExchange] = useState<string | undefined>(
undefined,
);
const [errorAccepting, setErrorAccepting] = useState<string | undefined>(
undefined,
);
// const [errorAccepting, setErrorAccepting] = useState<string | undefined>(
// undefined,
// );
const [reviewing, setReviewing] = useState<boolean>(false);
const [reviewed, setReviewed] = useState<boolean>(false);
const [confirmed, setConfirmed] = useState<boolean>(false);
const knownExchangesHook = useAsyncAsHook(() => listExchanges());
const knownExchangesHook = useAsyncAsHook(() => wxApi.listExchanges());
const knownExchanges =
!knownExchangesHook || knownExchangesHook.hasError
@ -329,19 +207,25 @@ export function WithdrawPageWithParsedURI({
(ex) => ex.currency === withdrawAmount.currency,
);
const exchange =
customExchange ||
uriInfo.defaultExchangeBaseUrl ||
thisCurrencyExchanges[0]?.exchangeBaseUrl;
const exchange: string | undefined =
customExchange ??
uriInfo.defaultExchangeBaseUrl ??
(thisCurrencyExchanges[0]
? thisCurrencyExchanges[0].exchangeBaseUrl
: undefined);
const detailsHook = useAsyncAsHook(async () => {
if (!exchange) throw Error("no default exchange");
const tos = await getExchangeTos(exchange, ["text/xml"]);
const info = await getExchangeWithdrawalInfo({
const tos = await wxApi.getExchangeTos(exchange, ["text/xml"]);
const tosState = buildTermsOfServiceState(tos);
const info = await wxApi.getExchangeWithdrawalInfo({
exchangeBaseUrl: exchange,
amount: withdrawAmount,
tosAcceptedFormat: ["text/xml"],
});
return { tos, info };
return { tos: tosState, info };
});
if (!detailsHook) {
@ -364,21 +248,24 @@ export function WithdrawPageWithParsedURI({
const details = detailsHook.response;
const onAccept = async (): Promise<void> => {
if (!exchange) return;
try {
await setExchangeTosAccepted(exchange, details.tos.currentEtag);
await wxApi.setExchangeTosAccepted(exchange, details.tos.version);
setReviewed(true);
} catch (e) {
if (e instanceof Error) {
setErrorAccepting(e.message);
//FIXME: uncomment this and display error
// setErrorAccepting(e.message);
}
}
};
const onWithdraw = async (): Promise<void> => {
if (!exchange) return;
setConfirmed(true);
console.log("accepting exchange", exchange);
try {
const res = await acceptWithdrawal(uri, exchange);
const res = await wxApi.acceptWithdrawal(uri, exchange);
console.log("accept withdrawal response", res);
if (res.confirmTransferUrl) {
document.location.href = res.confirmTransferUrl;
@ -388,30 +275,13 @@ export function WithdrawPageWithParsedURI({
}
};
const termsContent: TermsDocument | undefined = parseTermsOfServiceContent(
details.tos.contentType,
details.tos.content,
);
const status: TermsStatus = !termsContent
? "notfound"
: !details.tos.acceptedEtag
? "new"
: details.tos.acceptedEtag !== details.tos.currentEtag
? "changed"
: "accepted";
return (
<View
onWithdraw={onWithdraw}
// details={details.tos}
amount={withdrawAmount}
exchangeBaseUrl={exchange}
withdrawalFee={details.info.withdrawFee} //FIXME
terms={{
status,
value: termsContent,
}}
terms={detailsHook.response.tos}
onSwitchExchange={setCustomExchange}
knownExchanges={knownExchanges}
confirmed={confirmed}
@ -426,7 +296,7 @@ export function WithdrawPage({ talerWithdrawUri }: Props): VNode {
const uriInfoHook = useAsyncAsHook(() =>
!talerWithdrawUri
? Promise.reject(undefined)
: getWithdrawalDetailsForUri({ talerWithdrawUri }),
: wxApi.getWithdrawalDetailsForUri({ talerWithdrawUri }),
);
if (!talerWithdrawUri) {
@ -459,46 +329,3 @@ export function WithdrawPage({ talerWithdrawUri }: Props): VNode {
/>
);
}
function parseTermsOfServiceContent(
type: string,
text: string,
): TermsDocument | undefined {
if (type === "text/xml") {
try {
const document = new DOMParser().parseFromString(text, "text/xml");
return { type: "xml", document };
} catch (e) {
console.log(e);
}
} else if (type === "text/html") {
try {
const href = new URL(text);
return { type: "html", href };
} catch (e) {
console.log(e);
}
} else if (type === "text/json") {
try {
const data = JSON.parse(text);
return { type: "json", data };
} catch (e) {
console.log(e);
}
} else if (type === "text/pdf") {
try {
const location = new URL(text);
return { type: "pdf", location };
} catch (e) {
console.log(e);
}
} else if (type === "text/plain") {
try {
const content = text;
return { type: "plain", content };
} catch (e) {
console.log(e);
}
}
return undefined;
}

View File

@ -0,0 +1,781 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
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/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
export const termsHtml = `<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Terms Of Service &#8212; Taler Terms of Service</title>
</head><body>
<div>
Terms of service
</div>
<div>
A complete separated html with it's own design
</div>
</body>
</html>
`;
export const termsPlain = `
Terms Of Service
****************
Last Updated: 12.4.2019
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.
Overview
========
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 Wallets 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.
Highlights:
-----------
* 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.
* 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.
* 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.
* You agree to not intentionally overwhelm our systems with
requests and follow responsible disclosure if you find security
issues in our services.
* 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.
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 legal@taler-systems.com. If you do not agree to this
Agreement, you must not use our Services.
How you accept this policy
==========================
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.
Services
========
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.
Fees
====
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.
Eligibility
===========
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.
Financial self-responsibility
=============================
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.
Copyrights and trademarks
=========================
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 GPLs full terms and
conditions at https://www.gnu.org/licenses/gpl-3.0.en.html. “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.
Your use of our services
========================
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 security@taler-systems.com 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.
Limitation of liability & disclaimer of warranties
==================================================
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:
1. user error such as forgotten passwords, incorrectly constructed
transactions;
2. server failure or data loss;
3. unauthorized access to the Taler Wallet application;
4. bugs or other errors in the Taler Wallet software; and
5. 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.
Any other terms, conditions, warranties, or representations associated
with such content, are solely between you and such organizations
and/or individuals.
Limitation of liability
=======================
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:
1. any lost profits, data loss, cost of procurement of substitute
goods or services, or direct, indirect, incidental, special,
punitive, compensatory, or consequential damages of any kind
whatsoever resulting from:
1. your use of, or conduct in connection with, our services;
2. any unauthorized use of your wallet and/or private key due to
your failure to maintain the confidentiality of your wallet;
3. any interruption or cessation of transmission to or from the
services; or
4. 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
2. any direct damages.
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.
Warranty disclaimer
===================
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.
Indemnity
=========
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, attorneys 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.
Time limitation on claims
=========================
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.
Governing law
=============
No matter where youre 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.
Termination
===========
In the event of termination concerning your use of our Services, your
obligations under this Agreement will still continue.
Discontinuance of services
==========================
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 protocols 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.
No waiver
=========
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.
Severability
============
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.
Force majeure
=============
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.
Assignment
==========
You agree that we may assign any of our rights and/or transfer, sub-
contract, or delegate any of our obligations under these Terms.
Entire agreement
================
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.
Questions or comments
=====================
We welcome comments, questions, concerns, or suggestions. Please send
us a message on our contact page at legal@taler-systems.com.
`;
export const termsXml = `<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE document PUBLIC "+//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML" "http://docutils.sourceforge.net/docs/ref/docutils.dtd">
<!-- Generated by Docutils 0.14 -->
<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
Wallets 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 GPLs 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
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, attorneys 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 youre 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 protocols 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 termsPdf = `
%PDF-1.2
9 0 obj << >>
stream
BT/ 9 Tf(This is the Exchange TERMS OF SERVICE)' ET
endstream
endobj
4 0 obj << /Type /Page /Parent 5 0 R /Contents 9 0 R >> endobj
5 0 obj << /Kids [4 0 R ] /Count 1 /Type /Pages /MediaBox [ 0 0 180 20 ] >> endobj
3 0 obj << /Pages 5 0 R /Type /Catalog >> endobj
trailer
<< /Root 3 0 R >>
%%EOF
`;

View File

@ -71,6 +71,11 @@ export function BalanceView({
<Linker pageName="/welcome">help</Linker> getting started?
</i18n.Translate>
</p>
<footer style={{ justifyContent: "space-around" }}>
<ButtonPrimary onClick={goToWalletManualWithdraw}>
Withdraw
</ButtonPrimary>
</footer>
</Fragment>
);
}

View File

@ -30,13 +30,8 @@ export default {
},
};
export const AllOff = createExample(TestedComponent, {
deviceName: "this-is-the-device-name",
setDeviceName: () => Promise.resolve(),
});
export const AllOff = createExample(TestedComponent, {});
export const OneChecked = createExample(TestedComponent, {
deviceName: "this-is-the-device-name",
permissionsEnabled: true,
setDeviceName: () => Promise.resolve(),
});

View File

@ -14,36 +14,18 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { ExchangeListItem, i18n } from "@gnu-taler/taler-util";
import { i18n } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { Checkbox } from "../components/Checkbox";
import { ButtonPrimary } from "../components/styled";
import { useDevContext } from "../context/devContext";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
import { useBackupDeviceName } from "../hooks/useBackupDeviceName";
import { useExtendedPermissions } from "../hooks/useExtendedPermissions";
import { useLang } from "../hooks/useLang";
// import { strings as messages } from "../i18n/strings";
import * as wxApi from "../wxApi";
export function SettingsPage(): VNode {
const [permissionsEnabled, togglePermissions] = useExtendedPermissions();
const { devMode, toggleDevMode } = useDevContext();
const { name, update } = useBackupDeviceName();
const [lang, changeLang] = useLang();
const exchangesHook = useAsyncAsHook(wxApi.listExchanges);
return (
<SettingsView
lang={lang}
changeLang={changeLang}
knownExchanges={
!exchangesHook || exchangesHook.hasError
? []
: exchangesHook.response.exchanges
}
deviceName={name}
setDeviceName={update}
permissionsEnabled={permissionsEnabled}
togglePermissions={togglePermissions}
developerMode={devMode}
@ -53,36 +35,13 @@ export function SettingsPage(): VNode {
}
export interface ViewProps {
lang: string;
changeLang: (s: string) => void;
deviceName: string;
setDeviceName: (s: string) => Promise<void>;
permissionsEnabled: boolean;
togglePermissions: () => void;
developerMode: boolean;
toggleDeveloperMode: () => void;
knownExchanges: Array<ExchangeListItem>;
}
// type LangsNames = {
// [P in keyof typeof messages]: string;
// };
// const names: LangsNames = {
// es: "Español [es]",
// en: "English [en]",
// fr: "Français [fr]",
// de: "Deutsch [de]",
// sv: "Svenska [sv]",
// it: "Italiano [it]",
// };
export function SettingsView({
knownExchanges,
// lang,
// changeLang,
// deviceName,
// setDeviceName,
permissionsEnabled,
togglePermissions,
developerMode,
@ -91,45 +50,6 @@ export function SettingsView({
return (
<Fragment>
<section>
<h2>
<i18n.Translate>Known exchanges</i18n.Translate>
</h2>
{!knownExchanges || !knownExchanges.length ? (
<div>No exchange yet!</div>
) : (
<Fragment>
<table>
{knownExchanges.map((e, idx) => (
<tr key={idx}>
<td>{e.currency}</td>
<td>
<a href={e.exchangeBaseUrl}>{e.exchangeBaseUrl}</a>
</td>
</tr>
))}
</table>
</Fragment>
)}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div />
<ButtonPrimary>Manage exchange</ButtonPrimary>
</div>
{/* <h2><i18n.Translate>Wallet</i18n.Translate></h2> */}
{/* <SelectList
value={lang}
onChange={changeLang}
name="lang"
list={names}
label={i18n.str`Language`}
description="(Choose your preferred lang)"
/>
<EditableText
value={deviceName}
onChange={setDeviceName}
name="device-id"
label={i18n.str`Device name`}
description="(This is how you will recognize the wallet in the backup provider)"
/> */}
<h2>
<i18n.Translate>Permissions</i18n.Translate>
</h2>

View File

@ -38,6 +38,7 @@ import { ProviderAddPage } from "./wallet/ProviderAddPage";
import { ProviderDetailPage } from "./wallet/ProviderDetailPage";
import { SettingsPage } from "./popup/Settings";
import { TalerActionFound } from "./popup/TalerActionFound";
import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
function main(): void {
try {
@ -127,6 +128,15 @@ function Application() {
route(Pages.backup);
}}
/>
<Route
path={Pages.exchange_add}
component={ExchangeAddPage}
onBack={() => {
route(Pages.balance);
}}
/>
<Route default component={Redirect} to={Pages.balance} />
</Router>
</PopupBox>

View File

@ -0,0 +1,162 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
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 { AmountJson, Amounts, GetExchangeTosResult } from "@gnu-taler/taler-util";
function getJsonIfOk(r: Response): Promise<any> {
if (r.ok) {
return r.json();
}
if (r.status >= 400 && r.status < 500) {
throw new Error(`URL may not be right: (${r.status}) ${r.statusText}`);
}
throw new Error(
`Try another server: (${r.status}) ${r.statusText || "internal server error"
}`,
);
}
export async function queryToSlashConfig<T>(
url: string,
): Promise<T> {
return fetch(new URL("config", url).href)
.catch(() => {
throw new Error(`Network error`);
})
.then(getJsonIfOk);
}
export async function queryToSlashKeys<T>(
url: string,
): Promise<T> {
return fetch(new URL("keys", url).href)
.catch(() => {
throw new Error(`Network error`);
})
.then(getJsonIfOk);
}
export function buildTermsOfServiceState(tos: GetExchangeTosResult): TermsState {
const content: TermsDocument | undefined = parseTermsOfServiceContent(
tos.contentType,
tos.content,
);
const status: TermsStatus = !content
? "notfound"
: !tos.acceptedEtag
? "new"
: tos.acceptedEtag !== tos.currentEtag
? "changed"
: "accepted";
return { content, status, version: tos.currentEtag }
}
function parseTermsOfServiceContent(
type: string,
text: string,
): TermsDocument | undefined {
if (type === "text/xml") {
try {
const document = new DOMParser().parseFromString(text, "text/xml");
return { type: "xml", document };
} catch (e) {
console.log(e);
}
} else if (type === "text/html") {
try {
const href = new URL(text);
return { type: "html", href };
} catch (e) {
console.log(e);
}
} else if (type === "text/json") {
try {
const data = JSON.parse(text);
return { type: "json", data };
} catch (e) {
console.log(e);
}
} else if (type === "text/pdf") {
try {
const location = new URL(text);
return { type: "pdf", location };
} catch (e) {
console.log(e);
}
} else if (type === "text/plain") {
try {
const content = text;
return { type: "plain", content };
} catch (e) {
console.log(e);
}
}
return undefined;
}
export type TermsState = {
content: TermsDocument | undefined;
status: TermsStatus;
version: string;
};
type TermsStatus = "new" | "accepted" | "changed" | "notfound";
type TermsDocument =
| TermsDocumentXml
| TermsDocumentHtml
| TermsDocumentPlain
| TermsDocumentJson
| TermsDocumentPdf;
interface TermsDocumentXml {
type: "xml";
document: Document;
}
interface TermsDocumentHtml {
type: "html";
href: URL;
}
interface TermsDocumentPlain {
type: "plain";
content: string;
}
interface TermsDocumentJson {
type: "json";
data: any;
}
interface TermsDocumentPdf {
type: "pdf";
location: URL;
}
export function amountToString(text: AmountJson): string {
const aj = Amounts.jsonifyAmount(text);
const amount = Amounts.stringifyValue(aj);
return `${amount} ${aj.currency}`;
}

View File

@ -17,7 +17,7 @@
import { BalancesResponse, i18n } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { BalanceTable } from "../components/BalanceTable";
import { ButtonPrimary, ErrorBox } from "../components/styled/index";
import { ButtonPrimary, Centered, ErrorBox } from "../components/styled/index";
import { HookResponse, useAsyncAsHook } from "../hooks/useAsyncAsHook";
import { PageLink } from "../renderHtml";
import * as wxApi from "../wxApi";
@ -66,10 +66,17 @@ export function BalanceView({
if (balance.response.balances.length === 0) {
return (
<p>
<i18n.Translate>
You have no balance to show. Need some{" "}
<Linker pageName="/welcome">help</Linker> getting started?
</i18n.Translate>
<Centered style={{ marginTop: 100 }}>
<i18n.Translate>
You have no balance to show. Need some{" "}
<Linker pageName="/welcome">help</Linker> getting started?
</i18n.Translate>
<div>
<ButtonPrimary onClick={goToWalletManualWithdraw}>
Withdraw
</ButtonPrimary>
</div>
</Centered>
</p>
);
}

View File

@ -21,6 +21,7 @@
import { AmountJson, Amounts, i18n } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { route } from "preact-router";
import { useState } from "preact/hooks";
import { ErrorMessage } from "../components/ErrorMessage";
import { SelectList } from "../components/SelectList";
@ -32,7 +33,9 @@ import {
Input,
InputWithLabel,
LightText,
LinkPrimary,
} from "../components/styled";
import { Pages } from "../NavigationBar";
export interface Props {
error: string | undefined;
@ -87,12 +90,7 @@ export function CreateManualWithdraw({
return (
<Centered style={{ marginTop: 100 }}>
<BoldLight>No exchange configured</BoldLight>
<ButtonSuccess
//FIXME: add exchange feature
onClick={() => {
null;
}}
>
<ButtonSuccess onClick={() => route(Pages.exchange_add)}>
<i18n.Translate>Add exchange</i18n.Translate>
</ButtonSuccess>
</Centered>
@ -108,8 +106,9 @@ export function CreateManualWithdraw({
/>
<h2>Manual Withdrawal</h2>
<LightText>
Choose a exchange to create a reserve and then fill the reserve to
withdraw the coins
Choose a exchange from where the coins will be withdrawn. The exchange
will send the coins to this wallet after receiving a wire transfer
with the correct subject.
</LightText>
<p>
<Input>
@ -130,11 +129,14 @@ export function CreateManualWithdraw({
onChange={changeExchange}
/>
</Input>
{/* <p style={{ display: "flex", justifyContent: "right" }}>
<a href="" style={{ marginLeft: "auto" }}>
Add new exchange
</a>
</p> */}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<LinkPrimary
onClick={() => route(Pages.exchange_add)}
style={{ marginLeft: "auto" }}
>
<i18n.Translate>Add exchange</i18n.Translate>
</LinkPrimary>
</div>
{currency && (
<InputWithLabel invalid={!!amount && !parsedAmount}>
<label>Amount</label>

View File

@ -0,0 +1,67 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
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/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
import { termsXml } from "../cta/termsExample";
import { createExample } from "../test-utils";
import { View as TestedComponent } from "./ExchangeAddConfirm";
export default {
title: "wallet/exchange add/confirm",
component: TestedComponent,
argTypes: {
onRetry: { action: "onRetry" },
onDelete: { action: "onDelete" },
onBack: { action: "onBack" },
},
};
export const TermsNotFound = createExample(TestedComponent, {
url: "https://exchange.demo.taler.net/",
terms: {
status: "notfound",
version: "1",
content: undefined,
},
onAccept: async () => undefined,
});
export const NewTerms = createExample(TestedComponent, {
url: "https://exchange.demo.taler.net/",
terms: {
status: "new",
version: "1",
content: undefined,
},
onAccept: async () => undefined,
});
export const TermsChanged = createExample(TestedComponent, {
url: "https://exchange.demo.taler.net/",
terms: {
status: "changed",
version: "1",
content: {
type: "xml",
document: new DOMParser().parseFromString(termsXml, "text/xml"),
},
},
onAccept: async () => undefined,
});

View File

@ -0,0 +1,152 @@
import { i18n } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import {
Button,
ButtonSuccess,
ButtonWarning,
WarningBox,
} from "../components/styled/index";
import { TermsOfServiceSection } from "../cta/TermsOfServiceSection";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
import { buildTermsOfServiceState, TermsState } from "../utils";
import * as wxApi from "../wxApi";
export interface Props {
url: string;
onCancel: () => void;
onConfirm: () => void;
}
export function ExchangeAddConfirmPage({
url,
onCancel,
onConfirm,
}: Props): VNode {
const detailsHook = useAsyncAsHook(async () => {
const tos = await wxApi.getExchangeTos(url, ["text/xml"]);
const tosState = buildTermsOfServiceState(tos);
return { tos: tosState };
});
const termsNotFound: TermsState = {
status: "notfound",
version: "",
content: undefined,
};
const terms = !detailsHook
? undefined
: detailsHook.hasError
? termsNotFound
: detailsHook.response.tos;
// const [errorAccepting, setErrorAccepting] = useState<string | undefined>(
// undefined,
// );
const onAccept = async (): Promise<void> => {
if (!terms) return;
try {
await wxApi.setExchangeTosAccepted(url, terms.version);
} catch (e) {
if (e instanceof Error) {
// setErrorAccepting(e.message);
}
}
};
return (
<View
url={url}
onAccept={onAccept}
onCancel={onCancel}
onConfirm={onConfirm}
terms={terms}
/>
);
}
export interface ViewProps {
url: string;
terms: TermsState | undefined;
onAccept: (b: boolean) => Promise<void>;
onCancel: () => void;
onConfirm: () => void;
}
export function View({
url,
terms,
onAccept: doAccept,
onConfirm,
onCancel,
}: ViewProps): VNode {
const needsReview =
!terms || terms.status === "changed" || terms.status === "new";
const [reviewed, setReviewed] = useState<boolean>(false);
return (
<Fragment>
<section>
<h1>Review terms of service</h1>
<div>
Exchange URL:
<a href={url} target="_blank" rel="noreferrer">
{url}
</a>
</div>
</section>
{terms && terms.status === "notfound" && (
<section>
<WarningBox>
{i18n.str`Exchange doesn't have terms of service`}
</WarningBox>
</section>
)}
{terms && (
<TermsOfServiceSection
reviewed={reviewed}
reviewing={true}
terms={terms}
onAccept={(value) =>
doAccept(value).then(() => {
setReviewed(value);
})
}
/>
)}
<footer>
<Button onClick={onCancel}>
<i18n.Translate>Cancel</i18n.Translate>
</Button>
{!terms && (
<Button disabled>
<i18n.Translate>Loading terms..</i18n.Translate>
</Button>
)}
{terms && (
<Fragment>
{needsReview && !reviewed && (
<ButtonSuccess disabled upperCased onClick={onConfirm}>
{i18n.str`Add exchange`}
</ButtonSuccess>
)}
{(terms.status === "accepted" || (needsReview && reviewed)) && (
<ButtonSuccess upperCased onClick={onConfirm}>
{i18n.str`Add exchange`}
</ButtonSuccess>
)}
{terms.status === "notfound" && (
<ButtonWarning upperCased onClick={onConfirm}>
{i18n.str`Add exchange anyway`}
</ButtonWarning>
)}
</Fragment>
)}
</footer>
</Fragment>
);
}

View File

@ -0,0 +1,75 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
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 {
canonicalizeBaseUrl,
TalerConfigResponse,
} from "@gnu-taler/taler-util";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
import { queryToSlashKeys } from "../utils";
import * as wxApi from "../wxApi";
import { ExchangeAddConfirmPage } from "./ExchangeAddConfirm";
import { ExchangeSetUrlPage } from "./ExchangeSetUrl";
interface Props {
currency: string;
onBack: () => void;
}
export function ExchangeAddPage({ onBack }: Props): VNode {
const [verifying, setVerifying] = useState<
{ url: string; config: TalerConfigResponse } | undefined
>(undefined);
const knownExchangesResponse = useAsyncAsHook(wxApi.listExchanges);
const knownExchanges = !knownExchangesResponse
? []
: knownExchangesResponse.hasError
? []
: knownExchangesResponse.response.exchanges;
if (!verifying) {
return (
<ExchangeSetUrlPage
onCancel={onBack}
knownExchanges={knownExchanges}
onVerify={(url) => queryToSlashKeys(url)}
onConfirm={(url) =>
queryToSlashKeys<TalerConfigResponse>(url)
.then((config) => {
setVerifying({ url, config });
})
.catch((e) => e.message)
}
/>
);
}
return (
<ExchangeAddConfirmPage
url={verifying.url}
onCancel={onBack}
onConfirm={async () => {
await wxApi.addExchange({
exchangeBaseUrl: canonicalizeBaseUrl(verifying.url),
forceUpdate: true,
});
onBack();
}}
/>
);
}

View File

@ -0,0 +1,62 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
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/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
import { createExample } from "../test-utils";
import { queryToSlashKeys } from "../utils";
import { ExchangeSetUrlPage as TestedComponent } from "./ExchangeSetUrl";
export default {
title: "wallet/exchange add/set url",
component: TestedComponent,
argTypes: {
onRetry: { action: "onRetry" },
onDelete: { action: "onDelete" },
onBack: { action: "onBack" },
},
};
export const ExpectedUSD = createExample(TestedComponent, {
expectedCurrency: "USD",
onVerify: queryToSlashKeys,
knownExchanges: [],
});
export const ExpectedKUDOS = createExample(TestedComponent, {
expectedCurrency: "KUDOS",
onVerify: queryToSlashKeys,
knownExchanges: [],
});
export const InitialState = createExample(TestedComponent, {
onVerify: queryToSlashKeys,
knownExchanges: [],
});
export const WithDemoAsKnownExchange = createExample(TestedComponent, {
knownExchanges: [
{
currency: "TESTKUDOS",
exchangeBaseUrl: "https://exchange.demo.taler.net/",
paytoUris: [],
},
],
onVerify: queryToSlashKeys,
});

View File

@ -0,0 +1,130 @@
import {
canonicalizeBaseUrl,
ExchangeListItem,
i18n,
TalerConfigResponse,
} from "@gnu-taler/taler-util";
import { Fragment, h } from "preact";
import { useEffect, useState } from "preact/hooks";
import { ErrorMessage } from "../components/ErrorMessage";
import {
Button,
ButtonPrimary,
Input,
WarningBox,
} from "../components/styled/index";
export interface Props {
initialValue?: string;
expectedCurrency?: string;
knownExchanges: ExchangeListItem[];
onCancel: () => void;
onVerify: (s: string) => Promise<TalerConfigResponse | undefined>;
onConfirm: (url: string) => Promise<string | undefined>;
withError?: string;
}
export function ExchangeSetUrlPage({
initialValue,
knownExchanges,
expectedCurrency,
onCancel,
onVerify,
onConfirm,
withError,
}: Props) {
const [value, setValue] = useState<string>(initialValue || "");
const [dirty, setDirty] = useState(false);
const [result, setResult] = useState<TalerConfigResponse | undefined>(
undefined,
);
const [error, setError] = useState<string | undefined>(withError);
useEffect(() => {
try {
const url = canonicalizeBaseUrl(value);
const found =
knownExchanges.findIndex((e) => e.exchangeBaseUrl === url) !== -1;
if (found) {
setError("This exchange is already known");
return;
}
onVerify(url)
.then((r) => {
setResult(r);
})
.catch(() => {
setResult(undefined);
});
setDirty(true);
} catch {
setResult(undefined);
}
}, [value]);
return (
<Fragment>
<section>
{!expectedCurrency ? (
<h1>Add new exchange</h1>
) : (
<h2>Add exchange for {expectedCurrency}</h2>
)}
<ErrorMessage
title={error && "Unable to add this exchange"}
description={error}
/>
<p>
<Input invalid={dirty && !!error}>
<label>URL</label>
<input
type="text"
placeholder="https://"
value={value}
onInput={(e) => setValue(e.currentTarget.value)}
/>
</Input>
{result && (
<Fragment>
<Input>
<label>Version</label>
<input type="text" disabled value={result.version} />
</Input>
<Input>
<label>Currency</label>
<input type="text" disabled value={result.currency} />
</Input>
</Fragment>
)}
</p>
</section>
{result && expectedCurrency && expectedCurrency !== result.currency && (
<WarningBox>
This exchange doesn't match the expected currency{" "}
<b>{expectedCurrency}</b>
</WarningBox>
)}
<footer>
<Button onClick={onCancel}>
<i18n.Translate>Cancel</i18n.Translate>
</Button>
<ButtonPrimary
disabled={
!result ||
!!error ||
(expectedCurrency !== undefined &&
expectedCurrency !== result.currency)
}
onClick={() => {
const url = canonicalizeBaseUrl(value);
return onConfirm(url).then((r) => (r ? setError(r) : undefined));
}}
>
<i18n.Translate>Next</i18n.Translate>
</ButtonPrimary>
</footer>
</Fragment>
);
}

View File

@ -31,6 +31,7 @@ import {
LightText,
SmallLightText,
} from "../components/styled/index";
import { queryToSlashConfig } from "../utils";
import * as wxApi from "../wxApi";
interface Props {
@ -38,45 +39,19 @@ interface Props {
onBack: () => void;
}
function getJsonIfOk(r: Response) {
if (r.ok) {
return r.json();
} else {
if (r.status >= 400 && r.status < 500) {
throw new Error(`URL may not be right: (${r.status}) ${r.statusText}`);
} else {
throw new Error(
`Try another server: (${r.status}) ${
r.statusText || "internal server error"
}`,
);
}
}
}
export function ProviderAddPage({ onBack }: Props): VNode {
const [verifying, setVerifying] = useState<
| { url: string; name: string; provider: BackupBackupProviderTerms }
| undefined
>(undefined);
async function getProviderInfo(
url: string,
): Promise<BackupBackupProviderTerms> {
return fetch(new URL("config", url).href)
.catch((e) => {
throw new Error(`Network error`);
})
.then(getJsonIfOk);
}
if (!verifying) {
return (
<SetUrlView
onCancel={onBack}
onVerify={(url) => getProviderInfo(url)}
onVerify={(url) => queryToSlashConfig(url)}
onConfirm={(url, name) =>
getProviderInfo(url)
queryToSlashConfig<BackupBackupProviderTerms>(url)
.then((provider) => {
setVerifying({ url, name, provider });
})

View File

@ -3,6 +3,7 @@ import { Fragment, h, VNode } from "preact";
import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType";
import { QR } from "../components/QR";
import { ButtonDestructive, WarningBox } from "../components/styled";
import { amountToString } from "../utils";
export interface Props {
reservePub: string;
payto: string;
@ -29,10 +30,10 @@ export function ReserveCreated({
<h1>Exchange is ready for withdrawal!</h1>
<p>
To complete the process you need to wire{" "}
<b>{Amounts.stringify(amount)}</b> to the exchange bank account
<b>{amountToString(amount)}</b> to the exchange bank account
</p>
<BankDetailsByPaytoType
amount={Amounts.stringify(amount)}
amount={amountToString(amount)}
exchangeBaseUrl={exchangeBaseUrl}
payto={paytoURI}
subject={reservePub}

View File

@ -17,12 +17,13 @@
import { ExchangeListItem, i18n } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { Checkbox } from "../components/Checkbox";
import { ButtonPrimary } from "../components/styled";
import { LinkPrimary } from "../components/styled";
import { useDevContext } from "../context/devContext";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
import { useBackupDeviceName } from "../hooks/useBackupDeviceName";
import { useExtendedPermissions } from "../hooks/useExtendedPermissions";
import { useLang } from "../hooks/useLang";
import { Pages } from "../NavigationBar";
// import { strings as messages } from "../i18n/strings";
import * as wxApi from "../wxApi";
@ -112,7 +113,7 @@ export function SettingsView({
)}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div />
<ButtonPrimary>Manage exchange</ButtonPrimary>
<LinkPrimary href={Pages.exchange_add}>Add an exchange</LinkPrimary>
</div>
<h2>

View File

@ -44,6 +44,7 @@ import { ManualWithdrawPage } from "./wallet/ManualWithdrawPage";
import { WalletBox } from "./components/styled";
import { ProviderDetailPage } from "./wallet/ProviderDetailPage";
import { ProviderAddPage } from "./wallet/ProviderAddPage";
import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
function main(): void {
try {
@ -131,6 +132,14 @@ function Application(): VNode {
}}
/>
<Route
path={Pages.exchange_add}
component={withLogoAndNavBar(ExchangeAddPage)}
onBack={() => {
route(Pages.balance);
}}
/>
<Route
path={Pages.manual_withdraw}
component={withLogoAndNavBar(ManualWithdrawPage)}