diff options
author | Florian Dold <florian.dold@gmail.com> | 2017-08-30 17:08:54 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2017-08-30 17:08:54 +0200 |
commit | 008926b18470e7f394cd640302957b29728a9803 (patch) | |
tree | 45f914f5117116bb3af5010f9e7570e99b015952 /src/webex | |
parent | 24e021fef360448caf11ab5a489b570102e66f6f (diff) |
compute full fees for refresh and spending
Diffstat (limited to 'src/webex')
-rw-r--r-- | src/webex/messages.ts | 6 | ||||
-rw-r--r-- | src/webex/pages/confirm-contract.html | 1 | ||||
-rw-r--r-- | src/webex/pages/confirm-contract.tsx | 43 | ||||
-rw-r--r-- | src/webex/pages/refund.tsx | 17 | ||||
-rw-r--r-- | src/webex/renderHtml.tsx | 32 | ||||
-rw-r--r-- | src/webex/wxApi.ts | 5 | ||||
-rw-r--r-- | src/webex/wxBackend.ts | 2 |
7 files changed, 54 insertions, 52 deletions
diff --git a/src/webex/messages.ts b/src/webex/messages.ts index 7de28b9e9..122bd8fe2 100644 --- a/src/webex/messages.ts +++ b/src/webex/messages.ts @@ -191,7 +191,11 @@ export interface MessageMap { "get-purchase": { request: any; response: void; - } + }; + "get-full-refund-fees": { + request: { refundPermissions: types.RefundPermission[] }; + response: void; + }; } /** diff --git a/src/webex/pages/confirm-contract.html b/src/webex/pages/confirm-contract.html index 394de582a..223d413d8 100644 --- a/src/webex/pages/confirm-contract.html +++ b/src/webex/pages/confirm-contract.html @@ -5,6 +5,7 @@ <meta charset="UTF-8"> <title>Taler Wallet: Confirm Reserve Creation</title> + <link rel="stylesheet" type="text/css" href="../style/pure.css"> <link rel="stylesheet" type="text/css" href="../style/wallet.css"> <link rel="icon" href="/img/icon.png"> diff --git a/src/webex/pages/confirm-contract.tsx b/src/webex/pages/confirm-contract.tsx index fa71b1028..5436cb5a6 100644 --- a/src/webex/pages/confirm-contract.tsx +++ b/src/webex/pages/confirm-contract.tsx @@ -25,12 +25,13 @@ */ import * as i18n from "../../i18n"; import { + CheckPayResult, ContractTerms, ExchangeRecord, ProposalRecord, } from "../../types"; -import { renderContractTerms } from "../renderHtml"; +import { renderAmount } from "../renderHtml"; import * as wxApi from "../wxApi"; import * as React from "react"; @@ -113,6 +114,7 @@ interface ContractPromptState { * when pressing pay. */ holdCheck: boolean; + payStatus?: CheckPayResult; } class ContractPrompt extends React.Component<ContractPromptProps, ContractPromptState> { @@ -150,7 +152,7 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt return; } const payStatus = await wxApi.checkPay(this.props.proposalId); - if (payStatus === "insufficient-balance") { + if (payStatus.status === "insufficient-balance") { const msgInsufficient = i18n.str`You have insufficient funds of the requested currency in your wallet.`; // tslint:disable-next-line:max-line-length const msgNoMatch = i18n.str`You do not have any funds from an exchange that is accepted by this merchant. None of the exchanges accepted by the merchant is known to your wallet.`; @@ -166,10 +168,10 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt this.setState({error: msgInsufficient}); } this.setState({payDisabled: true}); - } else if (payStatus === "paid") { - this.setState({alreadyPaid: true, payDisabled: false, error: null}); + } else if (payStatus.status === "paid") { + this.setState({alreadyPaid: true, payDisabled: false, error: null, payStatus}); } else { - this.setState({payDisabled: false, error: null}); + this.setState({payDisabled: false, error: null, payStatus}); } } @@ -189,7 +191,7 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt document.location.href = proposal.contractTerms.fulfillment_url; break; } - this.setState({holdCheck: false}); + this.setState({holdCheck: true}); } @@ -198,15 +200,36 @@ class ContractPrompt extends React.Component<ContractPromptProps, ContractPrompt return <span>...</span>; } const c = this.state.proposal.contractTerms; + let merchantName; + if (c.merchant && c.merchant.name) { + merchantName = <strong>{c.merchant.name}</strong>; + } else { + merchantName = <strong>(pub: {c.merchant_pub})</strong>; + } + const amount = <strong>{renderAmount(c.amount)}</strong>; + console.log("payStatus", this.state.payStatus); return ( <div> <div> - {renderContractTerms(c)} + <i18n.Translate wrap="p"> + The merchant <span>{merchantName}</span> {" "} + offers you to purchase: + </i18n.Translate> + <ul> + {c.products.map( + (p: any, i: number) => (<li key={i}>{p.description}: {renderAmount(p.price)}</li>)) + } + </ul> + {(this.state.payStatus && this.state.payStatus.coinSelection) ? + <p>The total price is <span>{amount}</span> (plus <span>{renderAmount(this.state.payStatus.coinSelection.totalFees)}</span> fees).</p> + : + <p>The total price is <span>{amount}</span>.</p> + } </div> - <button onClick={() => this.doPayment()} + <button className="pure-button button-success" disabled={this.state.payDisabled} - className="accept"> - Confirm payment + onClick={() => this.doPayment()}> + {i18n.str`Confirm payment`} </button> <div> {(this.state.alreadyPaid ? <p className="okaybox">You already paid for this, clicking "Confirm payment" will not cost money again.</p> : <p />)} diff --git a/src/webex/pages/refund.tsx b/src/webex/pages/refund.tsx index b9506bf29..d2c21c2f4 100644 --- a/src/webex/pages/refund.tsx +++ b/src/webex/pages/refund.tsx @@ -37,11 +37,12 @@ interface RefundStatusViewProps { interface RefundStatusViewState { purchase?: types.PurchaseRecord; + refundFees?: types.AmountJson; gotResult: boolean; } -const RefundDetail = ({purchase}: {purchase: types.PurchaseRecord}) => { +const RefundDetail = ({purchase, fullRefundFees}: {purchase: types.PurchaseRecord, fullRefundFees: types.AmountJson}) => { const pendingKeys = Object.keys(purchase.refundsPending); const doneKeys = Object.keys(purchase.refundsDone); if (pendingKeys.length == 0 && doneKeys.length == 0) { @@ -54,22 +55,18 @@ const RefundDetail = ({purchase}: {purchase: types.PurchaseRecord}) => { } let amountPending = types.Amounts.getZero(currency); - let feesPending = types.Amounts.getZero(currency) for (let k of pendingKeys) { amountPending = types.Amounts.add(amountPending, purchase.refundsPending[k].refund_amount).amount; - feesPending = types.Amounts.add(feesPending, purchase.refundsPending[k].refund_fee).amount; } let amountDone = types.Amounts.getZero(currency); - let feesDone = types.Amounts.getZero(currency); for (let k of doneKeys) { amountDone = types.Amounts.add(amountDone, purchase.refundsDone[k].refund_amount).amount; - feesDone = types.Amounts.add(feesDone, purchase.refundsDone[k].refund_fee).amount; } return ( <div> - <p>Refund fully received: <AmountDisplay amount={amountDone} /> (refund fees: <AmountDisplay amount={feesDone} />)</p> - <p>Refund incoming: <AmountDisplay amount={amountPending} /> (refund fees: <AmountDisplay amount={feesPending} />)</p> + <p>Refund fully received: <AmountDisplay amount={amountDone} /> (refund fees: <AmountDisplay amount={fullRefundFees} />)</p> + <p>Refund incoming: <AmountDisplay amount={amountPending} /></p> </div> ); }; @@ -108,7 +105,7 @@ class RefundStatusView extends React.Component<RefundStatusViewProps, RefundStat <h1>Refund Status</h1> <p>Status of purchase <strong>{summary}</strong> from merchant <strong>{merchantName}</strong> (order id {purchase.contractTerms.order_id}).</p> <p>Total amount: <AmountDisplay amount={purchase.contractTerms.amount} /></p> - {purchase.finished ? <RefundDetail purchase={purchase} /> : <p>Purchase not completed.</p>} + {purchase.finished ? <RefundDetail purchase={purchase} fullRefundFees={this.state.refundFees!} /> : <p>Purchase not completed.</p>} </div> ); } @@ -116,7 +113,9 @@ class RefundStatusView extends React.Component<RefundStatusViewProps, RefundStat async update() { const purchase = await wxApi.getPurchase(this.props.contractTermsHash); console.log("got purchase", purchase); - this.setState({ purchase, gotResult: true }); + const refundsDone = Object.keys(purchase.refundsDone).map((x) => purchase.refundsDone[x]); + const refundFees = await wxApi.getFullRefundFees( {refundPermissions: refundsDone }); + this.setState({ purchase, gotResult: true, refundFees }); } } diff --git a/src/webex/renderHtml.tsx b/src/webex/renderHtml.tsx index 2a5b50533..d26f726af 100644 --- a/src/webex/renderHtml.tsx +++ b/src/webex/renderHtml.tsx @@ -24,45 +24,13 @@ /** * Imports. */ -import { amountToPretty } from "../helpers"; -import * as i18n from "../i18n"; import { AmountJson, Amounts, - ContractTerms, } from "../types"; import * as React from "react"; -/** - * Render contract terms for the end user to view. - */ -export function renderContractTerms(contractTerms: ContractTerms): JSX.Element { - let merchantName; - if (contractTerms.merchant && contractTerms.merchant.name) { - merchantName = <strong>{contractTerms.merchant.name}</strong>; - } else { - merchantName = <strong>(pub: {contractTerms.merchant_pub})</strong>; - } - const amount = <strong>{amountToPretty(contractTerms.amount)}</strong>; - - return ( - <div> - <i18n.Translate wrap="p"> - The merchant <span>{merchantName}</span> - wants to enter a contract over <span>{amount}</span>{" "} - with you. - </i18n.Translate> - <p>{i18n.str`You are about to purchase:`}</p> - <ul> - {contractTerms.products.map( - (p: any, i: number) => (<li key={i}>{`${p.description}: ${amountToPretty(p.price)}`}</li>)) - } - </ul> - </div> - ); -} - /** * Render amount as HTML, which non-breaking space between diff --git a/src/webex/wxApi.ts b/src/webex/wxApi.ts index 1423da53b..096d855e0 100644 --- a/src/webex/wxApi.ts +++ b/src/webex/wxApi.ts @@ -33,6 +33,7 @@ import { PreCoinRecord, PurchaseRecord, QueryPaymentResult, + RefundPermission, ReserveCreationInfo, ReserveRecord, SenderWireInfos, @@ -345,3 +346,7 @@ export function acceptRefund(refundData: any): Promise<number> { export function getPurchase(contractTermsHash: string): Promise<PurchaseRecord> { return callBackend("get-purchase", { contractTermsHash }); } + +export function getFullRefundFees(args: { refundPermissions: RefundPermission[] }): Promise<AmountJson> { + return callBackend("get-full-refund-fees", { refundPermissions: args.refundPermissions }); +} diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts index db2ffbfbd..16da3d97d 100644 --- a/src/webex/wxBackend.ts +++ b/src/webex/wxBackend.ts @@ -323,6 +323,8 @@ function handleMessage(sender: MessageSender, throw Error("contractTermsHash missing"); } return needsWallet().getPurchase(contractTermsHash); + case "get-full-refund-fees": + return needsWallet().getFullRefundFees(detail.refundPermissions); default: // Exhaustiveness check. // See https://www.typescriptlang.org/docs/handbook/advanced-types.html |