From 9297bbc8253650a2530afc3fd88c9bd102de0793 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 6 Sep 2019 09:48:00 +0200 Subject: fold checkPay into preparePay --- src/headless/integrationtest.ts | 18 ++-- src/wallet.ts | 195 ++++++++++++++++------------------------ src/walletTypes.ts | 23 ++--- src/webex/messages.ts | 5 -- src/webex/pages/pay.tsx | 2 +- src/webex/wxApi.ts | 14 --- src/webex/wxBackend.ts | 6 -- 7 files changed, 94 insertions(+), 169 deletions(-) (limited to 'src') diff --git a/src/headless/integrationtest.ts b/src/headless/integrationtest.ts index 3e60d418a..a692cabd0 100644 --- a/src/headless/integrationtest.ts +++ b/src/headless/integrationtest.ts @@ -58,20 +58,20 @@ export async function runIntegrationTest(args: { console.log("payment status", paymentStatus); - const contractUrl = paymentStatus.contract_url; - if (!contractUrl) { - throw Error("no contract URL in payment response"); + const talerPayUri = paymentStatus.taler_pay_uri; + if (!talerPayUri) { + throw Error("no taler://pay/ URI in payment response"); } - const proposalId = await myWallet.downloadProposal(contractUrl); + const preparePayResult = await myWallet.preparePay(talerPayUri); - console.log("proposal id", proposalId); + console.log("prepare pay result", preparePayResult); - const checkPayResult = await myWallet.checkPay(proposalId); - - console.log("check pay result", checkPayResult); + if (preparePayResult.status != "payment-possible") { + throw Error("payment not possible"); + } - const confirmPayResult = await myWallet.confirmPay(proposalId, undefined); + const confirmPayResult = await myWallet.confirmPay(preparePayResult.proposalId, undefined); console.log("confirmPayResult", confirmPayResult); diff --git a/src/wallet.ts b/src/wallet.ts index 45bab48f8..ca829e3fa 100644 --- a/src/wallet.ts +++ b/src/wallet.ts @@ -85,7 +85,6 @@ import { import { Badge, BenchmarkResult, - CheckPayResult, CoinSelectionResult, CoinWithDenom, ConfirmPayResult, @@ -734,8 +733,15 @@ export class Wallet { return fu.href(); } - async preparePay(url: string): Promise { - const uriResult = parsePayUri(url); + + /** + * Check if a payment for the given taler://pay/ URI is possible. + * + * If the payment is possible, the signature are already generated but not + * yet send to the merchant. + */ + async preparePay(talerPayUri: string): Promise { + const uriResult = parsePayUri(talerPayUri); if (!uriResult) { return { @@ -745,13 +751,11 @@ export class Wallet { } let proposalId: number; - let checkResult: CheckPayResult; try { proposalId = await this.downloadProposal( uriResult.downloadUrl, uriResult.sessionId, ); - checkResult = await this.checkPay(proposalId); } catch (e) { return { status: "error", @@ -765,50 +769,84 @@ export class Wallet { console.log("proposal", proposal); - if (uriResult.sessionId) { - const existingPayment = await this.q().getIndexed( - Stores.purchases.fulfillmentUrlIndex, - proposal.contractTerms.fulfillment_url, - ); - if (existingPayment) { - console.log("existing payment", existingPayment); - await this.submitPay( - existingPayment.contractTermsHash, - uriResult.sessionId, - ); + // First check if we already payed for it. + const purchase = await this.q().get( + Stores.purchases, + proposal.contractTermsHash, + ); + + if (!purchase) { + const paymentAmount = Amounts.parseOrThrow(proposal.contractTerms.amount); + let wireFeeLimit; + if (proposal.contractTerms.max_wire_fee) { + wireFeeLimit = Amounts.parseOrThrow(proposal.contractTerms.max_wire_fee); + } else { + wireFeeLimit = Amounts.getZero(paymentAmount.currency); + } + // If not already payed, check if we could pay for it. + const res = await this.getCoinsForPayment({ + allowedAuditors: proposal.contractTerms.auditors, + allowedExchanges: proposal.contractTerms.exchanges, + depositFeeLimit: Amounts.parseOrThrow(proposal.contractTerms.max_fee), + paymentAmount, + wireFeeAmortization: proposal.contractTerms.wire_fee_amortization || 1, + wireFeeLimit, + wireFeeTime: getTalerStampSec(proposal.contractTerms.timestamp) || 0, + wireMethod: proposal.contractTerms.wire_method, + }); + + if (!res) { + console.log("not confirming payment, insufficient coins"); return { - status: "paid", - contractTerms: existingPayment.contractTerms, - nextUrl: this.getNextUrl(existingPayment.contractTerms), + status: "insufficient-balance", + contractTerms: proposal.contractTerms, + proposalId: proposal.id!, }; } - } - if (checkResult.status === "paid") { - const nextUrl = this.getNextUrl(proposal.contractTerms); - return { - status: "paid", - contractTerms: proposal.contractTerms, - proposalId: proposal.id!, - nextUrl, - }; - } - if (checkResult.status === "insufficient-balance") { - return { - status: "insufficient-balance", - contractTerms: proposal.contractTerms, - proposalId: proposal.id!, - }; - } - if (checkResult.status === "payment-possible") { + // Only create speculative signature if we don't already have one for this proposal + if ( + !this.speculativePayData || + (this.speculativePayData && + this.speculativePayData.proposalId !== proposalId) + ) { + const { exchangeUrl, cds, totalAmount } = res; + const payCoinInfo = await this.cryptoApi.signDeposit( + proposal.contractTerms, + cds, + totalAmount, + ); + this.speculativePayData = { + exchangeUrl, + payCoinInfo, + proposal, + proposalId, + }; + Wallet.enableTracing && + console.log("created speculative pay data for payment"); + } + return { status: "payment-possible", contractTerms: proposal.contractTerms, proposalId: proposal.id!, - totalFees: checkResult.coinSelection!.totalFees, + totalFees: res.totalFees, }; } - throw Error("not reached"); + + if (uriResult.sessionId) { + await this.submitPay( + purchase.contractTermsHash, + uriResult.sessionId, + ); + } + + return { + status: "paid", + contractTerms: proposal.contractTerms, + proposalId: proposal.id!, + nextUrl: this.getNextUrl(purchase.contractTerms), + }; } /** @@ -1088,85 +1126,6 @@ export class Wallet { return sp; } - /** - * Check if payment for an offer is possible, or if the offer has already - * been payed for. - * - * Also speculatively computes the signature for the payment to make the payment - * look faster to the user. - */ - async checkPay(proposalId: number): Promise { - const proposal = await this.q().get(Stores.proposals, proposalId); - - if (!proposal) { - throw Error(`proposal with id ${proposalId} not found`); - } - - // First check if we already payed for it. - const purchase = await this.q().get( - Stores.purchases, - proposal.contractTermsHash, - ); - if (purchase) { - Wallet.enableTracing && console.log("got purchase", purchase); - return { status: "paid" }; - } - - const paymentAmount = Amounts.parseOrThrow(proposal.contractTerms.amount); - - Wallet.enableTracing && - console.log( - `checking if payment of ${JSON.stringify(paymentAmount)} is possible`, - ); - - let wireFeeLimit; - if (proposal.contractTerms.max_wire_fee) { - wireFeeLimit = Amounts.parseOrThrow(proposal.contractTerms.max_wire_fee); - } else { - wireFeeLimit = Amounts.getZero(paymentAmount.currency); - } - - // If not already payed, check if we could pay for it. - const res = await this.getCoinsForPayment({ - allowedAuditors: proposal.contractTerms.auditors, - allowedExchanges: proposal.contractTerms.exchanges, - depositFeeLimit: Amounts.parseOrThrow(proposal.contractTerms.max_fee), - paymentAmount, - wireFeeAmortization: proposal.contractTerms.wire_fee_amortization || 1, - wireFeeLimit, - wireFeeTime: getTalerStampSec(proposal.contractTerms.timestamp) || 0, - wireMethod: proposal.contractTerms.wire_method, - }); - - if (!res) { - console.log("not confirming payment, insufficient coins"); - return { status: "insufficient-balance" }; - } - - // Only create speculative signature if we don't already have one for this proposal - if ( - !this.speculativePayData || - (this.speculativePayData && - this.speculativePayData.proposalId !== proposalId) - ) { - const { exchangeUrl, cds, totalAmount } = res; - const payCoinInfo = await this.cryptoApi.signDeposit( - proposal.contractTerms, - cds, - totalAmount, - ); - this.speculativePayData = { - exchangeUrl, - payCoinInfo, - proposal, - proposalId, - }; - Wallet.enableTracing && - console.log("created speculative pay data for payment"); - } - - return { status: "payment-possible", coinSelection: res }; - } private async sendReserveInfoToBank(reservePub: string) { const reserve = await this.q().get( diff --git a/src/walletTypes.ts b/src/walletTypes.ts index 47360c660..82024bb41 100644 --- a/src/walletTypes.ts +++ b/src/walletTypes.ts @@ -220,14 +220,6 @@ export function mkAmount( return { value, fraction, currency }; } -/** - * Possible results for checkPay. - */ -export interface CheckPayResult { - status: "paid" | "payment-possible" | "insufficient-balance"; - coinSelection?: CoinSelectionResult; -} - /** * Result for confirmPay */ @@ -463,16 +455,15 @@ export type PreparePayResult = export interface PreparePayResultPaymentPossible { status: "payment-possible"; - proposalId?: number; - contractTerms?: ContractTerms; - totalFees?: AmountJson; + proposalId: number; + contractTerms: ContractTerms; + totalFees: AmountJson; } export interface PreparePayResultInsufficientBalance { status: "insufficient-balance"; - proposalId?: number; - contractTerms?: ContractTerms; - totalFees?: AmountJson; + proposalId: number; + contractTerms: ContractTerms; } export interface PreparePayResultError { @@ -482,8 +473,8 @@ export interface PreparePayResultError { export interface PreparePayResultPaid { status: "paid"; - proposalId?: number; - contractTerms?: ContractTerms; + proposalId: number; + contractTerms: ContractTerms; nextUrl: string; } diff --git a/src/webex/messages.ts b/src/webex/messages.ts index 27d85a1f3..78a1a1fd0 100644 --- a/src/webex/messages.ts +++ b/src/webex/messages.ts @@ -69,10 +69,6 @@ export interface MessageMap { request: { proposalId: number; sessionId?: string }; response: walletTypes.ConfirmPayResult; }; - "check-pay": { - request: { proposalId: number }; - response: walletTypes.CheckPayResult; - }; "exchange-info": { request: { baseUrl: string }; response: dbTypes.ExchangeRecord; @@ -205,7 +201,6 @@ export interface MessageMap { request: { talerPayUri: string }; response: walletTypes.PreparePayResult; }; - "get-diagnostics": { request: { }; response: walletTypes.WalletDiagnostics; diff --git a/src/webex/pages/pay.tsx b/src/webex/pages/pay.tsx index c266f6d48..9041f5d1c 100644 --- a/src/webex/pages/pay.tsx +++ b/src/webex/pages/pay.tsx @@ -24,7 +24,7 @@ */ import * as i18n from "../../i18n"; -import { CheckPayResult, PreparePayResult } from "../../walletTypes"; +import { PreparePayResult } from "../../walletTypes"; import { renderAmount, ProgressButton, registerMountPage } from "../renderHtml"; import * as wxApi from "../wxApi"; diff --git a/src/webex/wxApi.ts b/src/webex/wxApi.ts index 61dc2ca69..65c14ac48 100644 --- a/src/webex/wxApi.ts +++ b/src/webex/wxApi.ts @@ -29,13 +29,10 @@ import { DenominationRecord, ExchangeRecord, PreCoinRecord, - ProposalDownloadRecord, - PurchaseRecord, ReserveRecord, } from "../dbTypes"; import { BenchmarkResult, - CheckPayResult, ConfirmPayResult, ReserveCreationInfo, SenderWireInfos, @@ -45,10 +42,6 @@ import { WalletDiagnostics, } from "../walletTypes"; -import { - MerchantRefundPermission, -} from "../talerTypes"; - import { MessageMap, MessageType } from "./messages"; @@ -217,13 +210,6 @@ export function payback(coinPub: string): Promise { return callBackend("payback-coin", { coinPub }); } -/** - * Check if payment is possible or already done. - */ -export function checkPay(proposalId: number): Promise { - return callBackend("check-pay", { proposalId }); -} - /** * Pay for a proposal. */ diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts index 0cfaf2346..564ee24f0 100644 --- a/src/webex/wxBackend.ts +++ b/src/webex/wxBackend.ts @@ -132,12 +132,6 @@ async function handleMessage( detail.sessionId, ); } - case "check-pay": { - if (typeof detail.proposalId !== "number") { - throw Error("proposalId must be number"); - } - return needsWallet().checkPay(detail.proposalId); - } case "exchange-info": { if (!detail.baseUrl) { return Promise.resolve({ error: "bad url" }); -- cgit v1.2.3