fold checkPay into preparePay
This commit is contained in:
parent
51aa6d8146
commit
9297bbc825
@ -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);
|
||||
if (preparePayResult.status != "payment-possible") {
|
||||
throw Error("payment not possible");
|
||||
}
|
||||
|
||||
console.log("check pay result", checkPayResult);
|
||||
|
||||
const confirmPayResult = await myWallet.confirmPay(proposalId, undefined);
|
||||
const confirmPayResult = await myWallet.confirmPay(preparePayResult.proposalId, undefined);
|
||||
|
||||
console.log("confirmPayResult", confirmPayResult);
|
||||
|
||||
|
195
src/wallet.ts
195
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>(
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
@ -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<void> {
|
||||
return callBackend("payback-coin", { coinPub });
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if payment is possible or already done.
|
||||
*/
|
||||
export function checkPay(proposalId: number): Promise<CheckPayResult> {
|
||||
return callBackend("check-pay", { proposalId });
|
||||
}
|
||||
|
||||
/**
|
||||
* Pay for a proposal.
|
||||
*/
|
||||
|
@ -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" });
|
||||
|
Loading…
Reference in New Issue
Block a user