aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/headless/integrationtest.ts18
-rw-r--r--src/wallet.ts195
-rw-r--r--src/walletTypes.ts23
-rw-r--r--src/webex/messages.ts5
-rw-r--r--src/webex/pages/pay.tsx2
-rw-r--r--src/webex/wxApi.ts14
-rw-r--r--src/webex/wxBackend.ts6
7 files changed, 94 insertions, 169 deletions
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<PreparePayResult> {
- 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<PreparePayResult> {
+ 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<CheckPayResult> {
- 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<ReserveRecord>(
diff --git a/src/walletTypes.ts b/src/walletTypes.ts
index 47360c660..82024bb41 100644
--- a/src/walletTypes.ts
+++ b/src/walletTypes.ts
@@ -221,14 +221,6 @@ export function mkAmount(
}
/**
- * Possible results for checkPay.
- */
-export interface CheckPayResult {
- status: "paid" | "payment-possible" | "insufficient-balance";
- coinSelection?: CoinSelectionResult;
-}
-
-/**
* Result for confirmPay
*/
export interface ConfirmPayResult {
@@ -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";
@@ -218,13 +211,6 @@ export function payback(coinPub: string): Promise<void> {
}
/**
- * Check if payment is possible or already done.
- */
-export function checkPay(proposalId: number): Promise<CheckPayResult> {
- return callBackend("check-pay", { proposalId });
-}
-
-/**
* Pay for a proposal.
*/
export function confirmPay(proposalId: number, sessionId: string | undefined): Promise<ConfirmPayResult> {
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" });