diff options
Diffstat (limited to 'packages/taler-wallet-webextension')
23 files changed, 1700 insertions, 1124 deletions
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx index 56704fb57..8dc73efdb 100644 --- a/packages/taler-wallet-webextension/src/NavigationBar.tsx +++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx @@ -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", diff --git a/packages/taler-wallet-webextension/src/components/CheckboxOutlined.tsx b/packages/taler-wallet-webextension/src/components/CheckboxOutlined.tsx index 3b9519f39..c22103a85 100644 --- a/packages/taler-wallet-webextension/src/components/CheckboxOutlined.tsx +++ b/packages/taler-wallet-webextension/src/components/CheckboxOutlined.tsx @@ -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> ); } diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx index b2ca13801..7cef8789b 100644 --- a/packages/taler-wallet-webextension/src/components/styled/index.tsx +++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx @@ -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; } } diff --git a/packages/taler-wallet-webextension/src/cta/TermsOfServiceSection.tsx b/packages/taler-wallet-webextension/src/cta/TermsOfServiceSection.tsx new file mode 100644 index 000000000..5eddde64f --- /dev/null +++ b/packages/taler-wallet-webextension/src/cta/TermsOfServiceSection.tsx @@ -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> + ); +} diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx index 54ae19c61..fbbecd6f3 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx @@ -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 — 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 Wallet’s self-hosted personal payment -application. When using the Taler Wallet to interact with our -Services, you are agreeing to our Terms, so please read carefully. - - -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 GPL’s 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, attorney’s fees) -arising from: (a) your use of and access to the Services; (b) any -feedback or submissions you provide to us concerning the Taler Wallet; -(c) your violation of any term of this Agreement; or (d) your -violation of any law, rule, or regulation, or the rights of any third -party. - - -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 you’re located, the laws of Switzerland will govern -these Terms. If any provisions of these Terms are inconsistent with -any applicable law, those provisions will be superseded or modified -only to the extent such provisions are inconsistent. The parties agree -to submit to the ordinary courts in Zurich, Switzerland for exclusive -jurisdiction of any dispute arising out of or related to your use of -the Services or your breach of these Terms. - - -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 protocol’s provisions to notify Wallets if our Services are -to be discontinued. It is your responsibility to ensure that the Taler -Wallet is online at least once every three months to observe these -notifications. We shall not be held responsible or liable for any loss -of funds in the event that we discontinue or depreciate the Services -and your Taler Wallet fails to transfer out the coins within a three -months notification period. - - -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 - Wallet’s self-hosted personal payment application. When using the Taler Wallet - to interact with our Services, you are agreeing to our Terms, so please read - carefully.</paragraph> - <section ids="highlights" names="highlights:"> - <title>Highlights:</title> - <block_quote> - <bullet_list bullet="•"> - <list_item> - <paragraph>You are responsible for keeping the data in your Taler Wallet at all times - under your control. Any losses arising from you not being in control of - your private information are your problem.</paragraph> - </list_item> - <list_item> - <paragraph>We will try to transfer funds we hold in escrow for our users to any legal - recipient to the best of our ability within the limitations of the law and - our implementation. However, the Services offered today are highly - experimental and the set of recipients of funds is severely restricted.</paragraph> - </list_item> - <list_item> - <paragraph>For our Services, we may charge transaction fees. The specific fee structure - is provided based on the Taler protocol and should be shown to you when you - withdraw electronic coins using a Taler Wallet. You agree and understand - that the Taler protocol allows for the fee structure to change.</paragraph> - </list_item> - <list_item> - <paragraph>You agree to not intentionally overwhelm our systems with requests and - follow responsible disclosure if you find security issues in our services.</paragraph> - </list_item> - <list_item> - <paragraph>We cannot be held accountable for our Services not being available due to - circumstances beyond our control. If we modify or terminate our services, - we will try to give you the opportunity to recover your funds. However, - given the experimental state of the Services today, this may not be - possible. You are strongly advised to limit your use of the Service - to small-scale experiments expecting total loss of all funds.</paragraph> - </list_item> - </bullet_list> - </block_quote> - <paragraph>These terms outline approved uses of our Services. The Services and these - Terms are still at an experimental stage. If you have any questions or - comments related to this Agreement, please send us a message to - <reference refuri="mailto:legal@taler-systems.com">legal@taler-systems.com</reference>. If you do not agree to this Agreement, you must not - use our Services.</paragraph> - </section> - </section> - <section ids="how-you-accept-this-policy" names="how\ you\ accept\ this\ policy"> - <title>How you accept this policy</title> - <paragraph>By sending funds to us (to top-up your Taler Wallet), you acknowledge that you - have read, understood, and agreed to these Terms. We reserve the right to - change these Terms at any time. If you disagree with the change, we may in the - future offer you with an easy option to recover your unspent funds. However, - in the current experimental period you acknowledge that this feature is not - yet available, resulting in your funds being lost unless you accept the new - Terms. If you continue to use our Services other than to recover your unspent - funds, your continued use of our Services following any such change will - signify your acceptance to be bound by the then current Terms. Please check - the effective date above to determine if there have been any changes since you - have last reviewed these Terms.</paragraph> - </section> - <section ids="services" names="services"> - <title>Services</title> - <paragraph>We will try to transfer funds that we hold in escrow for our users to any - legal recipient to the best of our ability and within the limitations of the - law and our implementation. However, the Services offered today are highly - experimental and the set of recipients of funds is severely restricted. The - Taler Wallet can be loaded by exchanging fiat currencies against electronic - coins. We are providing this exchange service. Once your Taler Wallet is - loaded with electronic coins they can be spent for purchases if the seller is - accepting Taler as a means of payment. We are not guaranteeing that any seller - is accepting Taler at all or a particular seller. The seller or recipient of - deposits of electronic coins must specify the target account, as per the - design of the Taler protocol. They are responsible for following the protocol - and specifying the correct bank account, and are solely liable for any losses - that may arise from specifying the wrong account. We will allow the government - to link wire transfers to the underlying contract hash. It is the - responsibility of recipients to preserve the full contracts and to pay - whatever taxes and charges may be applicable. Technical issues may lead to - situations where we are unable to make transfers at all or lead to incorrect - transfers that cannot be reversed. We will only refuse to execute transfers if - the transfers are prohibited by a competent legal authority and we are ordered - to do so.</paragraph> - </section> - <section ids="fees" names="fees"> - <title>Fees</title> - <paragraph>You agree to pay the fees for exchanges and withdrawals completed via the - Taler Wallet (“Fees”) as defined by us, which we may change from time to - time. With the exception of wire transfer fees, Taler transaction fees are set - for any electronic coin at the time of withdrawal and fixed throughout the - validity period of the respective electronic coin. Your wallet should obtain - and display applicable fees when withdrawing funds. Fees for coins obtained as - change may differ from the fees applicable to the original coin. Wire transfer - fees that are independent from electronic coins may change annually. You - authorize us to charge or deduct applicable fees owed in connection with - deposits, exchanges and withdrawals following the rules of the Taler protocol. - We reserve the right to provide different types of rewards to users either in - the form of discount for our Services or in any other form at our discretion - and without prior notice to you.</paragraph> - </section> - <section ids="eligibility" names="eligibility"> - <title>Eligibility</title> - <paragraph>To be eligible to use our Services, you must be able to form legally binding - contracts or have the permission of your legal guardian. By using our - Services, you represent and warrant that you meet all eligibility requirements - that we outline in these Terms.</paragraph> - </section> - <section ids="financial-self-responsibility" names="financial\ self-responsibility"> - <title>Financial self-responsibility</title> - <paragraph>You will be responsible for maintaining the availability, integrity and - confidentiality of the data stored in your wallet. When you setup a Taler - Wallet, you are strongly advised to follow the precautionary measures offered - by the software to minimize the chances to losse access to or control over - your Wallet data. We will not be liable for any loss or damage arising from - your failure to comply with this paragraph.</paragraph> - </section> - <section ids="copyrights-and-trademarks" names="copyrights\ and\ trademarks"> - <title>Copyrights and trademarks</title> - <paragraph>The Taler Wallet is released under the terms of the GNU General Public License - (GNU GPL). You have the right to access, use, and share the Taler Wallet, in - modified or unmodified form. However, the GPL is a strong copyleft license, - which means that any derivative works must be distributed under the same - license terms as the original software. If you have any questions, you should - review the GNU GPL’s full terms and conditions at - <reference refuri="https://www.gnu.org/licenses/gpl-3.0.en.html">https://www.gnu.org/licenses/gpl-3.0.en.html</reference>. “Taler” itself is a trademark - of Taler Systems SA. You are welcome to use the name in relation to processing - payments using the Taler protocol, assuming your use is compatible with an - official release from the GNU Project that is not older than two years.</paragraph> - </section> - <section ids="your-use-of-our-services" names="your\ use\ of\ our\ services"> - <title>Your use of our services</title> - <paragraph>When using our Services, you agree to not take any action that intentionally - imposes an unreasonable load on our infrastructure. If you find security - problems in our Services, you agree to first report them to - <reference refuri="mailto:security@taler-systems.com">security@taler-systems.com</reference> and grant us the right to publish your report. We - warrant that we will ourselves publicly disclose any issues reported within 3 - months, and that we will not prosecute anyone reporting security issues if - they did not exploit the issue beyond a proof-of-concept, and followed the - above responsible disclosure practice.</paragraph> - </section> - <section ids="limitation-of-liability-disclaimer-of-warranties" names="limitation\ of\ liability\ &\ disclaimer\ of\ warranties"> - <title>Limitation of liability & disclaimer of warranties</title> - <paragraph>You understand and agree that we have no control over, and no duty to take any - action regarding: Failures, disruptions, errors, or delays in processing that - you may experience while using our Services; The risk of failure of hardware, - software, and Internet connections; The risk of malicious software being - introduced or found in the software underlying the Taler Wallet; The risk that - third parties may obtain unauthorized access to information stored within your - Taler Wallet, including, but not limited to your Taler Wallet coins or backup - encryption keys. You release us from all liability related to any losses, - damages, or claims arising from:</paragraph> - <enumerated_list enumtype="loweralpha" prefix="(" suffix=")"> - <list_item> - <paragraph>user error such as forgotten passwords, incorrectly constructed - transactions;</paragraph> - </list_item> - <list_item> - <paragraph>server failure or data loss;</paragraph> - </list_item> - <list_item> - <paragraph>unauthorized access to the Taler Wallet application;</paragraph> - </list_item> - <list_item> - <paragraph>bugs or other errors in the Taler Wallet software; and</paragraph> - </list_item> - <list_item> - <paragraph>any unauthorized third party activities, including, but not limited to, - the use of viruses, phishing, brute forcing, or other means of attack - against the Taler Wallet. We make no representations concerning any - Third Party Content contained in or accessed through our Services.</paragraph> - </list_item> - </enumerated_list> - <paragraph>Any other terms, conditions, warranties, or representations associated with - such content, are solely between you and such organizations and/or - individuals.</paragraph> - </section> - <section ids="limitation-of-liability" names="limitation\ of\ liability"> - <title>Limitation of liability</title> - <paragraph>To the fullest extent permitted by applicable law, in no event will we or any - of our officers, directors, representatives, agents, servants, counsel, - employees, consultants, lawyers, and other personnel authorized to act, - acting, or purporting to act on our behalf (collectively the “Taler Parties”) - be liable to you under contract, tort, strict liability, negligence, or any - other legal or equitable theory, for:</paragraph> - <enumerated_list enumtype="loweralpha" prefix="(" suffix=")"> - <list_item> - <paragraph>any lost profits, data loss, cost of procurement of substitute goods or - services, or direct, indirect, incidental, special, punitive, compensatory, - or consequential damages of any kind whatsoever resulting from:</paragraph> - </list_item> - </enumerated_list> - <block_quote> - <enumerated_list enumtype="lowerroman" prefix="(" suffix=")"> - <list_item> - <paragraph>your use of, or conduct in connection with, our services;</paragraph> - </list_item> - <list_item> - <paragraph>any unauthorized use of your wallet and/or private key due to your - failure to maintain the confidentiality of your wallet;</paragraph> - </list_item> - <list_item> - <paragraph>any interruption or cessation of transmission to or from the services; or</paragraph> - </list_item> - <list_item> - <paragraph>any bugs, viruses, trojan horses, or the like that are found in the Taler - Wallet software or that may be transmitted to or through our services by - any third party (regardless of the source of origination), or</paragraph> - </list_item> - </enumerated_list> - </block_quote> - <enumerated_list enumtype="loweralpha" prefix="(" start="2" suffix=")"> - <list_item> - <paragraph>any direct damages.</paragraph> - </list_item> - </enumerated_list> - <paragraph>These limitations apply regardless of legal theory, whether based on tort, - strict liability, breach of contract, breach of warranty, or any other legal - theory, and whether or not we were advised of the possibility of such - damages. Some jurisdictions do not allow the exclusion or limitation of - liability for consequential or incidental damages, so the above limitation may - not apply to you.</paragraph> - </section> - <section ids="warranty-disclaimer" names="warranty\ disclaimer"> - <title>Warranty disclaimer</title> - <paragraph>Our services are provided “as is” and without warranty of any kind. To the - maximum extent permitted by law, we disclaim all representations and - warranties, express or implied, relating to the services and underlying - software or any content on the services, whether provided or owned by us or by - any third party, including without limitation, warranties of merchantability, - fitness for a particular purpose, title, non-infringement, freedom from - computer virus, and any implied warranties arising from course of dealing, - course of performance, or usage in trade, all of which are expressly - disclaimed. In addition, we do not represent or warrant that the content - accessible via the services is accurate, complete, available, current, free of - viruses or other harmful components, or that the results of using the services - will meet your requirements. Some states do not allow the disclaimer of - implied warranties, so the foregoing disclaimers may not apply to you. This - paragraph gives you specific legal rights and you may also have other legal - rights that vary from state to state.</paragraph> - </section> - <section ids="indemnity" names="indemnity"> - <title>Indemnity</title> - <paragraph>To the extent permitted by applicable law, you agree to defend, indemnify, and - hold harmless the Taler Parties from and against any and all claims, damages, - obligations, losses, liabilities, costs or debt, and expenses (including, but - not limited to, attorney’s fees) arising from: (a) your use of and access to - the Services; (b) any feedback or submissions you provide to us concerning the - Taler Wallet; (c) your violation of any term of this Agreement; or (d) your - violation of any law, rule, or regulation, or the rights of any third party.</paragraph> - </section> - <section ids="time-limitation-on-claims" names="time\ limitation\ on\ claims"> - <title>Time limitation on claims</title> - <paragraph>You agree that any claim you may have arising out of or related to your - relationship with us must be filed within one year after such claim arises, - otherwise, your claim in permanently barred.</paragraph> - </section> - <section ids="governing-law" names="governing\ law"> - <title>Governing law</title> - <paragraph>No matter where you’re located, the laws of Switzerland will govern these - Terms. If any provisions of these Terms are inconsistent with any applicable - law, those provisions will be superseded or modified only to the extent such - provisions are inconsistent. The parties agree to submit to the ordinary - courts in Zurich, Switzerland for exclusive jurisdiction of any dispute - arising out of or related to your use of the Services or your breach of these - Terms.</paragraph> - </section> - <section ids="termination" names="termination"> - <title>Termination</title> - <paragraph>In the event of termination concerning your use of our Services, your - obligations under this Agreement will still continue.</paragraph> - </section> - <section ids="discontinuance-of-services" names="discontinuance\ of\ services"> - <title>Discontinuance of services</title> - <paragraph>We may, in our sole discretion and without cost to you, with or without prior - notice, and at any time, modify or discontinue, temporarily or permanently, - any portion of our Services. We will use the Taler protocol’s provisions to - notify Wallets if our Services are to be discontinued. It is your - responsibility to ensure that the Taler Wallet is online at least once every - three months to observe these notifications. We shall not be held responsible - or liable for any loss of funds in the event that we discontinue or depreciate - the Services and your Taler Wallet fails to transfer out the coins within a - three months notification period.</paragraph> - </section> - <section ids="no-waiver" names="no\ waiver"> - <title>No waiver</title> - <paragraph>Our failure to exercise or delay in exercising any right, power, or privilege - under this Agreement shall not operate as a waiver; nor shall any single or - partial exercise of any right, power, or privilege preclude any other or - further exercise thereof.</paragraph> - </section> - <section ids="severability" names="severability"> - <title>Severability</title> - <paragraph>If it turns out that any part of this Agreement is invalid, void, or for any - reason unenforceable, that term will be deemed severable and limited or - eliminated to the minimum extent necessary.</paragraph> - </section> - <section ids="force-majeure" names="force\ majeure"> - <title>Force majeure</title> - <paragraph>We shall not be held liable for any delays, failure in performance, or - interruptions of service which result directly or indirectly from any cause or - condition beyond our reasonable control, including but not limited to: any - delay or failure due to any act of God, act of civil or military authorities, - act of terrorism, civil disturbance, war, strike or other labor dispute, fire, - interruption in telecommunications or Internet services or network provider - services, failure of equipment and/or software, other catastrophe, or any - other occurrence which is beyond our reasonable control and shall not affect - the validity and enforceability of any remaining provisions.</paragraph> - </section> - <section ids="assignment" names="assignment"> - <title>Assignment</title> - <paragraph>You agree that we may assign any of our rights and/or transfer, sub-contract, - or delegate any of our obligations under these Terms.</paragraph> - </section> - <section ids="entire-agreement" names="entire\ agreement"> - <title>Entire agreement</title> - <paragraph>This Agreement sets forth the entire understanding and agreement as to the - subject matter hereof and supersedes any and all prior discussions, - agreements, and understandings of any kind (including, without limitation, any - prior versions of this Agreement) and every nature between us. Except as - provided for above, any modification to this Agreement must be in writing and - must be signed by both parties.</paragraph> - </section> - <section ids="questions-or-comments" names="questions\ or\ comments"> - <title>Questions or comments</title> - <paragraph>We welcome comments, questions, concerns, or suggestions. Please send us a - message on our contact page at <reference refuri="mailto:legal@taler-systems.com">legal@taler-systems.com</reference>.</paragraph> - </section> - </section> -</document> -`; - export const 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: "", }, }); diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx index 8258717bd..4ebbe11c6 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx @@ -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; -} diff --git a/packages/taler-wallet-webextension/src/cta/termsExample.ts b/packages/taler-wallet-webextension/src/cta/termsExample.ts new file mode 100644 index 000000000..d42e49c86 --- /dev/null +++ b/packages/taler-wallet-webextension/src/cta/termsExample.ts @@ -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 — 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 Wallet’s self-hosted personal payment +application. When using the Taler Wallet to interact with our +Services, you are agreeing to our Terms, so please read carefully. + + +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 GPL’s 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, attorney’s fees) +arising from: (a) your use of and access to the Services; (b) any +feedback or submissions you provide to us concerning the Taler Wallet; +(c) your violation of any term of this Agreement; or (d) your +violation of any law, rule, or regulation, or the rights of any third +party. + + +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 you’re located, the laws of Switzerland will govern +these Terms. If any provisions of these Terms are inconsistent with +any applicable law, those provisions will be superseded or modified +only to the extent such provisions are inconsistent. The parties agree +to submit to the ordinary courts in Zurich, Switzerland for exclusive +jurisdiction of any dispute arising out of or related to your use of +the Services or your breach of these Terms. + + +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 protocol’s provisions to notify Wallets if our Services are +to be discontinued. It is your responsibility to ensure that the Taler +Wallet is online at least once every three months to observe these +notifications. We shall not be held responsible or liable for any loss +of funds in the event that we discontinue or depreciate the Services +and your Taler Wallet fails to transfer out the coins within a three +months notification period. + + +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 + Wallet’s self-hosted personal payment application. When using the Taler Wallet + to interact with our Services, you are agreeing to our Terms, so please read + carefully.</paragraph> + <section ids="highlights" names="highlights:"> + <title>Highlights:</title> + <block_quote> + <bullet_list bullet="•"> + <list_item> + <paragraph>You are responsible for keeping the data in your Taler Wallet at all times + under your control. Any losses arising from you not being in control of + your private information are your problem.</paragraph> + </list_item> + <list_item> + <paragraph>We will try to transfer funds we hold in escrow for our users to any legal + recipient to the best of our ability within the limitations of the law and + our implementation. However, the Services offered today are highly + experimental and the set of recipients of funds is severely restricted.</paragraph> + </list_item> + <list_item> + <paragraph>For our Services, we may charge transaction fees. The specific fee structure + is provided based on the Taler protocol and should be shown to you when you + withdraw electronic coins using a Taler Wallet. You agree and understand + that the Taler protocol allows for the fee structure to change.</paragraph> + </list_item> + <list_item> + <paragraph>You agree to not intentionally overwhelm our systems with requests and + follow responsible disclosure if you find security issues in our services.</paragraph> + </list_item> + <list_item> + <paragraph>We cannot be held accountable for our Services not being available due to + circumstances beyond our control. If we modify or terminate our services, + we will try to give you the opportunity to recover your funds. However, + given the experimental state of the Services today, this may not be + possible. You are strongly advised to limit your use of the Service + to small-scale experiments expecting total loss of all funds.</paragraph> + </list_item> + </bullet_list> + </block_quote> + <paragraph>These terms outline approved uses of our Services. The Services and these + Terms are still at an experimental stage. If you have any questions or + comments related to this Agreement, please send us a message to + <reference refuri="mailto:legal@taler-systems.com">legal@taler-systems.com</reference>. If you do not agree to this Agreement, you must not + use our Services.</paragraph> + </section> + </section> + <section ids="how-you-accept-this-policy" names="how\ you\ accept\ this\ policy"> + <title>How you accept this policy</title> + <paragraph>By sending funds to us (to top-up your Taler Wallet), you acknowledge that you + have read, understood, and agreed to these Terms. We reserve the right to + change these Terms at any time. If you disagree with the change, we may in the + future offer you with an easy option to recover your unspent funds. However, + in the current experimental period you acknowledge that this feature is not + yet available, resulting in your funds being lost unless you accept the new + Terms. If you continue to use our Services other than to recover your unspent + funds, your continued use of our Services following any such change will + signify your acceptance to be bound by the then current Terms. Please check + the effective date above to determine if there have been any changes since you + have last reviewed these Terms.</paragraph> + </section> + <section ids="services" names="services"> + <title>Services</title> + <paragraph>We will try to transfer funds that we hold in escrow for our users to any + legal recipient to the best of our ability and within the limitations of the + law and our implementation. However, the Services offered today are highly + experimental and the set of recipients of funds is severely restricted. The + Taler Wallet can be loaded by exchanging fiat currencies against electronic + coins. We are providing this exchange service. Once your Taler Wallet is + loaded with electronic coins they can be spent for purchases if the seller is + accepting Taler as a means of payment. We are not guaranteeing that any seller + is accepting Taler at all or a particular seller. The seller or recipient of + deposits of electronic coins must specify the target account, as per the + design of the Taler protocol. They are responsible for following the protocol + and specifying the correct bank account, and are solely liable for any losses + that may arise from specifying the wrong account. We will allow the government + to link wire transfers to the underlying contract hash. It is the + responsibility of recipients to preserve the full contracts and to pay + whatever taxes and charges may be applicable. Technical issues may lead to + situations where we are unable to make transfers at all or lead to incorrect + transfers that cannot be reversed. We will only refuse to execute transfers if + the transfers are prohibited by a competent legal authority and we are ordered + to do so.</paragraph> + </section> + <section ids="fees" names="fees"> + <title>Fees</title> + <paragraph>You agree to pay the fees for exchanges and withdrawals completed via the + Taler Wallet (“Fees”) as defined by us, which we may change from time to + time. With the exception of wire transfer fees, Taler transaction fees are set + for any electronic coin at the time of withdrawal and fixed throughout the + validity period of the respective electronic coin. Your wallet should obtain + and display applicable fees when withdrawing funds. Fees for coins obtained as + change may differ from the fees applicable to the original coin. Wire transfer + fees that are independent from electronic coins may change annually. You + authorize us to charge or deduct applicable fees owed in connection with + deposits, exchanges and withdrawals following the rules of the Taler protocol. + We reserve the right to provide different types of rewards to users either in + the form of discount for our Services or in any other form at our discretion + and without prior notice to you.</paragraph> + </section> + <section ids="eligibility" names="eligibility"> + <title>Eligibility</title> + <paragraph>To be eligible to use our Services, you must be able to form legally binding + contracts or have the permission of your legal guardian. By using our + Services, you represent and warrant that you meet all eligibility requirements + that we outline in these Terms.</paragraph> + </section> + <section ids="financial-self-responsibility" names="financial\ self-responsibility"> + <title>Financial self-responsibility</title> + <paragraph>You will be responsible for maintaining the availability, integrity and + confidentiality of the data stored in your wallet. When you setup a Taler + Wallet, you are strongly advised to follow the precautionary measures offered + by the software to minimize the chances to losse access to or control over + your Wallet data. We will not be liable for any loss or damage arising from + your failure to comply with this paragraph.</paragraph> + </section> + <section ids="copyrights-and-trademarks" names="copyrights\ and\ trademarks"> + <title>Copyrights and trademarks</title> + <paragraph>The Taler Wallet is released under the terms of the GNU General Public License + (GNU GPL). You have the right to access, use, and share the Taler Wallet, in + modified or unmodified form. However, the GPL is a strong copyleft license, + which means that any derivative works must be distributed under the same + license terms as the original software. If you have any questions, you should + review the GNU GPL’s full terms and conditions at + <reference refuri="https://www.gnu.org/licenses/gpl-3.0.en.html">https://www.gnu.org/licenses/gpl-3.0.en.html</reference>. “Taler” itself is a trademark + of Taler Systems SA. You are welcome to use the name in relation to processing + payments using the Taler protocol, assuming your use is compatible with an + official release from the GNU Project that is not older than two years.</paragraph> + </section> + <section ids="your-use-of-our-services" names="your\ use\ of\ our\ services"> + <title>Your use of our services</title> + <paragraph>When using our Services, you agree to not take any action that intentionally + imposes an unreasonable load on our infrastructure. If you find security + problems in our Services, you agree to first report them to + <reference refuri="mailto:security@taler-systems.com">security@taler-systems.com</reference> and grant us the right to publish your report. We + warrant that we will ourselves publicly disclose any issues reported within 3 + months, and that we will not prosecute anyone reporting security issues if + they did not exploit the issue beyond a proof-of-concept, and followed the + above responsible disclosure practice.</paragraph> + </section> + <section ids="limitation-of-liability-disclaimer-of-warranties" names="limitation\ of\ liability\ &\ disclaimer\ of\ warranties"> + <title>Limitation of liability & disclaimer of warranties</title> + <paragraph>You understand and agree that we have no control over, and no duty to take any + action regarding: Failures, disruptions, errors, or delays in processing that + you may experience while using our Services; The risk of failure of hardware, + software, and Internet connections; The risk of malicious software being + introduced or found in the software underlying the Taler Wallet; The risk that + third parties may obtain unauthorized access to information stored within your + Taler Wallet, including, but not limited to your Taler Wallet coins or backup + encryption keys. You release us from all liability related to any losses, + damages, or claims arising from:</paragraph> + <enumerated_list enumtype="loweralpha" prefix="(" suffix=")"> + <list_item> + <paragraph>user error such as forgotten passwords, incorrectly constructed + transactions;</paragraph> + </list_item> + <list_item> + <paragraph>server failure or data loss;</paragraph> + </list_item> + <list_item> + <paragraph>unauthorized access to the Taler Wallet application;</paragraph> + </list_item> + <list_item> + <paragraph>bugs or other errors in the Taler Wallet software; and</paragraph> + </list_item> + <list_item> + <paragraph>any unauthorized third party activities, including, but not limited to, + the use of viruses, phishing, brute forcing, or other means of attack + against the Taler Wallet. We make no representations concerning any + Third Party Content contained in or accessed through our Services.</paragraph> + </list_item> + </enumerated_list> + <paragraph>Any other terms, conditions, warranties, or representations associated with + such content, are solely between you and such organizations and/or + individuals.</paragraph> + </section> + <section ids="limitation-of-liability" names="limitation\ of\ liability"> + <title>Limitation of liability</title> + <paragraph>To the fullest extent permitted by applicable law, in no event will we or any + of our officers, directors, representatives, agents, servants, counsel, + employees, consultants, lawyers, and other personnel authorized to act, + acting, or purporting to act on our behalf (collectively the “Taler Parties”) + be liable to you under contract, tort, strict liability, negligence, or any + other legal or equitable theory, for:</paragraph> + <enumerated_list enumtype="loweralpha" prefix="(" suffix=")"> + <list_item> + <paragraph>any lost profits, data loss, cost of procurement of substitute goods or + services, or direct, indirect, incidental, special, punitive, compensatory, + or consequential damages of any kind whatsoever resulting from:</paragraph> + </list_item> + </enumerated_list> + <block_quote> + <enumerated_list enumtype="lowerroman" prefix="(" suffix=")"> + <list_item> + <paragraph>your use of, or conduct in connection with, our services;</paragraph> + </list_item> + <list_item> + <paragraph>any unauthorized use of your wallet and/or private key due to your + failure to maintain the confidentiality of your wallet;</paragraph> + </list_item> + <list_item> + <paragraph>any interruption or cessation of transmission to or from the services; or</paragraph> + </list_item> + <list_item> + <paragraph>any bugs, viruses, trojan horses, or the like that are found in the Taler + Wallet software or that may be transmitted to or through our services by + any third party (regardless of the source of origination), or</paragraph> + </list_item> + </enumerated_list> + </block_quote> + <enumerated_list enumtype="loweralpha" prefix="(" start="2" suffix=")"> + <list_item> + <paragraph>any direct damages.</paragraph> + </list_item> + </enumerated_list> + <paragraph>These limitations apply regardless of legal theory, whether based on tort, + strict liability, breach of contract, breach of warranty, or any other legal + theory, and whether or not we were advised of the possibility of such + damages. Some jurisdictions do not allow the exclusion or limitation of + liability for consequential or incidental damages, so the above limitation may + not apply to you.</paragraph> + </section> + <section ids="warranty-disclaimer" names="warranty\ disclaimer"> + <title>Warranty disclaimer</title> + <paragraph>Our services are provided “as is” and without warranty of any kind. To the + maximum extent permitted by law, we disclaim all representations and + warranties, express or implied, relating to the services and underlying + software or any content on the services, whether provided or owned by us or by + any third party, including without limitation, warranties of merchantability, + fitness for a particular purpose, title, non-infringement, freedom from + computer virus, and any implied warranties arising from course of dealing, + course of performance, or usage in trade, all of which are expressly + disclaimed. In addition, we do not represent or warrant that the content + accessible via the services is accurate, complete, available, current, free of + viruses or other harmful components, or that the results of using the services + will meet your requirements. Some states do not allow the disclaimer of + implied warranties, so the foregoing disclaimers may not apply to you. This + paragraph gives you specific legal rights and you may also have other legal + rights that vary from state to state.</paragraph> + </section> + <section ids="indemnity" names="indemnity"> + <title>Indemnity</title> + <paragraph>To the extent permitted by applicable law, you agree to defend, indemnify, and + hold harmless the Taler Parties from and against any and all claims, damages, + obligations, losses, liabilities, costs or debt, and expenses (including, but + not limited to, attorney’s fees) arising from: (a) your use of and access to + the Services; (b) any feedback or submissions you provide to us concerning the + Taler Wallet; (c) your violation of any term of this Agreement; or (d) your + violation of any law, rule, or regulation, or the rights of any third party.</paragraph> + </section> + <section ids="time-limitation-on-claims" names="time\ limitation\ on\ claims"> + <title>Time limitation on claims</title> + <paragraph>You agree that any claim you may have arising out of or related to your + relationship with us must be filed within one year after such claim arises, + otherwise, your claim in permanently barred.</paragraph> + </section> + <section ids="governing-law" names="governing\ law"> + <title>Governing law</title> + <paragraph>No matter where you’re located, the laws of Switzerland will govern these + Terms. If any provisions of these Terms are inconsistent with any applicable + law, those provisions will be superseded or modified only to the extent such + provisions are inconsistent. The parties agree to submit to the ordinary + courts in Zurich, Switzerland for exclusive jurisdiction of any dispute + arising out of or related to your use of the Services or your breach of these + Terms.</paragraph> + </section> + <section ids="termination" names="termination"> + <title>Termination</title> + <paragraph>In the event of termination concerning your use of our Services, your + obligations under this Agreement will still continue.</paragraph> + </section> + <section ids="discontinuance-of-services" names="discontinuance\ of\ services"> + <title>Discontinuance of services</title> + <paragraph>We may, in our sole discretion and without cost to you, with or without prior + notice, and at any time, modify or discontinue, temporarily or permanently, + any portion of our Services. We will use the Taler protocol’s provisions to + notify Wallets if our Services are to be discontinued. It is your + responsibility to ensure that the Taler Wallet is online at least once every + three months to observe these notifications. We shall not be held responsible + or liable for any loss of funds in the event that we discontinue or depreciate + the Services and your Taler Wallet fails to transfer out the coins within a + three months notification period.</paragraph> + </section> + <section ids="no-waiver" names="no\ waiver"> + <title>No waiver</title> + <paragraph>Our failure to exercise or delay in exercising any right, power, or privilege + under this Agreement shall not operate as a waiver; nor shall any single or + partial exercise of any right, power, or privilege preclude any other or + further exercise thereof.</paragraph> + </section> + <section ids="severability" names="severability"> + <title>Severability</title> + <paragraph>If it turns out that any part of this Agreement is invalid, void, or for any + reason unenforceable, that term will be deemed severable and limited or + eliminated to the minimum extent necessary.</paragraph> + </section> + <section ids="force-majeure" names="force\ majeure"> + <title>Force majeure</title> + <paragraph>We shall not be held liable for any delays, failure in performance, or + interruptions of service which result directly or indirectly from any cause or + condition beyond our reasonable control, including but not limited to: any + delay or failure due to any act of God, act of civil or military authorities, + act of terrorism, civil disturbance, war, strike or other labor dispute, fire, + interruption in telecommunications or Internet services or network provider + services, failure of equipment and/or software, other catastrophe, or any + other occurrence which is beyond our reasonable control and shall not affect + the validity and enforceability of any remaining provisions.</paragraph> + </section> + <section ids="assignment" names="assignment"> + <title>Assignment</title> + <paragraph>You agree that we may assign any of our rights and/or transfer, sub-contract, + or delegate any of our obligations under these Terms.</paragraph> + </section> + <section ids="entire-agreement" names="entire\ agreement"> + <title>Entire agreement</title> + <paragraph>This Agreement sets forth the entire understanding and agreement as to the + subject matter hereof and supersedes any and all prior discussions, + agreements, and understandings of any kind (including, without limitation, any + prior versions of this Agreement) and every nature between us. Except as + provided for above, any modification to this Agreement must be in writing and + must be signed by both parties.</paragraph> + </section> + <section ids="questions-or-comments" names="questions\ or\ comments"> + <title>Questions or comments</title> + <paragraph>We welcome comments, questions, concerns, or suggestions. Please send us a + message on our contact page at <reference refuri="mailto:legal@taler-systems.com">legal@taler-systems.com</reference>.</paragraph> + </section> + </section> +</document> +`; + +export const 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 +`; + diff --git a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx index 008f30cb6..33164783d 100644 --- a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx +++ b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx @@ -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> ); } diff --git a/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx b/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx index ae8e54ba1..069157475 100644 --- a/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx +++ b/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx @@ -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(), }); diff --git a/packages/taler-wallet-webextension/src/popup/Settings.tsx b/packages/taler-wallet-webextension/src/popup/Settings.tsx index 0a3f777d5..84ecea4fe 100644 --- a/packages/taler-wallet-webextension/src/popup/Settings.tsx +++ b/packages/taler-wallet-webextension/src/popup/Settings.tsx @@ -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, @@ -92,45 +51,6 @@ export function SettingsView({ <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> <Checkbox diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx index d0c79f6d4..c6c872f21 100644 --- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx +++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx @@ -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> diff --git a/packages/taler-wallet-webextension/src/utils/index.ts b/packages/taler-wallet-webextension/src/utils/index.ts new file mode 100644 index 000000000..477818520 --- /dev/null +++ b/packages/taler-wallet-webextension/src/utils/index.ts @@ -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}`; +} + diff --git a/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx b/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx index 04d79a5ea..0a8910646 100644 --- a/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx +++ b/packages/taler-wallet-webextension/src/wallet/BalancePage.tsx @@ -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> ); } diff --git a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx index 1bceabd20..554952795 100644 --- a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx +++ b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx @@ -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> diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeAddConfirm.stories.tsx b/packages/taler-wallet-webextension/src/wallet/ExchangeAddConfirm.stories.tsx new file mode 100644 index 000000000..2e034458a --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeAddConfirm.stories.tsx @@ -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, +}); diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeAddConfirm.tsx b/packages/taler-wallet-webextension/src/wallet/ExchangeAddConfirm.tsx new file mode 100644 index 000000000..5c7f94ecd --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeAddConfirm.tsx @@ -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> + ); +} diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx b/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx new file mode 100644 index 000000000..10449c101 --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeAddPage.tsx @@ -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(); + }} + /> + ); +} diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeAddSetUrl.stories.tsx b/packages/taler-wallet-webextension/src/wallet/ExchangeAddSetUrl.stories.tsx new file mode 100644 index 000000000..bc182cb70 --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeAddSetUrl.stories.tsx @@ -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, +}); diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx b/packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx new file mode 100644 index 000000000..e87a8894f --- /dev/null +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSetUrl.tsx @@ -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> + ); +} diff --git a/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx b/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx index 41852e38c..16f239674 100644 --- a/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx +++ b/packages/taler-wallet-webextension/src/wallet/ProviderAddPage.tsx @@ -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 }); }) diff --git a/packages/taler-wallet-webextension/src/wallet/ReserveCreated.tsx b/packages/taler-wallet-webextension/src/wallet/ReserveCreated.tsx index 075126dc8..f009c5ad0 100644 --- a/packages/taler-wallet-webextension/src/wallet/ReserveCreated.tsx +++ b/packages/taler-wallet-webextension/src/wallet/ReserveCreated.tsx @@ -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} diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.tsx b/packages/taler-wallet-webextension/src/wallet/Settings.tsx index 586d7b53e..5f1cd89d3 100644 --- a/packages/taler-wallet-webextension/src/wallet/Settings.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Settings.tsx @@ -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> diff --git a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx index a17550ff9..73000c9ae 100644 --- a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx +++ b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx @@ -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 { @@ -132,6 +133,14 @@ function Application(): VNode { /> <Route + path={Pages.exchange_add} + component={withLogoAndNavBar(ExchangeAddPage)} + onBack={() => { + route(Pages.balance); + }} + /> + + <Route path={Pages.manual_withdraw} component={withLogoAndNavBar(ManualWithdrawPage)} /> |